1/*-
2 * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved.
3 * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
4 * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * a) Redistributions of source code must retain the above copyright notice,
10 *    this list of conditions and the following disclaimer.
11 *
12 * b) Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in
14 *    the documentation and/or other materials provided with the distribution.
15 *
16 * c) Neither the name of Cisco Systems, Inc. nor the names of its
17 *    contributors may be used to endorse or promote products derived
18 *    from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30 * THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#ifdef __FreeBSD__
34#include <sys/cdefs.h>
35__FBSDID("$FreeBSD: head/sys/netinet/sctp_usrreq.c 263237 2014-03-16 12:32:16Z tuexen $");
36#endif
37
38#include <netinet/sctp_os.h>
39#ifdef __FreeBSD__
40#include <sys/proc.h>
41#endif
42#include <netinet/sctp_pcb.h>
43#include <netinet/sctp_header.h>
44#include <netinet/sctp_var.h>
45#ifdef INET6
46#if defined(__Userspace_os_FreeBSD)
47#include <netinet6/sctp6_var.h>
48#endif
49#endif
50#include <netinet/sctp_sysctl.h>
51#include <netinet/sctp_output.h>
52#include <netinet/sctp_uio.h>
53#include <netinet/sctp_asconf.h>
54#include <netinet/sctputil.h>
55#include <netinet/sctp_indata.h>
56#include <netinet/sctp_timer.h>
57#include <netinet/sctp_auth.h>
58#include <netinet/sctp_bsd_addr.h>
59#if !defined(__Userspace_os_Windows)
60#include <netinet/udp.h>
61#endif
62
63#if defined(HAVE_SCTP_PEELOFF_SOCKOPT)
64#include <netinet/sctp_peeloff.h>
65#endif				/* HAVE_SCTP_PEELOFF_SOCKOPT */
66
67#if defined(__APPLE__)
68#define APPLE_FILE_NO 7
69#endif
70
71extern struct sctp_cc_functions sctp_cc_functions[];
72extern struct sctp_ss_functions sctp_ss_functions[];
73
74void
75#if defined(__Userspace__)
76sctp_init(uint16_t port,
77          int (*conn_output)(void *addr, void *buffer, size_t length, uint8_t tos, uint8_t set_df),
78          void (*debug_printf)(const char *format, ...))
79#elif defined(__APPLE__) && (!defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) &&!defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION))
80sctp_init(struct protosw *pp SCTP_UNUSED, struct domain *dp SCTP_UNUSED)
81#else
82sctp_init(void)
83#endif
84{
85#if !defined(__Panda__) && !defined(__Userspace__)
86	u_long sb_max_adj;
87
88#endif
89#if defined(__Userspace__)
90#if defined(__Userspace_os_Windows)
91#if defined(INET) || defined(INET6)
92	WSADATA wsaData;
93
94	if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
95		SCTP_PRINTF("WSAStartup failed\n");
96		exit (-1);
97	}
98#endif
99	InitializeConditionVariable(&accept_cond);
100	InitializeCriticalSection(&accept_mtx);
101#else
102	pthread_cond_init(&accept_cond, NULL);
103	pthread_mutex_init(&accept_mtx, NULL);
104#endif
105#endif
106	/* Initialize and modify the sysctled variables */
107	sctp_init_sysctls();
108#if defined(__Userspace__)
109#if defined(__Userspace_os_Windows)
110	srand((unsigned int)time(NULL));
111#else
112	srandom(getpid()); /* so inp->sctp_ep.random_numbers are truly random... */
113#endif
114#endif
115#if defined(__Panda__)
116	sctp_sendspace = SB_MAX;
117	sctp_recvspace = SB_MAX;
118
119#elif defined(__Userspace__)
120	SCTP_BASE_SYSCTL(sctp_sendspace) = SB_MAX;
121	SCTP_BASE_SYSCTL(sctp_recvspace) = SB_RAW;
122	SCTP_BASE_SYSCTL(sctp_udp_tunneling_port) = port;
123#else
124#if !defined(__APPLE__)
125	if ((nmbclusters / 8) > SCTP_ASOC_MAX_CHUNKS_ON_QUEUE)
126		SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue) = (nmbclusters / 8);
127#endif
128	/*
129	 * Allow a user to take no more than 1/2 the number of clusters or
130	 * the SB_MAX whichever is smaller for the send window.
131	 */
132#if defined(__APPLE__)
133	sb_max_adj = (u_long)((u_quad_t) (sb_max) * MCLBYTES / (MSIZE + MCLBYTES));
134#else
135	sb_max_adj = (u_long)((u_quad_t) (SB_MAX) * MCLBYTES / (MSIZE + MCLBYTES));
136#endif
137#if defined(__APPLE__)
138	SCTP_BASE_SYSCTL(sctp_sendspace) = sb_max_adj;
139#else
140	SCTP_BASE_SYSCTL(sctp_sendspace) = min(sb_max_adj,
141	    (((uint32_t)nmbclusters / 2) * SCTP_DEFAULT_MAXSEGMENT));
142#endif
143	/*
144	 * Now for the recv window, should we take the same amount? or
145	 * should I do 1/2 the SB_MAX instead in the SB_MAX min above. For
146	 * now I will just copy.
147	 */
148	SCTP_BASE_SYSCTL(sctp_recvspace) = SCTP_BASE_SYSCTL(sctp_sendspace);
149#endif
150	SCTP_BASE_VAR(first_time) = 0;
151	SCTP_BASE_VAR(sctp_pcb_initialized) = 0;
152#if defined(__Userspace__)
153#if !defined(__Userspace_os_Windows)
154#if defined(INET) || defined(INET6)
155	SCTP_BASE_VAR(userspace_route) = -1;
156#endif
157#endif
158#ifdef INET
159	SCTP_BASE_VAR(userspace_rawsctp) = -1;
160	SCTP_BASE_VAR(userspace_udpsctp) = -1;
161#endif
162#ifdef INET6
163	SCTP_BASE_VAR(userspace_rawsctp6) = -1;
164	SCTP_BASE_VAR(userspace_udpsctp6) = -1;
165#endif
166	SCTP_BASE_VAR(timer_thread_should_exit) = 0;
167	SCTP_BASE_VAR(conn_output) = conn_output;
168	SCTP_BASE_VAR(debug_printf) = debug_printf;
169#endif
170	sctp_pcb_init();
171#if defined(__Userspace__)
172	sctp_start_timer();
173#endif
174#if defined(SCTP_PACKET_LOGGING)
175	SCTP_BASE_VAR(packet_log_writers) = 0;
176	SCTP_BASE_VAR(packet_log_end) = 0;
177	bzero(&SCTP_BASE_VAR(packet_log_buffer), SCTP_PACKET_LOG_SIZE);
178#endif
179#if defined(__APPLE__)
180	SCTP_BASE_VAR(sctp_main_timer_ticks) = 0;
181	sctp_start_main_timer();
182	timeout(sctp_delayed_startup, NULL, 1);
183#endif
184}
185
186void
187sctp_finish(void)
188{
189#if defined(__APPLE__)
190	untimeout(sctp_delayed_startup, NULL);
191	sctp_over_udp_stop();
192	sctp_address_monitor_stop();
193	sctp_stop_main_timer();
194#endif
195#if defined(__Userspace__)
196#if defined(INET) || defined(INET6)
197	recv_thread_destroy();
198#endif
199#if !defined(__Userspace_os_Windows)
200#if defined(INET) || defined(INET6)
201	if (SCTP_BASE_VAR(userspace_route) != -1) {
202		pthread_join(SCTP_BASE_VAR(recvthreadroute), NULL);
203	}
204#endif
205#endif
206#ifdef INET
207	if (SCTP_BASE_VAR(userspace_rawsctp) != -1) {
208#if defined(__Userspace_os_Windows)
209		WaitForSingleObject(SCTP_BASE_VAR(recvthreadraw), INFINITE);
210		CloseHandle(SCTP_BASE_VAR(recvthreadraw));
211#else
212		pthread_join(SCTP_BASE_VAR(recvthreadraw), NULL);
213#endif
214	}
215	if (SCTP_BASE_VAR(userspace_udpsctp) != -1) {
216#if defined(__Userspace_os_Windows)
217		WaitForSingleObject(SCTP_BASE_VAR(recvthreadudp), INFINITE);
218		CloseHandle(SCTP_BASE_VAR(recvthreadudp));
219#else
220		pthread_join(SCTP_BASE_VAR(recvthreadudp), NULL);
221#endif
222	}
223#endif
224#ifdef INET6
225	if (SCTP_BASE_VAR(userspace_rawsctp6) != -1) {
226#if defined(__Userspace_os_Windows)
227		WaitForSingleObject(SCTP_BASE_VAR(recvthreadraw6), INFINITE);
228		CloseHandle(SCTP_BASE_VAR(recvthreadraw6));
229#else
230		pthread_join(SCTP_BASE_VAR(recvthreadraw6), NULL);
231#endif
232	}
233	if (SCTP_BASE_VAR(userspace_udpsctp6) != -1) {
234#if defined(__Userspace_os_Windows)
235		WaitForSingleObject(SCTP_BASE_VAR(recvthreadudp6), INFINITE);
236		CloseHandle(SCTP_BASE_VAR(recvthreadudp6));
237#else
238		pthread_join(SCTP_BASE_VAR(recvthreadudp6), NULL);
239#endif
240	}
241#endif
242	SCTP_BASE_VAR(timer_thread_should_exit) = 1;
243#if defined(__Userspace_os_Windows)
244	WaitForSingleObject(SCTP_BASE_VAR(timer_thread), INFINITE);
245	CloseHandle(SCTP_BASE_VAR(timer_thread));
246#else
247	pthread_join(SCTP_BASE_VAR(timer_thread), NULL);
248#endif
249#endif
250	sctp_pcb_finish();
251#if defined(__Userspace__)
252#if defined(__Userspace_os_Windows)
253	DeleteConditionVariable(&accept_cond);
254	DeleteCriticalSection(&accept_mtx);
255#else
256	pthread_cond_destroy(&accept_cond);
257	pthread_mutex_destroy(&accept_mtx);
258#endif
259#endif
260#if defined(__Windows__)
261	sctp_finish_sysctls();
262#if defined(INET) || defined(INET6)
263	WSACleanup();
264#endif
265#endif
266}
267
268
269
270void
271sctp_pathmtu_adjustment(struct sctp_tcb *stcb, uint16_t nxtsz)
272{
273	struct sctp_tmit_chunk *chk;
274	uint16_t overhead;
275
276	/* Adjust that too */
277	stcb->asoc.smallest_mtu = nxtsz;
278	/* now off to subtract IP_DF flag if needed */
279	overhead = IP_HDR_SIZE;
280	if (sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.peer_auth_chunks)) {
281		overhead += sctp_get_auth_chunk_len(stcb->asoc.peer_hmac_id);
282	}
283	TAILQ_FOREACH(chk, &stcb->asoc.send_queue, sctp_next) {
284		if ((chk->send_size + overhead) > nxtsz) {
285			chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
286		}
287	}
288	TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
289		if ((chk->send_size + overhead) > nxtsz) {
290			/*
291			 * For this guy we also mark for immediate resend
292			 * since we sent to big of chunk
293			 */
294			chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
295			if (chk->sent < SCTP_DATAGRAM_RESEND) {
296				sctp_flight_size_decrease(chk);
297				sctp_total_flight_decrease(stcb, chk);
298			}
299			if (chk->sent != SCTP_DATAGRAM_RESEND) {
300				sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
301			}
302			chk->sent = SCTP_DATAGRAM_RESEND;
303			chk->rec.data.doing_fast_retransmit = 0;
304			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) {
305				sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_PMTU,
306					       chk->whoTo->flight_size,
307					       chk->book_size,
308					       (uintptr_t)chk->whoTo,
309					       chk->rec.data.TSN_seq);
310			}
311			/* Clear any time so NO RTT is being done */
312			chk->do_rtt = 0;
313		}
314	}
315}
316
317#ifdef INET
318#if !defined(__Userspace__)
319#if defined(__Panda__) || defined(__Windows__)
320void
321#else
322static void
323#endif
324sctp_notify_mbuf(struct sctp_inpcb *inp,
325    struct sctp_tcb *stcb,
326    struct sctp_nets *net,
327    struct ip *ip,
328    struct sctphdr *sh)
329{
330	struct icmp *icmph;
331	int totsz, tmr_stopped = 0;
332	uint16_t nxtsz;
333
334	/* protection */
335	if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
336	    (ip == NULL) || (sh == NULL)) {
337		if (stcb != NULL) {
338			SCTP_TCB_UNLOCK(stcb);
339		}
340		return;
341	}
342	/* First job is to verify the vtag matches what I would send */
343	if (ntohl(sh->v_tag) != (stcb->asoc.peer_vtag)) {
344		SCTP_TCB_UNLOCK(stcb);
345		return;
346	}
347	icmph = (struct icmp *)((caddr_t)ip - (sizeof(struct icmp) -
348	    sizeof(struct ip)));
349	if (icmph->icmp_type != ICMP_UNREACH) {
350		/* We only care about unreachable */
351		SCTP_TCB_UNLOCK(stcb);
352		return;
353	}
354	if (icmph->icmp_code != ICMP_UNREACH_NEEDFRAG) {
355		/* not a unreachable message due to frag. */
356		SCTP_TCB_UNLOCK(stcb);
357		return;
358	}
359#if defined(__FreeBSD__) && __FreeBSD_version >= 1000000
360	totsz = ntohs(ip->ip_len);
361#else
362	totsz = ip->ip_len;
363#endif
364
365	nxtsz = ntohs(icmph->icmp_nextmtu);
366	if (nxtsz == 0) {
367		/*
368		 * old type router that does not tell us what the next size
369		 * mtu is. Rats we will have to guess (in a educated fashion
370		 * of course)
371		 */
372		nxtsz = sctp_get_prev_mtu(totsz);
373	}
374	/* Stop any PMTU timer */
375	if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
376		tmr_stopped = 1;
377		sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
378				SCTP_FROM_SCTP_USRREQ+SCTP_LOC_1);
379	}
380	/* Adjust destination size limit */
381	if (net->mtu > nxtsz) {
382		net->mtu = nxtsz;
383		if (net->port) {
384			net->mtu -= sizeof(struct udphdr);
385		}
386	}
387	/* now what about the ep? */
388	if (stcb->asoc.smallest_mtu > nxtsz) {
389		sctp_pathmtu_adjustment(stcb, nxtsz);
390	}
391	if (tmr_stopped)
392		sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
393
394	SCTP_TCB_UNLOCK(stcb);
395}
396#endif
397#endif
398
399void
400sctp_notify(struct sctp_inpcb *inp,
401    struct ip *ip,
402    struct sctphdr *sh,
403    struct sockaddr *to,
404    struct sctp_tcb *stcb,
405    struct sctp_nets *net)
406{
407#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
408	struct socket *so;
409
410#endif
411	struct icmp *icmph;
412
413	/* protection */
414	if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
415	    (sh == NULL) || (to == NULL)) {
416		if (stcb)
417			SCTP_TCB_UNLOCK(stcb);
418		return;
419	}
420	/* First job is to verify the vtag matches what I would send */
421	if (ntohl(sh->v_tag) != (stcb->asoc.peer_vtag)) {
422		SCTP_TCB_UNLOCK(stcb);
423		return;
424	}
425
426	icmph = (struct icmp *)((caddr_t)ip - (sizeof(struct icmp) -
427					       sizeof(struct ip)));
428	if (icmph->icmp_type != ICMP_UNREACH) {
429		/* We only care about unreachable */
430		SCTP_TCB_UNLOCK(stcb);
431		return;
432	}
433	if ((icmph->icmp_code == ICMP_UNREACH_NET) ||
434	    (icmph->icmp_code == ICMP_UNREACH_HOST) ||
435	    (icmph->icmp_code == ICMP_UNREACH_NET_UNKNOWN) ||
436	    (icmph->icmp_code == ICMP_UNREACH_HOST_UNKNOWN) ||
437	    (icmph->icmp_code == ICMP_UNREACH_ISOLATED) ||
438	    (icmph->icmp_code == ICMP_UNREACH_NET_PROHIB) ||
439	    (icmph->icmp_code == ICMP_UNREACH_HOST_PROHIB) ||
440#if defined(__Panda__)
441	    (icmph->icmp_code == ICMP_UNREACH_ADMIN)) {
442#elif defined(__Userspace_os_NetBSD)
443	    (icmph->icmp_code == ICMP_UNREACH_ADMIN_PROHIBIT)) {
444#else
445	    (icmph->icmp_code == ICMP_UNREACH_FILTER_PROHIB)) {
446#endif
447
448		/*
449		 * Hmm reachablity problems we must examine closely. If its
450		 * not reachable, we may have lost a network. Or if there is
451		 * NO protocol at the other end named SCTP. well we consider
452		 * it a OOTB abort.
453		 */
454		if (net->dest_state & SCTP_ADDR_REACHABLE) {
455			/* Ok that destination is NOT reachable */
456			net->dest_state &= ~SCTP_ADDR_REACHABLE;
457			net->dest_state &= ~SCTP_ADDR_PF;
458			sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
459					stcb, 0,
460					(void *)net, SCTP_SO_NOT_LOCKED);
461		}
462		SCTP_TCB_UNLOCK(stcb);
463	} else  if ((icmph->icmp_code == ICMP_UNREACH_PROTOCOL) ||
464		    (icmph->icmp_code == ICMP_UNREACH_PORT)) {
465		/*
466		 * Here the peer is either playing tricks on us,
467		 * including an address that belongs to someone who
468		 * does not support SCTP OR was a userland
469		 * implementation that shutdown and now is dead. In
470		 * either case treat it like a OOTB abort with no
471		 * TCB
472		 */
473		sctp_abort_notification(stcb, 1, 0, NULL, SCTP_SO_NOT_LOCKED);
474#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
475		so = SCTP_INP_SO(inp);
476		atomic_add_int(&stcb->asoc.refcnt, 1);
477		SCTP_TCB_UNLOCK(stcb);
478		SCTP_SOCKET_LOCK(so, 1);
479		SCTP_TCB_LOCK(stcb);
480		atomic_subtract_int(&stcb->asoc.refcnt, 1);
481#endif
482		(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_2);
483#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
484		SCTP_SOCKET_UNLOCK(so, 1);
485		/* SCTP_TCB_UNLOCK(stcb); MT: I think this is not needed.*/
486#endif
487		/* no need to unlock here, since the TCB is gone */
488	} else {
489		SCTP_TCB_UNLOCK(stcb);
490	}
491}
492
493#ifdef INET
494#if !defined(__Panda__) && !defined(__Userspace__)
495#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
496void
497#else
498void *
499#endif
500sctp_ctlinput(cmd, sa, vip)
501	int cmd;
502	struct sockaddr *sa;
503	void *vip;
504{
505	struct ip *ip = vip;
506	struct sctphdr *sh;
507	uint32_t vrf_id;
508	/* FIX, for non-bsd is this right? */
509	vrf_id = SCTP_DEFAULT_VRFID;
510	if (sa->sa_family != AF_INET ||
511	    ((struct sockaddr_in *)sa)->sin_addr.s_addr == INADDR_ANY) {
512#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
513		return;
514#else
515		return (NULL);
516#endif
517	}
518	if (PRC_IS_REDIRECT(cmd)) {
519		ip = 0;
520	} else if ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0) {
521#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
522		return;
523#else
524		return (NULL);
525#endif
526	}
527	if (ip) {
528		struct sctp_inpcb *inp = NULL;
529		struct sctp_tcb *stcb = NULL;
530		struct sctp_nets *net = NULL;
531		struct sockaddr_in to, from;
532
533		sh = (struct sctphdr *)((caddr_t)ip + (ip->ip_hl << 2));
534		bzero(&to, sizeof(to));
535		bzero(&from, sizeof(from));
536		from.sin_family = to.sin_family = AF_INET;
537#ifdef HAVE_SIN_LEN
538		from.sin_len = to.sin_len = sizeof(to);
539#endif
540		from.sin_port = sh->src_port;
541		from.sin_addr = ip->ip_src;
542		to.sin_port = sh->dest_port;
543		to.sin_addr = ip->ip_dst;
544
545		/*
546		 * 'to' holds the dest of the packet that failed to be sent.
547		 * 'from' holds our local endpoint address. Thus we reverse
548		 * the to and the from in the lookup.
549		 */
550		stcb = sctp_findassociation_addr_sa((struct sockaddr *)&to,
551		    (struct sockaddr *)&from,
552		    &inp, &net, 1, vrf_id);
553		if (stcb != NULL && inp && (inp->sctp_socket != NULL)) {
554			if (cmd != PRC_MSGSIZE) {
555				sctp_notify(inp, ip, sh,
556				    (struct sockaddr *)&to, stcb,
557				    net);
558			} else {
559				/* handle possible ICMP size messages */
560				sctp_notify_mbuf(inp, stcb, net, ip, sh);
561			}
562		} else {
563#if defined(__FreeBSD__) && __FreeBSD_version < 500000
564			/*
565			 * XXX must be fixed for 5.x and higher, leave for
566			 * 4.x
567			 */
568			if (PRC_IS_REDIRECT(cmd) && inp) {
569				in_rtchange((struct inpcb *)inp,
570				    inetctlerrmap[cmd]);
571			}
572#endif
573			if ((stcb == NULL) && (inp != NULL)) {
574				/* reduce ref-count */
575				SCTP_INP_WLOCK(inp);
576				SCTP_INP_DECR_REF(inp);
577				SCTP_INP_WUNLOCK(inp);
578			}
579			if (stcb) {
580				SCTP_TCB_UNLOCK(stcb);
581			}
582		}
583	}
584#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
585	return;
586#else
587	return (NULL);
588#endif
589}
590#endif
591#endif
592
593#if defined(__FreeBSD__)
594static int
595sctp_getcred(SYSCTL_HANDLER_ARGS)
596{
597	struct xucred xuc;
598	struct sockaddr_in addrs[2];
599	struct sctp_inpcb *inp;
600	struct sctp_nets *net;
601	struct sctp_tcb *stcb;
602	int error;
603	uint32_t vrf_id;
604
605	/* FIX, for non-bsd is this right? */
606	vrf_id = SCTP_DEFAULT_VRFID;
607
608#if __FreeBSD_version > 602000
609	error = priv_check(req->td, PRIV_NETINET_GETCRED);
610
611#elif __FreeBSD_version >= 500000
612	error = suser(req->td);
613#else
614	error = suser(req->p);
615#endif
616	if (error)
617		return (error);
618
619	error = SYSCTL_IN(req, addrs, sizeof(addrs));
620	if (error)
621		return (error);
622
623	stcb = sctp_findassociation_addr_sa(sintosa(&addrs[1]),
624	    sintosa(&addrs[0]),
625	    &inp, &net, 1, vrf_id);
626	if (stcb == NULL || inp == NULL || inp->sctp_socket == NULL) {
627		if ((inp != NULL) && (stcb == NULL)) {
628			/* reduce ref-count */
629			SCTP_INP_WLOCK(inp);
630			SCTP_INP_DECR_REF(inp);
631			goto cred_can_cont;
632		}
633
634		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
635		error = ENOENT;
636		goto out;
637	}
638	SCTP_TCB_UNLOCK(stcb);
639	/* We use the write lock here, only
640	 * since in the error leg we need it.
641	 * If we used RLOCK, then we would have
642	 * to wlock/decr/unlock/rlock. Which
643	 * in theory could create a hole. Better
644	 * to use higher wlock.
645	 */
646	SCTP_INP_WLOCK(inp);
647 cred_can_cont:
648	error = cr_canseesocket(req->td->td_ucred, inp->sctp_socket);
649	if (error) {
650		SCTP_INP_WUNLOCK(inp);
651		goto out;
652	}
653	cru2x(inp->sctp_socket->so_cred, &xuc);
654	SCTP_INP_WUNLOCK(inp);
655	error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
656out:
657	return (error);
658}
659
660SYSCTL_PROC(_net_inet_sctp, OID_AUTO, getcred, CTLTYPE_OPAQUE | CTLFLAG_RW,
661    0, 0, sctp_getcred, "S,ucred", "Get the ucred of a SCTP connection");
662#endif				/* #if defined(__FreeBSD__) */
663
664
665#ifdef INET
666#if defined(__Panda__) || defined(__Windows__) || defined(__Userspace__)
667int
668#elif defined(__FreeBSD__) && __FreeBSD_version > 690000
669static void
670#else
671static int
672#endif
673sctp_abort(struct socket *so)
674{
675	struct sctp_inpcb *inp;
676	uint32_t flags;
677
678	inp = (struct sctp_inpcb *)so->so_pcb;
679	if (inp == NULL) {
680#if defined(__FreeBSD__) && __FreeBSD_version > 690000
681		return;
682#else
683		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
684		return (EINVAL);
685#endif
686	}
687
688 sctp_must_try_again:
689	flags = inp->sctp_flags;
690#ifdef SCTP_LOG_CLOSING
691	sctp_log_closing(inp, NULL, 17);
692#endif
693	if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
694	    (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
695#ifdef SCTP_LOG_CLOSING
696		sctp_log_closing(inp, NULL, 16);
697#endif
698		sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
699				SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
700		SOCK_LOCK(so);
701		SCTP_SB_CLEAR(so->so_snd);
702		/* same for the rcv ones, they are only
703		 * here for the accounting/select.
704		 */
705		SCTP_SB_CLEAR(so->so_rcv);
706
707#if defined(__APPLE__)
708		so->so_usecount--;
709#else
710		/* Now null out the reference, we are completely detached. */
711		so->so_pcb = NULL;
712#endif
713		SOCK_UNLOCK(so);
714	} else {
715		flags = inp->sctp_flags;
716		if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
717			goto sctp_must_try_again;
718		}
719	}
720#if defined(__FreeBSD__) && __FreeBSD_version > 690000
721	return;
722#else
723	return (0);
724#endif
725}
726
727#if defined(__Panda__) || defined(__Userspace__)
728int
729#else
730static int
731#endif
732#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
733sctp_attach(struct socket *so, int proto SCTP_UNUSED, struct thread *p SCTP_UNUSED)
734#elif defined(__Panda__) || defined(__Userspace__)
735sctp_attach(struct socket *so, int proto SCTP_UNUSED, uint32_t vrf_id)
736#elif defined(__Windows__)
737sctp_attach(struct socket *so, int proto SCTP_UNUSED, PKTHREAD p SCTP_UNUSED)
738#else
739sctp_attach(struct socket *so, int proto SCTP_UNUSED, struct proc *p SCTP_UNUSED)
740#endif
741{
742	struct sctp_inpcb *inp;
743	struct inpcb *ip_inp;
744	int error;
745#if !defined(__Panda__) && !defined(__Userspace__)
746	uint32_t vrf_id = SCTP_DEFAULT_VRFID;
747#endif
748#ifdef IPSEC
749	uint32_t flags;
750#endif
751
752	inp = (struct sctp_inpcb *)so->so_pcb;
753	if (inp != 0) {
754		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
755		return (EINVAL);
756	}
757	if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
758		error = SCTP_SORESERVE(so, SCTP_BASE_SYSCTL(sctp_sendspace), SCTP_BASE_SYSCTL(sctp_recvspace));
759		if (error) {
760			return (error);
761		}
762	}
763	error = sctp_inpcb_alloc(so, vrf_id);
764	if (error) {
765		return (error);
766	}
767	inp = (struct sctp_inpcb *)so->so_pcb;
768	SCTP_INP_WLOCK(inp);
769	inp->sctp_flags &= ~SCTP_PCB_FLAGS_BOUND_V6;	/* I'm not v6! */
770	ip_inp = &inp->ip_inp.inp;
771	ip_inp->inp_vflag |= INP_IPV4;
772	ip_inp->inp_ip_ttl = MODULE_GLOBAL(ip_defttl);
773#ifdef IPSEC
774#if !(defined(__APPLE__))
775	error = ipsec_init_policy(so, &ip_inp->inp_sp);
776#ifdef SCTP_LOG_CLOSING
777	sctp_log_closing(inp, NULL, 17);
778#endif
779	if (error != 0) {
780	try_again:
781		flags = inp->sctp_flags;
782		if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
783		    (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
784#ifdef SCTP_LOG_CLOSING
785			sctp_log_closing(inp, NULL, 15);
786#endif
787			SCTP_INP_WUNLOCK(inp);
788			sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
789					SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
790		} else {
791			flags = inp->sctp_flags;
792			if ((flags &  SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
793				goto try_again;
794			} else {
795				SCTP_INP_WUNLOCK(inp);
796			}
797		}
798		return (error);
799	}
800#endif
801#endif				/* IPSEC */
802	SCTP_INP_WUNLOCK(inp);
803	return (0);
804}
805
806#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
807static int
808sctp_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
809{
810#elif defined(__FreeBSD__) || defined(__APPLE__)
811static int
812sctp_bind(struct socket *so, struct sockaddr *addr, struct proc *p) {
813#elif defined(__Panda__) || defined(__Userspace__)
814int
815sctp_bind(struct socket *so, struct sockaddr *addr) {
816	void *p = NULL;
817#elif defined(__Windows__)
818static int
819sctp_bind(struct socket *so, struct sockaddr *addr, PKTHREAD p) {
820#else
821static int
822sctp_bind(struct socket *so, struct mbuf *nam, struct proc *p)
823{
824	struct sockaddr *addr = nam ? mtod(nam, struct sockaddr *): NULL;
825
826#endif
827	struct sctp_inpcb *inp;
828
829	inp = (struct sctp_inpcb *)so->so_pcb;
830	if (inp == NULL) {
831		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
832		return (EINVAL);
833	}
834	if (addr != NULL) {
835#ifdef HAVE_SA_LEN
836		if ((addr->sa_family != AF_INET) ||
837		    (addr->sa_len != sizeof(struct sockaddr_in))) {
838#else
839		if (addr->sa_family != AF_INET) {
840#endif
841			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
842			return (EINVAL);
843		}
844	}
845	return (sctp_inpcb_bind(so, addr, NULL, p));
846}
847
848#endif
849#if defined(__Userspace__)
850
851int
852sctpconn_attach(struct socket *so, int proto SCTP_UNUSED, uint32_t vrf_id)
853{
854	struct sctp_inpcb *inp;
855	struct inpcb *ip_inp;
856	int error;
857
858	inp = (struct sctp_inpcb *)so->so_pcb;
859	if (inp != NULL) {
860		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
861		return (EINVAL);
862	}
863	if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
864		error = SCTP_SORESERVE(so, SCTP_BASE_SYSCTL(sctp_sendspace), SCTP_BASE_SYSCTL(sctp_recvspace));
865		if (error) {
866			return (error);
867		}
868	}
869	error = sctp_inpcb_alloc(so, vrf_id);
870	if (error) {
871		return (error);
872	}
873	inp = (struct sctp_inpcb *)so->so_pcb;
874	SCTP_INP_WLOCK(inp);
875	inp->sctp_flags &= ~SCTP_PCB_FLAGS_BOUND_V6;
876	inp->sctp_flags |= SCTP_PCB_FLAGS_BOUND_CONN;
877	ip_inp = &inp->ip_inp.inp;
878	ip_inp->inp_vflag |= INP_CONN;
879	ip_inp->inp_ip_ttl = MODULE_GLOBAL(ip_defttl);
880	SCTP_INP_WUNLOCK(inp);
881	return (0);
882}
883
884int
885sctpconn_bind(struct socket *so, struct sockaddr *addr)
886{
887	struct sctp_inpcb *inp;
888
889	inp = (struct sctp_inpcb *)so->so_pcb;
890	if (inp == NULL) {
891		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
892		return (EINVAL);
893	}
894	if (addr != NULL) {
895#ifdef HAVE_SA_LEN
896		if ((addr->sa_family != AF_CONN) ||
897		    (addr->sa_len != sizeof(struct sockaddr_conn))) {
898#else
899		if (addr->sa_family != AF_CONN) {
900#endif
901			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
902			return (EINVAL);
903		}
904	}
905	return (sctp_inpcb_bind(so, addr, NULL, NULL));
906}
907
908#endif
909#if (defined(__FreeBSD__) && __FreeBSD_version > 690000) || defined(__Windows__) || defined(__Userspace__)
910void
911sctp_close(struct socket *so)
912{
913	struct sctp_inpcb *inp;
914	uint32_t flags;
915
916	inp = (struct sctp_inpcb *)so->so_pcb;
917	if (inp == NULL)
918		return;
919
920	/* Inform all the lower layer assoc that we
921	 * are done.
922	 */
923 sctp_must_try_again:
924	flags = inp->sctp_flags;
925#ifdef SCTP_LOG_CLOSING
926	sctp_log_closing(inp, NULL, 17);
927#endif
928	if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
929	    (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
930#if defined(__Userspace__)
931		if (((so->so_options & SCTP_SO_LINGER) && (so->so_linger == 0)) ||
932		    (so->so_rcv.sb_cc > 0)) {
933#else
934		if (((so->so_options & SO_LINGER) && (so->so_linger == 0)) ||
935		    (so->so_rcv.sb_cc > 0)) {
936#endif
937#ifdef SCTP_LOG_CLOSING
938			sctp_log_closing(inp, NULL, 13);
939#endif
940			sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
941					SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
942		} else {
943#ifdef SCTP_LOG_CLOSING
944			sctp_log_closing(inp, NULL, 14);
945#endif
946			sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_GRACEFUL_CLOSE,
947					SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
948		}
949		/* The socket is now detached, no matter what
950		 * the state of the SCTP association.
951		 */
952		SOCK_LOCK(so);
953		SCTP_SB_CLEAR(so->so_snd);
954		/* same for the rcv ones, they are only
955		 * here for the accounting/select.
956		 */
957		SCTP_SB_CLEAR(so->so_rcv);
958
959#if !defined(__APPLE__)
960		/* Now null out the reference, we are completely detached. */
961		so->so_pcb = NULL;
962#endif
963		SOCK_UNLOCK(so);
964	} else {
965		flags = inp->sctp_flags;
966		if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
967			goto sctp_must_try_again;
968		}
969	}
970	return;
971}
972
973#else
974
975
976int
977sctp_detach(struct socket *so)
978{
979	struct sctp_inpcb *inp;
980	uint32_t flags;
981
982	inp = (struct sctp_inpcb *)so->so_pcb;
983	if (inp == NULL) {
984#if defined(__FreeBSD__) && __FreeBSD_version > 690000
985		return;
986#else
987		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
988		return (EINVAL);
989#endif
990	}
991 sctp_must_try_again:
992	flags = inp->sctp_flags;
993#ifdef SCTP_LOG_CLOSING
994	sctp_log_closing(inp, NULL, 17);
995#endif
996	if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
997	    (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
998#if defined(__Userspace__)
999		if (((so->so_options & SCTP_SO_LINGER) && (so->so_linger == 0)) ||
1000		    (so->so_rcv.sb_cc > 0)) {
1001#else
1002		if (((so->so_options & SO_LINGER) && (so->so_linger == 0)) ||
1003		    (so->so_rcv.sb_cc > 0)) {
1004#endif
1005#ifdef SCTP_LOG_CLOSING
1006			sctp_log_closing(inp, NULL, 13);
1007#endif
1008			sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
1009					SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
1010		} else {
1011#ifdef SCTP_LOG_CLOSING
1012			sctp_log_closing(inp, NULL, 13);
1013#endif
1014			sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_GRACEFUL_CLOSE,
1015					SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
1016		}
1017		/* The socket is now detached, no matter what
1018		 * the state of the SCTP association.
1019		 */
1020		SCTP_SB_CLEAR(so->so_snd);
1021		/* same for the rcv ones, they are only
1022		 * here for the accounting/select.
1023		 */
1024		SCTP_SB_CLEAR(so->so_rcv);
1025#if !defined(__APPLE__)
1026		/* Now disconnect */
1027		so->so_pcb = NULL;
1028#endif
1029	} else {
1030		flags = inp->sctp_flags;
1031		if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
1032			goto sctp_must_try_again;
1033		}
1034	}
1035#if defined(__FreeBSD__) && __FreeBSD_version > 690000
1036	return;
1037#else
1038	return (0);
1039#endif
1040}
1041#endif
1042
1043#if defined(__Userspace__)
1044/* __Userspace__ is not calling sctp_sendm */
1045#endif
1046#if !(defined(__Panda__) || defined(__Windows__))
1047int
1048#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
1049sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
1050    struct mbuf *control, struct thread *p);
1051
1052#else
1053sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
1054    struct mbuf *control, struct proc *p);
1055
1056#endif
1057
1058int
1059#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
1060sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
1061    struct mbuf *control, struct thread *p)
1062{
1063#else
1064sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
1065    struct mbuf *control, struct proc *p)
1066{
1067#endif
1068	struct sctp_inpcb *inp;
1069	int error;
1070
1071	inp = (struct sctp_inpcb *)so->so_pcb;
1072	if (inp == NULL) {
1073		if (control) {
1074			sctp_m_freem(control);
1075			control = NULL;
1076		}
1077		SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1078		sctp_m_freem(m);
1079		return (EINVAL);
1080	}
1081	/* Got to have an to address if we are NOT a connected socket */
1082	if ((addr == NULL) &&
1083	    ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) ||
1084	    (inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE))) {
1085		goto connected_type;
1086	} else if (addr == NULL) {
1087		SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EDESTADDRREQ);
1088		error = EDESTADDRREQ;
1089		sctp_m_freem(m);
1090		if (control) {
1091			sctp_m_freem(control);
1092			control = NULL;
1093		}
1094		return (error);
1095	}
1096#ifdef INET6
1097	if (addr->sa_family != AF_INET) {
1098		/* must be a v4 address! */
1099		SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EDESTADDRREQ);
1100		sctp_m_freem(m);
1101		if (control) {
1102			sctp_m_freem(control);
1103			control = NULL;
1104		}
1105		error = EDESTADDRREQ;
1106		return (error);
1107	}
1108#endif				/* INET6 */
1109connected_type:
1110	/* now what about control */
1111	if (control) {
1112		if (inp->control) {
1113			SCTP_PRINTF("huh? control set?\n");
1114			sctp_m_freem(inp->control);
1115			inp->control = NULL;
1116		}
1117		inp->control = control;
1118	}
1119	/* Place the data */
1120	if (inp->pkt) {
1121		SCTP_BUF_NEXT(inp->pkt_last) = m;
1122		inp->pkt_last = m;
1123	} else {
1124		inp->pkt_last = inp->pkt = m;
1125	}
1126	if (
1127#if defined(__FreeBSD__) || defined(__APPLE__)
1128	/* FreeBSD uses a flag passed */
1129	    ((flags & PRUS_MORETOCOME) == 0)
1130#else
1131	    1			/* Open BSD does not have any "more to come"
1132				 * indication */
1133#endif
1134	    ) {
1135		/*
1136		 * note with the current version this code will only be used
1137		 * by OpenBSD-- NetBSD, FreeBSD, and MacOS have methods for
1138		 * re-defining sosend to use the sctp_sosend. One can
1139		 * optionally switch back to this code (by changing back the
1140		 * definitions) but this is not advisable. This code is used
1141		 * by FreeBSD when sending a file with sendfile() though.
1142		 */
1143		int ret;
1144
1145		ret = sctp_output(inp, inp->pkt, addr, inp->control, p, flags);
1146		inp->pkt = NULL;
1147		inp->control = NULL;
1148		return (ret);
1149	} else {
1150		return (0);
1151	}
1152}
1153#endif
1154
1155int
1156sctp_disconnect(struct socket *so)
1157{
1158	struct sctp_inpcb *inp;
1159
1160	inp = (struct sctp_inpcb *)so->so_pcb;
1161	if (inp == NULL) {
1162		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
1163		return (ENOTCONN);
1164	}
1165	SCTP_INP_RLOCK(inp);
1166	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1167	    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
1168		if (LIST_EMPTY(&inp->sctp_asoc_list)) {
1169			/* No connection */
1170			SCTP_INP_RUNLOCK(inp);
1171			return (0);
1172		} else {
1173			struct sctp_association *asoc;
1174			struct sctp_tcb *stcb;
1175
1176			stcb = LIST_FIRST(&inp->sctp_asoc_list);
1177			if (stcb == NULL) {
1178				SCTP_INP_RUNLOCK(inp);
1179				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1180				return (EINVAL);
1181			}
1182			SCTP_TCB_LOCK(stcb);
1183			asoc = &stcb->asoc;
1184			if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
1185				/* We are about to be freed, out of here */
1186				SCTP_TCB_UNLOCK(stcb);
1187				SCTP_INP_RUNLOCK(inp);
1188				return (0);
1189			}
1190#if defined(__Userspace__)
1191			if (((so->so_options & SCTP_SO_LINGER) &&
1192			     (so->so_linger == 0)) ||
1193			    (so->so_rcv.sb_cc > 0)) {
1194#else
1195			if (((so->so_options & SO_LINGER) &&
1196			     (so->so_linger == 0)) ||
1197			    (so->so_rcv.sb_cc > 0)) {
1198#endif
1199				if (SCTP_GET_STATE(asoc) !=
1200				    SCTP_STATE_COOKIE_WAIT) {
1201					/* Left with Data unread */
1202					struct mbuf *err;
1203
1204					err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), 0, M_NOWAIT, 1, MT_DATA);
1205					if (err) {
1206						/*
1207						 * Fill in the user
1208						 * initiated abort
1209						 */
1210						struct sctp_paramhdr *ph;
1211
1212						ph = mtod(err, struct sctp_paramhdr *);
1213						SCTP_BUF_LEN(err) = sizeof(struct sctp_paramhdr);
1214						ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
1215						ph->param_length = htons(SCTP_BUF_LEN(err));
1216					}
1217					sctp_send_abort_tcb(stcb, err, SCTP_SO_LOCKED);
1218					SCTP_STAT_INCR_COUNTER32(sctps_aborted);
1219				}
1220				SCTP_INP_RUNLOCK(inp);
1221				if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
1222				    (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
1223					SCTP_STAT_DECR_GAUGE32(sctps_currestab);
1224				}
1225				(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_3);
1226				/* No unlock tcb assoc is gone */
1227				return (0);
1228			}
1229			if (TAILQ_EMPTY(&asoc->send_queue) &&
1230			    TAILQ_EMPTY(&asoc->sent_queue) &&
1231			    (asoc->stream_queue_cnt == 0)) {
1232				/* there is nothing queued to send, so done */
1233				if (asoc->locked_on_sending) {
1234					goto abort_anyway;
1235				}
1236				if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) &&
1237				    (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
1238					/* only send SHUTDOWN 1st time thru */
1239					struct sctp_nets *netp;
1240
1241					if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
1242					    (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
1243						SCTP_STAT_DECR_GAUGE32(sctps_currestab);
1244					}
1245					SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
1246					SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
1247					sctp_stop_timers_for_shutdown(stcb);
1248					if (stcb->asoc.alternate) {
1249						netp = stcb->asoc.alternate;
1250					} else {
1251						netp = stcb->asoc.primary_destination;
1252					}
1253					sctp_send_shutdown(stcb,netp);
1254					sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
1255							 stcb->sctp_ep, stcb, netp);
1256					sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
1257							 stcb->sctp_ep, stcb, netp);
1258					sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_LOCKED);
1259				}
1260			} else {
1261				/*
1262				 * we still got (or just got) data to send,
1263				 * so set SHUTDOWN_PENDING
1264				 */
1265				/*
1266				 * XXX sockets draft says that SCTP_EOF
1267				 * should be sent with no data. currently,
1268				 * we will allow user data to be sent first
1269				 * and move to SHUTDOWN-PENDING
1270				 */
1271				struct sctp_nets *netp;
1272				if (stcb->asoc.alternate) {
1273					netp = stcb->asoc.alternate;
1274				} else {
1275					netp = stcb->asoc.primary_destination;
1276				}
1277
1278				asoc->state |= SCTP_STATE_SHUTDOWN_PENDING;
1279				sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb,
1280						 netp);
1281				if (asoc->locked_on_sending) {
1282					/* Locked to send out the data */
1283					struct sctp_stream_queue_pending *sp;
1284					sp = TAILQ_LAST(&asoc->locked_on_sending->outqueue, sctp_streamhead);
1285					if (sp == NULL) {
1286						SCTP_PRINTF("Error, sp is NULL, locked on sending is non-null strm:%d\n",
1287							    asoc->locked_on_sending->stream_no);
1288					} else {
1289						if ((sp->length == 0) && (sp->msg_is_complete == 0))
1290							asoc->state |= SCTP_STATE_PARTIAL_MSG_LEFT;
1291					}
1292				}
1293				if (TAILQ_EMPTY(&asoc->send_queue) &&
1294				    TAILQ_EMPTY(&asoc->sent_queue) &&
1295				    (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
1296					struct mbuf *op_err;
1297				abort_anyway:
1298					op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
1299					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ+SCTP_LOC_4;
1300					sctp_send_abort_tcb(stcb, op_err, SCTP_SO_LOCKED);
1301					SCTP_STAT_INCR_COUNTER32(sctps_aborted);
1302					if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
1303					    (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
1304						SCTP_STAT_DECR_GAUGE32(sctps_currestab);
1305					}
1306					SCTP_INP_RUNLOCK(inp);
1307					(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_5);
1308					return (0);
1309				} else {
1310					sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
1311				}
1312			}
1313			soisdisconnecting(so);
1314			SCTP_TCB_UNLOCK(stcb);
1315			SCTP_INP_RUNLOCK(inp);
1316			return (0);
1317		}
1318		/* not reached */
1319	} else {
1320		/* UDP model does not support this */
1321		SCTP_INP_RUNLOCK(inp);
1322		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
1323		return (EOPNOTSUPP);
1324	}
1325}
1326
1327#if defined(__FreeBSD__) || defined(__Windows__) || defined(__Userspace__)
1328int
1329sctp_flush(struct socket *so, int how)
1330{
1331        /*
1332	 * We will just clear out the values and let
1333	 * subsequent close clear out the data, if any.
1334	 * Note if the user did a shutdown(SHUT_RD) they
1335	 * will not be able to read the data, the socket
1336	 * will block that from happening.
1337	 */
1338	struct sctp_inpcb *inp;
1339
1340	inp = (struct sctp_inpcb *)so->so_pcb;
1341	if (inp == NULL) {
1342		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1343		return (EINVAL);
1344	}
1345	SCTP_INP_RLOCK(inp);
1346	/* For the 1 to many model this does nothing */
1347	if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
1348		SCTP_INP_RUNLOCK(inp);
1349		return (0);
1350	}
1351	SCTP_INP_RUNLOCK(inp);
1352        if ((how == PRU_FLUSH_RD) || (how == PRU_FLUSH_RDWR)) {
1353		/* First make sure the sb will be happy, we don't
1354		 * use these except maybe the count
1355		 */
1356		SCTP_INP_WLOCK(inp);
1357		SCTP_INP_READ_LOCK(inp);
1358		inp->sctp_flags |= SCTP_PCB_FLAGS_SOCKET_CANT_READ;
1359		SCTP_INP_READ_UNLOCK(inp);
1360		SCTP_INP_WUNLOCK(inp);
1361		so->so_rcv.sb_cc = 0;
1362		so->so_rcv.sb_mbcnt = 0;
1363		so->so_rcv.sb_mb = NULL;
1364	}
1365        if ((how == PRU_FLUSH_WR) || (how == PRU_FLUSH_RDWR)) {
1366		/* First make sure the sb will be happy, we don't
1367		 * use these except maybe the count
1368		 */
1369		so->so_snd.sb_cc = 0;
1370		so->so_snd.sb_mbcnt = 0;
1371		so->so_snd.sb_mb = NULL;
1372
1373	}
1374	return (0);
1375}
1376#endif
1377
1378int
1379sctp_shutdown(struct socket *so)
1380{
1381	struct sctp_inpcb *inp;
1382
1383	inp = (struct sctp_inpcb *)so->so_pcb;
1384	if (inp == NULL) {
1385		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1386		return (EINVAL);
1387	}
1388	SCTP_INP_RLOCK(inp);
1389	/* For UDP model this is a invalid call */
1390	if (!((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1391	      (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) {
1392		/* Restore the flags that the soshutdown took away. */
1393#if (defined(__FreeBSD__) && __FreeBSD_version >= 502115) || defined(__Windows__)
1394		SOCKBUF_LOCK(&so->so_rcv);
1395		so->so_rcv.sb_state &= ~SBS_CANTRCVMORE;
1396		SOCKBUF_UNLOCK(&so->so_rcv);
1397#else
1398		so->so_state &= ~SS_CANTRCVMORE;
1399#endif
1400		/* This proc will wakeup for read and do nothing (I hope) */
1401		SCTP_INP_RUNLOCK(inp);
1402		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
1403		return (EOPNOTSUPP);
1404	}
1405	/*
1406	 * Ok if we reach here its the TCP model and it is either a SHUT_WR
1407	 * or SHUT_RDWR. This means we put the shutdown flag against it.
1408	 */
1409	{
1410		struct sctp_tcb *stcb;
1411		struct sctp_association *asoc;
1412
1413		if ((so->so_state &
1414		     (SS_ISCONNECTED|SS_ISCONNECTING|SS_ISDISCONNECTING)) == 0) {
1415			SCTP_INP_RUNLOCK(inp);
1416			return (ENOTCONN);
1417		}
1418		socantsendmore(so);
1419
1420		stcb = LIST_FIRST(&inp->sctp_asoc_list);
1421		if (stcb == NULL) {
1422			/*
1423			 * Ok we hit the case that the shutdown call was
1424			 * made after an abort or something. Nothing to do
1425			 * now.
1426			 */
1427			SCTP_INP_RUNLOCK(inp);
1428			return (0);
1429		}
1430		SCTP_TCB_LOCK(stcb);
1431		asoc = &stcb->asoc;
1432		if (TAILQ_EMPTY(&asoc->send_queue) &&
1433		    TAILQ_EMPTY(&asoc->sent_queue) &&
1434		    (asoc->stream_queue_cnt == 0)) {
1435			if (asoc->locked_on_sending) {
1436				goto abort_anyway;
1437			}
1438			/* there is nothing queued to send, so I'm done... */
1439			if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) {
1440				/* only send SHUTDOWN the first time through */
1441				struct sctp_nets *netp;
1442
1443				if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
1444				    (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
1445					SCTP_STAT_DECR_GAUGE32(sctps_currestab);
1446				}
1447				SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
1448				SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
1449				sctp_stop_timers_for_shutdown(stcb);
1450				if (stcb->asoc.alternate) {
1451					netp = stcb->asoc.alternate;
1452				} else {
1453					netp = stcb->asoc.primary_destination;
1454				}
1455				sctp_send_shutdown(stcb, netp);
1456				sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
1457						 stcb->sctp_ep, stcb, netp);
1458				sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
1459						 stcb->sctp_ep, stcb, netp);
1460				sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_LOCKED);
1461			}
1462		} else {
1463			/*
1464			 * we still got (or just got) data to send, so set
1465			 * SHUTDOWN_PENDING
1466			 */
1467			struct sctp_nets *netp;
1468			if (stcb->asoc.alternate) {
1469				netp = stcb->asoc.alternate;
1470			} else {
1471				netp = stcb->asoc.primary_destination;
1472			}
1473
1474			asoc->state |= SCTP_STATE_SHUTDOWN_PENDING;
1475			sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb,
1476					 netp);
1477
1478			if (asoc->locked_on_sending) {
1479				/* Locked to send out the data */
1480				struct sctp_stream_queue_pending *sp;
1481				sp = TAILQ_LAST(&asoc->locked_on_sending->outqueue, sctp_streamhead);
1482				if (sp == NULL) {
1483					SCTP_PRINTF("Error, sp is NULL, locked on sending is non-null strm:%d\n",
1484						    asoc->locked_on_sending->stream_no);
1485				} else {
1486					if ((sp->length == 0)  && (sp-> msg_is_complete == 0)) {
1487						asoc->state |= SCTP_STATE_PARTIAL_MSG_LEFT;
1488					}
1489				}
1490			}
1491			if (TAILQ_EMPTY(&asoc->send_queue) &&
1492			    TAILQ_EMPTY(&asoc->sent_queue) &&
1493			    (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
1494				struct mbuf *op_err;
1495			abort_anyway:
1496				op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
1497				stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ+SCTP_LOC_6;
1498				sctp_abort_an_association(stcb->sctp_ep, stcb,
1499							  op_err, SCTP_SO_LOCKED);
1500				goto skip_unlock;
1501			} else {
1502				sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
1503			}
1504		}
1505		SCTP_TCB_UNLOCK(stcb);
1506	}
1507 skip_unlock:
1508	SCTP_INP_RUNLOCK(inp);
1509	return (0);
1510}
1511
1512/*
1513 * copies a "user" presentable address and removes embedded scope, etc.
1514 * returns 0 on success, 1 on error
1515 */
1516static uint32_t
1517sctp_fill_user_address(struct sockaddr_storage *ss, struct sockaddr *sa)
1518{
1519#ifdef INET6
1520#if defined(SCTP_EMBEDDED_V6_SCOPE)
1521	struct sockaddr_in6 lsa6;
1522
1523	sa = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)sa,
1524	    &lsa6);
1525#endif
1526#endif
1527#ifdef HAVE_SA_LEN
1528	memcpy(ss, sa, sa->sa_len);
1529#else
1530	switch (sa->sa_family) {
1531#ifdef INET
1532	case AF_INET:
1533		memcpy(ss, sa, sizeof(struct sockaddr_in));
1534		break;
1535#endif
1536#ifdef INET6
1537	case AF_INET6:
1538		memcpy(ss, sa, sizeof(struct sockaddr_in6));
1539		break;
1540#endif
1541#if defined(__Userspace__)
1542	case AF_CONN:
1543		memcpy(ss, sa, sizeof(struct sockaddr_conn));
1544		break;
1545#endif
1546	default:
1547		/* TSNH */
1548		break;
1549	}
1550#endif
1551	return (0);
1552}
1553
1554
1555
1556/*
1557 * NOTE: assumes addr lock is held
1558 */
1559static size_t
1560sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp,
1561			   struct sctp_tcb *stcb,
1562			   size_t limit,
1563			   struct sockaddr_storage *sas,
1564			   uint32_t vrf_id)
1565{
1566	struct sctp_ifn *sctp_ifn;
1567	struct sctp_ifa *sctp_ifa;
1568	size_t actual;
1569	int loopback_scope;
1570#if defined(INET)
1571	int ipv4_local_scope, ipv4_addr_legal;
1572#endif
1573#if defined(INET6)
1574	int local_scope, site_scope, ipv6_addr_legal;
1575#endif
1576#if defined(__Userspace__)
1577	int conn_addr_legal;
1578#endif
1579	struct sctp_vrf *vrf;
1580
1581	actual = 0;
1582	if (limit <= 0)
1583		return (actual);
1584
1585	if (stcb) {
1586		/* Turn on all the appropriate scope */
1587		loopback_scope = stcb->asoc.scope.loopback_scope;
1588#if defined(INET)
1589		ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope;
1590		ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal;
1591#endif
1592#if defined(INET6)
1593		local_scope = stcb->asoc.scope.local_scope;
1594		site_scope = stcb->asoc.scope.site_scope;
1595		ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal;
1596#endif
1597#if defined(__Userspace__)
1598		conn_addr_legal = stcb->asoc.scope.conn_addr_legal;
1599#endif
1600	} else {
1601		/* Use generic values for endpoints. */
1602		loopback_scope = 1;
1603#if defined(INET)
1604		ipv4_local_scope = 1;
1605#endif
1606#if defined(INET6)
1607		local_scope = 1;
1608		site_scope = 1;
1609#endif
1610		if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
1611#if defined(INET6)
1612			ipv6_addr_legal = 1;
1613#endif
1614#if defined(INET)
1615			if (SCTP_IPV6_V6ONLY(inp)) {
1616				ipv4_addr_legal = 0;
1617			} else {
1618				ipv4_addr_legal = 1;
1619			}
1620#endif
1621#if defined(__Userspace__)
1622			conn_addr_legal = 0;
1623#endif
1624		} else {
1625#if defined(INET6)
1626			ipv6_addr_legal = 0;
1627#endif
1628#if defined(__Userspace__)
1629			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_CONN) {
1630				conn_addr_legal = 1;
1631#if defined(INET)
1632				ipv4_addr_legal = 0;
1633#endif
1634			} else {
1635				conn_addr_legal = 0;
1636#if defined(INET)
1637				ipv4_addr_legal = 1;
1638#endif
1639			}
1640#else
1641#if defined(INET)
1642			ipv4_addr_legal = 1;
1643#endif
1644#endif
1645		}
1646	}
1647	vrf = sctp_find_vrf(vrf_id);
1648	if (vrf == NULL) {
1649		return (0);
1650	}
1651	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
1652		LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
1653			if ((loopback_scope == 0) &&
1654			    SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
1655				/* Skip loopback if loopback_scope not set */
1656				continue;
1657			}
1658			LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
1659				if (stcb) {
1660					/*
1661					 * For the BOUND-ALL case, the list
1662					 * associated with a TCB is Always
1663					 * considered a reverse list.. i.e.
1664					 * it lists addresses that are NOT
1665					 * part of the association. If this
1666					 * is one of those we must skip it.
1667					 */
1668					if (sctp_is_addr_restricted(stcb,
1669								    sctp_ifa)) {
1670						continue;
1671					}
1672				}
1673				switch (sctp_ifa->address.sa.sa_family) {
1674#ifdef INET
1675				case AF_INET:
1676					if (ipv4_addr_legal) {
1677						struct sockaddr_in *sin;
1678
1679						sin = (struct sockaddr_in *)&sctp_ifa->address.sa;
1680						if (sin->sin_addr.s_addr == 0) {
1681							/*
1682							 * we skip unspecifed
1683							 * addresses
1684							 */
1685							continue;
1686						}
1687						if ((ipv4_local_scope == 0) &&
1688						    (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) {
1689							continue;
1690						}
1691#ifdef INET6
1692						if (sctp_is_feature_on(inp,SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
1693							in6_sin_2_v4mapsin6(sin, (struct sockaddr_in6 *)sas);
1694							((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
1695							sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(struct sockaddr_in6));
1696							actual += sizeof(struct sockaddr_in6);
1697						} else {
1698#endif
1699							memcpy(sas, sin, sizeof(*sin));
1700							((struct sockaddr_in *)sas)->sin_port = inp->sctp_lport;
1701							sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(*sin));
1702							actual += sizeof(*sin);
1703#ifdef INET6
1704						}
1705#endif
1706						if (actual >= limit) {
1707							return (actual);
1708						}
1709					} else {
1710						continue;
1711					}
1712					break;
1713#endif
1714#ifdef INET6
1715				case AF_INET6:
1716					if (ipv6_addr_legal) {
1717						struct sockaddr_in6 *sin6;
1718
1719#if defined(SCTP_EMBEDDED_V6_SCOPE) && !defined(SCTP_KAME)
1720						struct sockaddr_in6 lsa6;
1721#endif
1722						sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa;
1723						if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
1724							/*
1725							 * we skip unspecifed
1726							 * addresses
1727							 */
1728							continue;
1729						}
1730						if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
1731							if (local_scope == 0)
1732								continue;
1733#if defined(SCTP_EMBEDDED_V6_SCOPE)
1734							if (sin6->sin6_scope_id == 0) {
1735#ifdef SCTP_KAME
1736								if (sa6_recoverscope(sin6) != 0)
1737									/*
1738									 * bad link
1739									 * local
1740									 * address
1741									 */
1742									continue;
1743#else
1744								lsa6 = *sin6;
1745								if (in6_recoverscope(&lsa6,
1746										     &lsa6.sin6_addr,
1747										     NULL))
1748									/*
1749									 * bad link
1750									 * local
1751									 * address
1752									 */
1753								continue;
1754								sin6 = &lsa6;
1755#endif				/* SCTP_KAME */
1756							}
1757#endif /* SCTP_EMBEDDED_V6_SCOPE */
1758						}
1759						if ((site_scope == 0) &&
1760						    (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) {
1761							continue;
1762						}
1763						memcpy(sas, sin6, sizeof(*sin6));
1764						((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
1765						sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(*sin6));
1766						actual += sizeof(*sin6);
1767						if (actual >= limit) {
1768							return (actual);
1769						}
1770					} else {
1771						continue;
1772					}
1773					break;
1774#endif
1775#if defined(__Userspace__)
1776				case AF_CONN:
1777					if (conn_addr_legal) {
1778						memcpy(sas, &sctp_ifa->address.sconn, sizeof(struct sockaddr_conn));
1779						((struct sockaddr_conn *)sas)->sconn_port = inp->sctp_lport;
1780						sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(struct sockaddr_conn));
1781						actual += sizeof(struct sockaddr_conn);
1782						if (actual >= limit) {
1783							return (actual);
1784						}
1785					} else {
1786						continue;
1787					}
1788#endif
1789				default:
1790					/* TSNH */
1791					break;
1792				}
1793			}
1794		}
1795	} else {
1796		struct sctp_laddr *laddr;
1797#ifndef HAVE_SA_LEN
1798		uint32_t sa_len = 0;
1799#endif
1800
1801		LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
1802			if (stcb) {
1803				if (sctp_is_addr_restricted(stcb, laddr->ifa)) {
1804					continue;
1805				}
1806			}
1807			if (sctp_fill_user_address(sas, &laddr->ifa->address.sa))
1808				continue;
1809			switch (laddr->ifa->address.sa.sa_family) {
1810#ifdef INET
1811			case AF_INET:
1812				((struct sockaddr_in *)sas)->sin_port = inp->sctp_lport;
1813				break;
1814#endif
1815#ifdef INET6
1816			case AF_INET6:
1817				((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
1818				break;
1819#endif
1820#if defined(__Userspace__)
1821			case AF_CONN:
1822				((struct sockaddr_conn *)sas)->sconn_port = inp->sctp_lport;
1823				break;
1824#endif
1825			default:
1826				/* TSNH */
1827				break;
1828			}
1829#ifdef HAVE_SA_LEN
1830			sas = (struct sockaddr_storage *)((caddr_t)sas +
1831							  laddr->ifa->address.sa.sa_len);
1832			actual += laddr->ifa->address.sa.sa_len;
1833#else
1834			switch (laddr->ifa->address.sa.sa_family) {
1835#ifdef INET
1836			case AF_INET:
1837				sa_len = sizeof(struct sockaddr_in);
1838				break;
1839#endif
1840#ifdef INET6
1841			case AF_INET6:
1842				sa_len = sizeof(struct sockaddr_in6);
1843				break;
1844#endif
1845#if defined(__Userspace__)
1846			case AF_CONN:
1847				sa_len = sizeof(struct sockaddr_conn);
1848				break;
1849#endif
1850			default:
1851				/* TSNH */
1852				break;
1853			}
1854			sas = (struct sockaddr_storage *)((caddr_t)sas + sa_len);
1855			actual += sa_len;
1856#endif
1857			if (actual >= limit) {
1858				return (actual);
1859			}
1860		}
1861	}
1862	return (actual);
1863}
1864
1865static size_t
1866sctp_fill_up_addresses(struct sctp_inpcb *inp,
1867                       struct sctp_tcb *stcb,
1868                       size_t limit,
1869                       struct sockaddr_storage *sas)
1870{
1871	size_t size = 0;
1872#ifdef SCTP_MVRF
1873	uint32_t id;
1874#endif
1875
1876	SCTP_IPI_ADDR_RLOCK();
1877#ifdef SCTP_MVRF
1878/*
1879 * FIX ME: ?? this WILL report duplicate addresses if they appear
1880 * in more than one VRF.
1881 */
1882	/* fill up addresses for all VRFs on the endpoint */
1883	for (id = 0; (id < inp->num_vrfs) && (size < limit); id++) {
1884		size += sctp_fill_up_addresses_vrf(inp, stcb, limit, sas,
1885						   inp->m_vrf_ids[id]);
1886		sas = (struct sockaddr_storage *)((caddr_t)sas + size);
1887	}
1888#else
1889	/* fill up addresses for the endpoint's default vrf */
1890	size = sctp_fill_up_addresses_vrf(inp, stcb, limit, sas,
1891					  inp->def_vrf_id);
1892#endif
1893	SCTP_IPI_ADDR_RUNLOCK();
1894	return (size);
1895}
1896
1897/*
1898 * NOTE: assumes addr lock is held
1899 */
1900static int
1901sctp_count_max_addresses_vrf(struct sctp_inpcb *inp, uint32_t vrf_id)
1902{
1903	int cnt = 0;
1904	struct sctp_vrf *vrf = NULL;
1905
1906	/*
1907	 * In both sub-set bound an bound_all cases we return the MAXIMUM
1908	 * number of addresses that you COULD get. In reality the sub-set
1909	 * bound may have an exclusion list for a given TCB OR in the
1910	 * bound-all case a TCB may NOT include the loopback or other
1911	 * addresses as well.
1912	 */
1913	vrf = sctp_find_vrf(vrf_id);
1914	if (vrf == NULL) {
1915		return (0);
1916	}
1917	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
1918		struct sctp_ifn *sctp_ifn;
1919		struct sctp_ifa *sctp_ifa;
1920
1921		LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
1922			LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
1923				/* Count them if they are the right type */
1924				switch (sctp_ifa->address.sa.sa_family) {
1925#ifdef INET
1926				case AF_INET:
1927					if (sctp_is_feature_on(inp,SCTP_PCB_FLAGS_NEEDS_MAPPED_V4))
1928						cnt += sizeof(struct sockaddr_in6);
1929					else
1930						cnt += sizeof(struct sockaddr_in);
1931					break;
1932#endif
1933#ifdef INET6
1934				case AF_INET6:
1935					cnt += sizeof(struct sockaddr_in6);
1936					break;
1937#endif
1938#if defined(__Userspace__)
1939				case AF_CONN:
1940					cnt += sizeof(struct sockaddr_conn);
1941					break;
1942#endif
1943				default:
1944					break;
1945				}
1946			}
1947		}
1948	} else {
1949		struct sctp_laddr *laddr;
1950
1951		LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
1952			switch (laddr->ifa->address.sa.sa_family) {
1953#ifdef INET
1954			case AF_INET:
1955				if (sctp_is_feature_on(inp,SCTP_PCB_FLAGS_NEEDS_MAPPED_V4))
1956					cnt += sizeof(struct sockaddr_in6);
1957				else
1958					cnt += sizeof(struct sockaddr_in);
1959				break;
1960#endif
1961#ifdef INET6
1962			case AF_INET6:
1963				cnt += sizeof(struct sockaddr_in6);
1964				break;
1965#endif
1966#if defined(__Userspace__)
1967			case AF_CONN:
1968				cnt += sizeof(struct sockaddr_conn);
1969				break;
1970#endif
1971			default:
1972				break;
1973			}
1974		}
1975	}
1976	return (cnt);
1977}
1978
1979static int
1980sctp_count_max_addresses(struct sctp_inpcb *inp)
1981{
1982	int cnt = 0;
1983#ifdef SCTP_MVRF
1984	int id;
1985#endif
1986
1987	SCTP_IPI_ADDR_RLOCK();
1988#ifdef SCTP_MVRF
1989/*
1990 * FIX ME: ?? this WILL count duplicate addresses if they appear
1991 * in more than one VRF.
1992 */
1993	/* count addresses for all VRFs on the endpoint */
1994	for (id = 0; id < inp->num_vrfs; id++) {
1995		cnt += sctp_count_max_addresses_vrf(inp, inp->m_vrf_ids[id]);
1996	}
1997#else
1998	/* count addresses for the endpoint's default VRF */
1999	cnt = sctp_count_max_addresses_vrf(inp, inp->def_vrf_id);
2000#endif
2001	SCTP_IPI_ADDR_RUNLOCK();
2002	return (cnt);
2003}
2004
2005static int
2006sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
2007		  size_t optsize, void *p, int delay)
2008{
2009	int error = 0;
2010	int creat_lock_on = 0;
2011	struct sctp_tcb *stcb = NULL;
2012	struct sockaddr *sa;
2013	int num_v6 = 0, num_v4 = 0, *totaddrp, totaddr;
2014	uint32_t vrf_id;
2015	int bad_addresses = 0;
2016	sctp_assoc_t *a_id;
2017
2018	SCTPDBG(SCTP_DEBUG_PCB1, "Connectx called\n");
2019
2020	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
2021	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
2022		/* We are already connected AND the TCP model */
2023		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
2024		return (EADDRINUSE);
2025	}
2026
2027	if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
2028	    (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
2029		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2030		return (EINVAL);
2031	}
2032
2033	if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
2034		SCTP_INP_RLOCK(inp);
2035		stcb = LIST_FIRST(&inp->sctp_asoc_list);
2036		SCTP_INP_RUNLOCK(inp);
2037	}
2038	if (stcb) {
2039		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
2040		return (EALREADY);
2041	}
2042	SCTP_INP_INCR_REF(inp);
2043	SCTP_ASOC_CREATE_LOCK(inp);
2044	creat_lock_on = 1;
2045	if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
2046	    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
2047		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
2048		error = EFAULT;
2049		goto out_now;
2050	}
2051	totaddrp = (int *)optval;
2052	totaddr = *totaddrp;
2053	sa = (struct sockaddr *)(totaddrp + 1);
2054	stcb = sctp_connectx_helper_find(inp, sa, &totaddr, &num_v4, &num_v6, &error, (optsize - sizeof(int)), &bad_addresses);
2055	if ((stcb != NULL) || bad_addresses) {
2056		/* Already have or am bring up an association */
2057		SCTP_ASOC_CREATE_UNLOCK(inp);
2058		creat_lock_on = 0;
2059		if (stcb)
2060			SCTP_TCB_UNLOCK(stcb);
2061		if (bad_addresses == 0) {
2062			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
2063			error = EALREADY;
2064		}
2065		goto out_now;
2066	}
2067#ifdef INET6
2068	if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
2069	    (num_v6 > 0)) {
2070		error = EINVAL;
2071		goto out_now;
2072	}
2073	if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
2074	    (num_v4 > 0)) {
2075		struct in6pcb *inp6;
2076
2077		inp6 = (struct in6pcb *)inp;
2078		if (SCTP_IPV6_V6ONLY(inp6)) {
2079			/*
2080			 * if IPV6_V6ONLY flag, ignore connections destined
2081			 * to a v4 addr or v4-mapped addr
2082			 */
2083			SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2084			error = EINVAL;
2085			goto out_now;
2086		}
2087	}
2088#endif				/* INET6 */
2089	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
2090	    SCTP_PCB_FLAGS_UNBOUND) {
2091		/* Bind a ephemeral port */
2092		error = sctp_inpcb_bind(so, NULL, NULL, p);
2093		if (error) {
2094			goto out_now;
2095		}
2096	}
2097
2098	/* FIX ME: do we want to pass in a vrf on the connect call? */
2099	vrf_id = inp->def_vrf_id;
2100
2101
2102	/* We are GOOD to go */
2103	stcb = sctp_aloc_assoc(inp, sa, &error, 0, vrf_id,
2104#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
2105			       (struct thread *)p
2106#elif defined(__Windows__)
2107			       (PKTHREAD)p
2108#else
2109			       (struct proc *)p
2110#endif
2111		);
2112	if (stcb == NULL) {
2113		/* Gak! no memory */
2114		goto out_now;
2115	}
2116	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
2117		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
2118		/* Set the connected flag so we can queue data */
2119		soisconnecting(so);
2120	}
2121	SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
2122	/* move to second address */
2123	switch (sa->sa_family) {
2124#ifdef INET
2125	case AF_INET:
2126		sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in));
2127		break;
2128#endif
2129#ifdef INET6
2130	case AF_INET6:
2131		sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in6));
2132		break;
2133#endif
2134	default:
2135		break;
2136	}
2137
2138	error = 0;
2139	sctp_connectx_helper_add(stcb, sa, (totaddr-1), &error);
2140	/* Fill in the return id */
2141	if (error) {
2142		(void)sctp_free_assoc(inp, stcb, SCTP_PCBFREE_FORCE, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_6);
2143		goto out_now;
2144	}
2145	a_id = (sctp_assoc_t *)optval;
2146	*a_id = sctp_get_associd(stcb);
2147
2148	/* initialize authentication parameters for the assoc */
2149	sctp_initialize_auth_params(inp, stcb);
2150
2151	if (delay) {
2152		/* doing delayed connection */
2153		stcb->asoc.delayed_connection = 1;
2154		sctp_timer_start(SCTP_TIMER_TYPE_INIT, inp, stcb, stcb->asoc.primary_destination);
2155	} else {
2156		(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
2157		sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
2158	}
2159	SCTP_TCB_UNLOCK(stcb);
2160	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
2161		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
2162		/* Set the connected flag so we can queue data */
2163		soisconnecting(so);
2164	}
2165 out_now:
2166	if (creat_lock_on) {
2167		SCTP_ASOC_CREATE_UNLOCK(inp);
2168	}
2169	SCTP_INP_DECR_REF(inp);
2170	return (error);
2171}
2172
2173#define SCTP_FIND_STCB(inp, stcb, assoc_id) { \
2174	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||\
2175	    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { \
2176		SCTP_INP_RLOCK(inp); \
2177		stcb = LIST_FIRST(&inp->sctp_asoc_list); \
2178		if (stcb) { \
2179			SCTP_TCB_LOCK(stcb); \
2180                } \
2181		SCTP_INP_RUNLOCK(inp); \
2182	} else if (assoc_id > SCTP_ALL_ASSOC) { \
2183		stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1); \
2184		if (stcb == NULL) { \
2185		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT); \
2186			error = ENOENT; \
2187			break; \
2188		} \
2189	} else { \
2190		stcb = NULL; \
2191        } \
2192  }
2193
2194
2195#define SCTP_CHECK_AND_CAST(destp, srcp, type, size) {\
2196	if (size < sizeof(type)) { \
2197		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); \
2198		error = EINVAL; \
2199		break; \
2200	} else { \
2201		destp = (type *)srcp; \
2202	} \
2203      }
2204
2205#if defined(__Panda__) || defined(__Userspace__)
2206int
2207#else
2208static int
2209#endif
2210sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
2211	    void *p) {
2212	struct sctp_inpcb *inp = NULL;
2213	int error, val = 0;
2214	struct sctp_tcb *stcb = NULL;
2215
2216	if (optval == NULL) {
2217		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2218		return (EINVAL);
2219	}
2220
2221	inp = (struct sctp_inpcb *)so->so_pcb;
2222	if (inp == NULL) {
2223		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2224		return EINVAL;
2225	}
2226	error = 0;
2227
2228	switch (optname) {
2229	case SCTP_NODELAY:
2230	case SCTP_AUTOCLOSE:
2231	case SCTP_EXPLICIT_EOR:
2232	case SCTP_AUTO_ASCONF:
2233	case SCTP_DISABLE_FRAGMENTS:
2234	case SCTP_I_WANT_MAPPED_V4_ADDR:
2235	case SCTP_USE_EXT_RCVINFO:
2236		SCTP_INP_RLOCK(inp);
2237		switch (optname) {
2238		case SCTP_DISABLE_FRAGMENTS:
2239			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NO_FRAGMENT);
2240			break;
2241		case SCTP_I_WANT_MAPPED_V4_ADDR:
2242			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4);
2243			break;
2244		case SCTP_AUTO_ASCONF:
2245			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
2246				/* only valid for bound all sockets */
2247				val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTO_ASCONF);
2248			} else {
2249				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2250				error = EINVAL;
2251				goto flags_out;
2252			}
2253			break;
2254		case SCTP_EXPLICIT_EOR:
2255			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR);
2256			break;
2257		case SCTP_NODELAY:
2258			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NODELAY);
2259			break;
2260		case SCTP_USE_EXT_RCVINFO:
2261			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO);
2262			break;
2263		case SCTP_AUTOCLOSE:
2264			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE))
2265				val = TICKS_TO_SEC(inp->sctp_ep.auto_close_time);
2266			else
2267				val = 0;
2268			break;
2269
2270		default:
2271			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
2272			error = ENOPROTOOPT;
2273		} /* end switch (sopt->sopt_name) */
2274		if (*optsize < sizeof(val)) {
2275			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2276			error = EINVAL;
2277		}
2278	flags_out:
2279		SCTP_INP_RUNLOCK(inp);
2280		if (error == 0) {
2281			/* return the option value */
2282			*(int *)optval = val;
2283			*optsize = sizeof(val);
2284		}
2285		break;
2286        case SCTP_GET_PACKET_LOG:
2287	{
2288#ifdef  SCTP_PACKET_LOGGING
2289		uint8_t *target;
2290		int ret;
2291
2292		SCTP_CHECK_AND_CAST(target, optval, uint8_t, *optsize);
2293		ret = sctp_copy_out_packet_log(target , (int)*optsize);
2294		*optsize = ret;
2295#else
2296		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
2297		error = EOPNOTSUPP;
2298#endif
2299		break;
2300	}
2301	case SCTP_REUSE_PORT:
2302	{
2303		uint32_t *value;
2304
2305		if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
2306			/* Can't do this for a 1-m socket */
2307			error = EINVAL;
2308			break;
2309		}
2310		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2311		*value = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE);
2312		*optsize = sizeof(uint32_t);
2313		break;
2314	}
2315	case SCTP_PARTIAL_DELIVERY_POINT:
2316	{
2317		uint32_t *value;
2318
2319		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2320		*value = inp->partial_delivery_point;
2321		*optsize = sizeof(uint32_t);
2322		break;
2323	}
2324	case SCTP_FRAGMENT_INTERLEAVE:
2325	{
2326		uint32_t *value;
2327
2328		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2329		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE)) {
2330			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS)) {
2331				*value = SCTP_FRAG_LEVEL_2;
2332			} else {
2333				*value = SCTP_FRAG_LEVEL_1;
2334			}
2335		} else {
2336			*value = SCTP_FRAG_LEVEL_0;
2337		}
2338		*optsize = sizeof(uint32_t);
2339		break;
2340	}
2341	case SCTP_CMT_ON_OFF:
2342	{
2343		struct sctp_assoc_value *av;
2344
2345		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2346		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2347		if (stcb) {
2348			av->assoc_value = stcb->asoc.sctp_cmt_on_off;
2349			SCTP_TCB_UNLOCK(stcb);
2350		} else {
2351			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2352			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2353			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
2354				SCTP_INP_RLOCK(inp);
2355				av->assoc_value = inp->sctp_cmt_on_off;
2356				SCTP_INP_RUNLOCK(inp);
2357			} else {
2358				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2359				error = EINVAL;
2360			}
2361		}
2362		if (error == 0) {
2363			*optsize = sizeof(struct sctp_assoc_value);
2364		}
2365		break;
2366	}
2367	case SCTP_PLUGGABLE_CC:
2368	{
2369		struct sctp_assoc_value *av;
2370
2371		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2372		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2373		if (stcb) {
2374			av->assoc_value = stcb->asoc.congestion_control_module;
2375			SCTP_TCB_UNLOCK(stcb);
2376		} else {
2377			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2378			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2379			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
2380				SCTP_INP_RLOCK(inp);
2381				av->assoc_value = inp->sctp_ep.sctp_default_cc_module;
2382				SCTP_INP_RUNLOCK(inp);
2383			} else {
2384				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2385				error = EINVAL;
2386			}
2387		}
2388		if (error == 0) {
2389			*optsize = sizeof(struct sctp_assoc_value);
2390		}
2391		break;
2392	}
2393	case SCTP_CC_OPTION:
2394	{
2395		struct sctp_cc_option *cc_opt;
2396
2397		SCTP_CHECK_AND_CAST(cc_opt, optval, struct sctp_cc_option, *optsize);
2398		SCTP_FIND_STCB(inp, stcb, cc_opt->aid_value.assoc_id);
2399		if (stcb == NULL) {
2400			error = EINVAL;
2401		} else {
2402			if (stcb->asoc.cc_functions.sctp_cwnd_socket_option == NULL) {
2403				error = ENOTSUP;
2404			} else {
2405				error = (*stcb->asoc.cc_functions.sctp_cwnd_socket_option)(stcb, 0, cc_opt);
2406				*optsize = sizeof(struct sctp_cc_option);
2407			}
2408			SCTP_TCB_UNLOCK(stcb);
2409		}
2410		break;
2411	}
2412	case SCTP_PLUGGABLE_SS:
2413	{
2414		struct sctp_assoc_value *av;
2415
2416		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2417		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2418		if (stcb) {
2419			av->assoc_value = stcb->asoc.stream_scheduling_module;
2420			SCTP_TCB_UNLOCK(stcb);
2421		} else {
2422			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2423			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2424			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
2425				SCTP_INP_RLOCK(inp);
2426				av->assoc_value = inp->sctp_ep.sctp_default_ss_module;
2427				SCTP_INP_RUNLOCK(inp);
2428			} else {
2429				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2430				error = EINVAL;
2431			}
2432		}
2433		if (error == 0) {
2434			*optsize = sizeof(struct sctp_assoc_value);
2435		}
2436		break;
2437	}
2438	case SCTP_SS_VALUE:
2439	{
2440		struct sctp_stream_value *av;
2441
2442		SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, *optsize);
2443		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2444		if (stcb) {
2445			if (stcb->asoc.ss_functions.sctp_ss_get_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id],
2446			                                              &av->stream_value) < 0) {
2447				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2448				error = EINVAL;
2449			} else {
2450				*optsize = sizeof(struct sctp_stream_value);
2451			}
2452			SCTP_TCB_UNLOCK(stcb);
2453		} else {
2454			/* Can't get stream value without association */
2455			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2456			error = EINVAL;
2457		}
2458		break;
2459	}
2460	case SCTP_GET_ADDR_LEN:
2461	{
2462		struct sctp_assoc_value *av;
2463
2464		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2465		error = EINVAL;
2466#ifdef INET
2467		if (av->assoc_value == AF_INET) {
2468			av->assoc_value = sizeof(struct sockaddr_in);
2469			error = 0;
2470		}
2471#endif
2472#ifdef INET6
2473		if (av->assoc_value == AF_INET6) {
2474			av->assoc_value = sizeof(struct sockaddr_in6);
2475			error = 0;
2476		}
2477#endif
2478#if defined(__Userspace__)
2479		if (av->assoc_value == AF_CONN) {
2480			av->assoc_value = sizeof(struct sockaddr_conn);
2481			error = 0;
2482		}
2483#endif
2484		if (error) {
2485			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2486		} else {
2487			*optsize = sizeof(struct sctp_assoc_value);
2488		}
2489		break;
2490	}
2491	case SCTP_GET_ASSOC_NUMBER:
2492	{
2493		uint32_t *value, cnt;
2494
2495		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2496		cnt = 0;
2497		SCTP_INP_RLOCK(inp);
2498		LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
2499			cnt++;
2500		}
2501		SCTP_INP_RUNLOCK(inp);
2502		*value = cnt;
2503		*optsize = sizeof(uint32_t);
2504		break;
2505	}
2506	case SCTP_GET_ASSOC_ID_LIST:
2507	{
2508		struct sctp_assoc_ids *ids;
2509		unsigned int at, limit;
2510
2511		SCTP_CHECK_AND_CAST(ids, optval, struct sctp_assoc_ids, *optsize);
2512		at = 0;
2513		limit = (*optsize-sizeof(uint32_t))/ sizeof(sctp_assoc_t);
2514		SCTP_INP_RLOCK(inp);
2515		LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
2516			if (at < limit) {
2517				ids->gaids_assoc_id[at++] = sctp_get_associd(stcb);
2518			} else {
2519				error = EINVAL;
2520				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2521				break;
2522			}
2523		}
2524		SCTP_INP_RUNLOCK(inp);
2525		if (error == 0) {
2526			ids->gaids_number_of_ids = at;
2527			*optsize = ((at * sizeof(sctp_assoc_t)) + sizeof(uint32_t));
2528		}
2529		break;
2530	}
2531	case SCTP_CONTEXT:
2532	{
2533		struct sctp_assoc_value *av;
2534
2535		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2536		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2537
2538		if (stcb) {
2539			av->assoc_value = stcb->asoc.context;
2540			SCTP_TCB_UNLOCK(stcb);
2541		} else {
2542			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2543			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2544			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
2545				SCTP_INP_RLOCK(inp);
2546				av->assoc_value = inp->sctp_context;
2547				SCTP_INP_RUNLOCK(inp);
2548			} else {
2549				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2550				error = EINVAL;
2551			}
2552		}
2553		if (error == 0) {
2554			*optsize = sizeof(struct sctp_assoc_value);
2555		}
2556		break;
2557	}
2558	case SCTP_VRF_ID:
2559	{
2560		uint32_t *default_vrfid;
2561
2562		SCTP_CHECK_AND_CAST(default_vrfid, optval, uint32_t, *optsize);
2563		*default_vrfid = inp->def_vrf_id;
2564		*optsize = sizeof(uint32_t);
2565		break;
2566	}
2567	case SCTP_GET_ASOC_VRF:
2568	{
2569		struct sctp_assoc_value *id;
2570
2571		SCTP_CHECK_AND_CAST(id, optval, struct sctp_assoc_value, *optsize);
2572		SCTP_FIND_STCB(inp, stcb, id->assoc_id);
2573		if (stcb == NULL) {
2574			error = EINVAL;
2575			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2576		} else {
2577			id->assoc_value = stcb->asoc.vrf_id;
2578			*optsize = sizeof(struct sctp_assoc_value);
2579		}
2580		break;
2581	}
2582	case SCTP_GET_VRF_IDS:
2583	{
2584#ifdef SCTP_MVRF
2585		int siz_needed;
2586		uint32_t *vrf_ids;
2587
2588		SCTP_CHECK_AND_CAST(vrf_ids, optval, uint32_t, *optsize);
2589		siz_needed = inp->num_vrfs * sizeof(uint32_t);
2590		if (*optsize < siz_needed) {
2591			error = EINVAL;
2592			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2593		} else {
2594			memcpy(vrf_ids, inp->m_vrf_ids, siz_needed);
2595			*optsize = siz_needed;
2596		}
2597#else
2598		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
2599		error = EOPNOTSUPP;
2600#endif
2601		break;
2602	}
2603	case SCTP_GET_NONCE_VALUES:
2604	{
2605		struct sctp_get_nonce_values *gnv;
2606
2607		SCTP_CHECK_AND_CAST(gnv, optval, struct sctp_get_nonce_values, *optsize);
2608		SCTP_FIND_STCB(inp, stcb, gnv->gn_assoc_id);
2609
2610		if (stcb) {
2611			gnv->gn_peers_tag = stcb->asoc.peer_vtag;
2612			gnv->gn_local_tag = stcb->asoc.my_vtag;
2613			SCTP_TCB_UNLOCK(stcb);
2614			*optsize = sizeof(struct sctp_get_nonce_values);
2615		} else {
2616			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
2617			error = ENOTCONN;
2618		}
2619		break;
2620	}
2621	case SCTP_DELAYED_SACK:
2622	{
2623		struct sctp_sack_info *sack;
2624
2625		SCTP_CHECK_AND_CAST(sack, optval, struct sctp_sack_info, *optsize);
2626		SCTP_FIND_STCB(inp, stcb, sack->sack_assoc_id);
2627		if (stcb) {
2628			sack->sack_delay = stcb->asoc.delayed_ack;
2629			sack->sack_freq = stcb->asoc.sack_freq;
2630			SCTP_TCB_UNLOCK(stcb);
2631		} else {
2632			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2633			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2634			    (sack->sack_assoc_id == SCTP_FUTURE_ASSOC)) {
2635				SCTP_INP_RLOCK(inp);
2636				sack->sack_delay = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
2637				sack->sack_freq = inp->sctp_ep.sctp_sack_freq;
2638				SCTP_INP_RUNLOCK(inp);
2639			} else {
2640				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2641				error = EINVAL;
2642			}
2643		}
2644		if (error == 0) {
2645			*optsize = sizeof(struct sctp_sack_info);
2646		}
2647		break;
2648	}
2649	case SCTP_GET_SNDBUF_USE:
2650	{
2651		struct sctp_sockstat *ss;
2652
2653		SCTP_CHECK_AND_CAST(ss, optval, struct sctp_sockstat, *optsize);
2654		SCTP_FIND_STCB(inp, stcb, ss->ss_assoc_id);
2655
2656		if (stcb) {
2657			ss->ss_total_sndbuf = stcb->asoc.total_output_queue_size;
2658			ss->ss_total_recv_buf = (stcb->asoc.size_on_reasm_queue +
2659						 stcb->asoc.size_on_all_streams);
2660			SCTP_TCB_UNLOCK(stcb);
2661			*optsize = sizeof(struct sctp_sockstat);
2662		} else {
2663			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
2664			error = ENOTCONN;
2665		}
2666		break;
2667	}
2668	case SCTP_MAX_BURST:
2669	{
2670#if defined(__FreeBSD__) && __FreeBSD_version < 900000
2671		uint8_t *value;
2672
2673		SCTP_CHECK_AND_CAST(value, optval, uint8_t, *optsize);
2674
2675		SCTP_INP_RLOCK(inp);
2676		if (inp->sctp_ep.max_burst < 256) {
2677			*value = inp->sctp_ep.max_burst;
2678		} else {
2679			*value = 255;
2680		}
2681		SCTP_INP_RUNLOCK(inp);
2682		*optsize = sizeof(uint8_t);
2683#else
2684		struct sctp_assoc_value *av;
2685
2686		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2687		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2688
2689		if (stcb) {
2690			av->assoc_value = stcb->asoc.max_burst;
2691			SCTP_TCB_UNLOCK(stcb);
2692		} else {
2693			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2694			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2695			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
2696				SCTP_INP_RLOCK(inp);
2697				av->assoc_value = inp->sctp_ep.max_burst;
2698				SCTP_INP_RUNLOCK(inp);
2699			} else {
2700				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2701				error = EINVAL;
2702			}
2703		}
2704		if (error == 0) {
2705			*optsize = sizeof(struct sctp_assoc_value);
2706		}
2707#endif
2708		break;
2709	}
2710	case SCTP_MAXSEG:
2711	{
2712		struct sctp_assoc_value *av;
2713		int ovh;
2714
2715		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2716		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2717
2718		if (stcb) {
2719			av->assoc_value = sctp_get_frag_point(stcb, &stcb->asoc);
2720			SCTP_TCB_UNLOCK(stcb);
2721		} else {
2722			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2723			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2724			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
2725				SCTP_INP_RLOCK(inp);
2726				if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
2727					ovh = SCTP_MED_OVERHEAD;
2728				} else {
2729					ovh = SCTP_MED_V4_OVERHEAD;
2730				}
2731				if (inp->sctp_frag_point >= SCTP_DEFAULT_MAXSEGMENT)
2732					av->assoc_value = 0;
2733				else
2734					av->assoc_value = inp->sctp_frag_point - ovh;
2735				SCTP_INP_RUNLOCK(inp);
2736			} else {
2737				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2738				error = EINVAL;
2739			}
2740		}
2741		if (error == 0) {
2742			*optsize = sizeof(struct sctp_assoc_value);
2743		}
2744		break;
2745	}
2746	case SCTP_GET_STAT_LOG:
2747		error = sctp_fill_stat_log(optval, optsize);
2748		break;
2749	case SCTP_EVENTS:
2750	{
2751		struct sctp_event_subscribe *events;
2752
2753		SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, *optsize);
2754		memset(events, 0, sizeof(struct sctp_event_subscribe));
2755		SCTP_INP_RLOCK(inp);
2756		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT))
2757			events->sctp_data_io_event = 1;
2758
2759		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT))
2760			events->sctp_association_event = 1;
2761
2762		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVPADDREVNT))
2763			events->sctp_address_event = 1;
2764
2765		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT))
2766			events->sctp_send_failure_event = 1;
2767
2768		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVPEERERR))
2769			events->sctp_peer_error_event = 1;
2770
2771		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT))
2772			events->sctp_shutdown_event = 1;
2773
2774		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT))
2775			events->sctp_partial_delivery_event = 1;
2776
2777		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT))
2778			events->sctp_adaptation_layer_event = 1;
2779
2780		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT))
2781			events->sctp_authentication_event = 1;
2782
2783		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT))
2784			events->sctp_sender_dry_event = 1;
2785
2786		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT))
2787			events->sctp_stream_reset_event = 1;
2788		SCTP_INP_RUNLOCK(inp);
2789		*optsize = sizeof(struct sctp_event_subscribe);
2790		break;
2791	}
2792	case SCTP_ADAPTATION_LAYER:
2793	{
2794		uint32_t *value;
2795
2796		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2797
2798		SCTP_INP_RLOCK(inp);
2799		*value = inp->sctp_ep.adaptation_layer_indicator;
2800		SCTP_INP_RUNLOCK(inp);
2801		*optsize = sizeof(uint32_t);
2802		break;
2803	}
2804	case SCTP_SET_INITIAL_DBG_SEQ:
2805	{
2806		uint32_t *value;
2807
2808		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2809		SCTP_INP_RLOCK(inp);
2810		*value = inp->sctp_ep.initial_sequence_debug;
2811		SCTP_INP_RUNLOCK(inp);
2812		*optsize = sizeof(uint32_t);
2813		break;
2814	}
2815	case SCTP_GET_LOCAL_ADDR_SIZE:
2816	{
2817		uint32_t *value;
2818
2819		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2820		SCTP_INP_RLOCK(inp);
2821		*value = sctp_count_max_addresses(inp);
2822		SCTP_INP_RUNLOCK(inp);
2823		*optsize = sizeof(uint32_t);
2824		break;
2825	}
2826	case SCTP_GET_REMOTE_ADDR_SIZE:
2827	{
2828		uint32_t *value;
2829		size_t size;
2830		struct sctp_nets *net;
2831
2832		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2833		/* FIXME MT: change to sctp_assoc_value? */
2834		SCTP_FIND_STCB(inp, stcb, (sctp_assoc_t) *value);
2835
2836		if (stcb) {
2837			size = 0;
2838			/* Count the sizes */
2839			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
2840				if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
2841					size += sizeof(struct sockaddr_in6);
2842				} else {
2843					switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) {
2844#ifdef INET
2845					case AF_INET:
2846						size += sizeof(struct sockaddr_in);
2847						break;
2848#endif
2849#ifdef INET6
2850					case AF_INET6:
2851						size += sizeof(struct sockaddr_in6);
2852						break;
2853#endif
2854#if defined(__Userspace__)
2855					case AF_CONN:
2856						size += sizeof(struct sockaddr_conn);
2857						break;
2858#endif
2859					default:
2860						break;
2861					}
2862				}
2863			}
2864			SCTP_TCB_UNLOCK(stcb);
2865			*value = (uint32_t) size;
2866			*optsize = sizeof(uint32_t);
2867		} else {
2868			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
2869			error = ENOTCONN;
2870		}
2871		break;
2872	}
2873	case SCTP_GET_PEER_ADDRESSES:
2874		/*
2875		 * Get the address information, an array is passed in to
2876		 * fill up we pack it.
2877		 */
2878	{
2879		size_t cpsz, left;
2880		struct sockaddr_storage *sas;
2881		struct sctp_nets *net;
2882		struct sctp_getaddresses *saddr;
2883
2884		SCTP_CHECK_AND_CAST(saddr, optval, struct sctp_getaddresses, *optsize);
2885		SCTP_FIND_STCB(inp, stcb, saddr->sget_assoc_id);
2886
2887		if (stcb) {
2888			left = (*optsize) - sizeof(struct sctp_getaddresses);
2889			*optsize = sizeof(struct sctp_getaddresses);
2890			sas = (struct sockaddr_storage *)&saddr->addr[0];
2891
2892			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
2893				if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
2894					cpsz = sizeof(struct sockaddr_in6);
2895				} else {
2896					switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) {
2897#ifdef INET
2898					case AF_INET:
2899						cpsz = sizeof(struct sockaddr_in);
2900						break;
2901#endif
2902#ifdef INET6
2903					case AF_INET6:
2904						cpsz = sizeof(struct sockaddr_in6);
2905						break;
2906#endif
2907#if defined(__Userspace__)
2908					case AF_CONN:
2909						cpsz = sizeof(struct sockaddr_conn);
2910						break;
2911#endif
2912					default:
2913						cpsz = 0;
2914						break;
2915					}
2916				}
2917				if (cpsz == 0) {
2918					break;
2919				}
2920				if (left < cpsz) {
2921					/* not enough room. */
2922					break;
2923				}
2924#if defined(INET) && defined(INET6)
2925				if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) &&
2926				    (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET)) {
2927					/* Must map the address */
2928					in6_sin_2_v4mapsin6((struct sockaddr_in *)&net->ro._l_addr,
2929							    (struct sockaddr_in6 *)sas);
2930				} else {
2931#endif
2932					memcpy(sas, &net->ro._l_addr, cpsz);
2933#if defined(INET) && defined(INET6)
2934				}
2935#endif
2936				((struct sockaddr_in *)sas)->sin_port = stcb->rport;
2937
2938				sas = (struct sockaddr_storage *)((caddr_t)sas + cpsz);
2939				left -= cpsz;
2940				*optsize += cpsz;
2941			}
2942			SCTP_TCB_UNLOCK(stcb);
2943		} else {
2944		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
2945			error = ENOENT;
2946		}
2947		break;
2948	}
2949	case SCTP_GET_LOCAL_ADDRESSES:
2950	{
2951		size_t limit, actual;
2952		struct sockaddr_storage *sas;
2953		struct sctp_getaddresses *saddr;
2954
2955		SCTP_CHECK_AND_CAST(saddr, optval, struct sctp_getaddresses, *optsize);
2956		SCTP_FIND_STCB(inp, stcb, saddr->sget_assoc_id);
2957
2958		sas = (struct sockaddr_storage *)&saddr->addr[0];
2959		limit = *optsize - sizeof(sctp_assoc_t);
2960		actual = sctp_fill_up_addresses(inp, stcb, limit, sas);
2961		if (stcb) {
2962			SCTP_TCB_UNLOCK(stcb);
2963		}
2964		*optsize = sizeof(struct sockaddr_storage) + actual;
2965		break;
2966	}
2967	case SCTP_PEER_ADDR_PARAMS:
2968	{
2969		struct sctp_paddrparams *paddrp;
2970		struct sctp_nets *net;
2971
2972		SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, *optsize);
2973		SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
2974
2975		net = NULL;
2976		if (stcb) {
2977			net = sctp_findnet(stcb, (struct sockaddr *)&paddrp->spp_address);
2978		} else {
2979			/* We increment here since sctp_findassociation_ep_addr() wil
2980			 * do a decrement if it finds the stcb as long as the locked
2981			 * tcb (last argument) is NOT a TCB.. aka NULL.
2982			 */
2983			SCTP_INP_INCR_REF(inp);
2984			stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&paddrp->spp_address, &net, NULL, NULL);
2985			if (stcb == NULL) {
2986				SCTP_INP_DECR_REF(inp);
2987			}
2988		}
2989		if (stcb && (net == NULL)) {
2990			struct sockaddr *sa;
2991
2992			sa = (struct sockaddr *)&paddrp->spp_address;
2993#ifdef INET
2994			if (sa->sa_family == AF_INET) {
2995				struct sockaddr_in *sin;
2996
2997				sin = (struct sockaddr_in *)sa;
2998				if (sin->sin_addr.s_addr) {
2999					error = EINVAL;
3000					SCTP_TCB_UNLOCK(stcb);
3001					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3002					break;
3003				}
3004			} else
3005#endif
3006#ifdef INET6
3007			if (sa->sa_family == AF_INET6) {
3008				struct sockaddr_in6 *sin6;
3009
3010				sin6 = (struct sockaddr_in6 *)sa;
3011				if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
3012					error = EINVAL;
3013					SCTP_TCB_UNLOCK(stcb);
3014					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3015					break;
3016				}
3017			} else
3018#endif
3019#if defined(__Userspace__)
3020			if (sa->sa_family == AF_CONN) {
3021				struct sockaddr_conn *sconn;
3022
3023				sconn = (struct sockaddr_conn *)sa;
3024				if (sconn->sconn_addr != NULL) {
3025					error = EINVAL;
3026					SCTP_TCB_UNLOCK(stcb);
3027					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3028					break;
3029				}
3030			} else
3031#endif
3032			{
3033				error = EAFNOSUPPORT;
3034				SCTP_TCB_UNLOCK(stcb);
3035				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3036				break;
3037			}
3038		}
3039
3040		if (stcb) {
3041			/* Applies to the specific association */
3042			paddrp->spp_flags = 0;
3043			if (net) {
3044				int ovh;
3045				if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
3046					ovh = SCTP_MED_OVERHEAD;
3047				} else {
3048					ovh = SCTP_MED_V4_OVERHEAD;
3049				}
3050
3051				paddrp->spp_hbinterval = net->heart_beat_delay;
3052				paddrp->spp_pathmaxrxt = net->failure_threshold;
3053				paddrp->spp_pathmtu = net->mtu - ovh;
3054				/* get flags for HB */
3055				if (net->dest_state & SCTP_ADDR_NOHB) {
3056					paddrp->spp_flags |= SPP_HB_DISABLE;
3057				} else {
3058					paddrp->spp_flags |= SPP_HB_ENABLE;
3059				}
3060				/* get flags for PMTU */
3061				if (net->dest_state & SCTP_ADDR_NO_PMTUD) {
3062					paddrp->spp_flags |= SPP_PMTUD_ENABLE;
3063				} else {
3064					paddrp->spp_flags |= SPP_PMTUD_DISABLE;
3065				}
3066				if (net->dscp & 0x01) {
3067					paddrp->spp_dscp = net->dscp & 0xfc;
3068					paddrp->spp_flags |= SPP_DSCP;
3069				}
3070#ifdef INET6
3071				if ((net->ro._l_addr.sa.sa_family == AF_INET6) &&
3072				    (net->flowlabel & 0x80000000)) {
3073					paddrp->spp_ipv6_flowlabel = net->flowlabel & 0x000fffff;
3074					paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
3075				}
3076#endif
3077			} else {
3078				/*
3079				 * No destination so return default
3080				 * value
3081				 */
3082				paddrp->spp_pathmaxrxt = stcb->asoc.def_net_failure;
3083				paddrp->spp_pathmtu = sctp_get_frag_point(stcb, &stcb->asoc);
3084				if (stcb->asoc.default_dscp & 0x01) {
3085					paddrp->spp_dscp = stcb->asoc.default_dscp & 0xfc;
3086					paddrp->spp_flags |= SPP_DSCP;
3087				}
3088#ifdef INET6
3089				if (stcb->asoc.default_flowlabel & 0x80000000) {
3090					paddrp->spp_ipv6_flowlabel = stcb->asoc.default_flowlabel & 0x000fffff;
3091					paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
3092				}
3093#endif
3094				/* default settings should be these */
3095				if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
3096					paddrp->spp_flags |= SPP_HB_DISABLE;
3097				} else {
3098					paddrp->spp_flags |= SPP_HB_ENABLE;
3099				}
3100				if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD)) {
3101					paddrp->spp_flags |= SPP_PMTUD_DISABLE;
3102				} else {
3103					paddrp->spp_flags |= SPP_PMTUD_ENABLE;
3104				}
3105				paddrp->spp_hbinterval = stcb->asoc.heart_beat_delay;
3106			}
3107			paddrp->spp_assoc_id = sctp_get_associd(stcb);
3108			SCTP_TCB_UNLOCK(stcb);
3109		} else {
3110			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3111			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3112			    (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC)) {
3113				/* Use endpoint defaults */
3114				SCTP_INP_RLOCK(inp);
3115				paddrp->spp_pathmaxrxt = inp->sctp_ep.def_net_failure;
3116				paddrp->spp_hbinterval = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]);
3117				paddrp->spp_assoc_id = SCTP_FUTURE_ASSOC;
3118				/* get inp's default */
3119				if (inp->sctp_ep.default_dscp & 0x01) {
3120					paddrp->spp_dscp = inp->sctp_ep.default_dscp & 0xfc;
3121					paddrp->spp_flags |= SPP_DSCP;
3122				}
3123#ifdef INET6
3124				if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
3125				    (inp->sctp_ep.default_flowlabel & 0x80000000)) {
3126					paddrp->spp_ipv6_flowlabel = inp->sctp_ep.default_flowlabel & 0x000fffff;
3127					paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
3128				}
3129#endif
3130				/* can't return this */
3131				paddrp->spp_pathmtu = 0;
3132
3133				if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
3134					paddrp->spp_flags |= SPP_HB_ENABLE;
3135				} else {
3136					paddrp->spp_flags |= SPP_HB_DISABLE;
3137				}
3138				if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD)) {
3139					paddrp->spp_flags |= SPP_PMTUD_ENABLE;
3140				} else {
3141					paddrp->spp_flags |= SPP_PMTUD_DISABLE;
3142				}
3143				SCTP_INP_RUNLOCK(inp);
3144			} else {
3145				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3146				error = EINVAL;
3147			}
3148		}
3149		if (error == 0) {
3150			*optsize = sizeof(struct sctp_paddrparams);
3151		}
3152		break;
3153	}
3154	case SCTP_GET_PEER_ADDR_INFO:
3155	{
3156		struct sctp_paddrinfo *paddri;
3157		struct sctp_nets *net;
3158
3159		SCTP_CHECK_AND_CAST(paddri, optval, struct sctp_paddrinfo, *optsize);
3160		SCTP_FIND_STCB(inp, stcb, paddri->spinfo_assoc_id);
3161
3162		net = NULL;
3163		if (stcb) {
3164			net = sctp_findnet(stcb, (struct sockaddr *)&paddri->spinfo_address);
3165		} else {
3166			/* We increment here since sctp_findassociation_ep_addr() wil
3167			 * do a decrement if it finds the stcb as long as the locked
3168			 * tcb (last argument) is NOT a TCB.. aka NULL.
3169			 */
3170			SCTP_INP_INCR_REF(inp);
3171			stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&paddri->spinfo_address, &net, NULL, NULL);
3172			if (stcb == NULL) {
3173				SCTP_INP_DECR_REF(inp);
3174			}
3175		}
3176
3177		if ((stcb) && (net)) {
3178			if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
3179				/* It's unconfirmed */
3180				paddri->spinfo_state = SCTP_UNCONFIRMED;
3181			} else if (net->dest_state & SCTP_ADDR_REACHABLE) {
3182				/* It's active */
3183				paddri->spinfo_state = SCTP_ACTIVE;
3184			} else {
3185				/* It's inactive */
3186				paddri->spinfo_state = SCTP_INACTIVE;
3187			}
3188			paddri->spinfo_cwnd = net->cwnd;
3189			paddri->spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT;
3190			paddri->spinfo_rto = net->RTO;
3191			paddri->spinfo_assoc_id = sctp_get_associd(stcb);
3192			paddri->spinfo_mtu = net->mtu;
3193			SCTP_TCB_UNLOCK(stcb);
3194			*optsize = sizeof(struct sctp_paddrinfo);
3195		} else {
3196			if (stcb) {
3197				SCTP_TCB_UNLOCK(stcb);
3198			}
3199		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
3200			error = ENOENT;
3201		}
3202		break;
3203	}
3204	case SCTP_PCB_STATUS:
3205	{
3206		struct sctp_pcbinfo *spcb;
3207
3208		SCTP_CHECK_AND_CAST(spcb, optval, struct sctp_pcbinfo, *optsize);
3209		sctp_fill_pcbinfo(spcb);
3210		*optsize = sizeof(struct sctp_pcbinfo);
3211		break;
3212	}
3213	case SCTP_STATUS:
3214	{
3215		struct sctp_nets *net;
3216		struct sctp_status *sstat;
3217
3218		SCTP_CHECK_AND_CAST(sstat, optval, struct sctp_status, *optsize);
3219		SCTP_FIND_STCB(inp, stcb, sstat->sstat_assoc_id);
3220
3221		if (stcb == NULL) {
3222			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3223			error = EINVAL;
3224			break;
3225		}
3226		/*
3227		 * I think passing the state is fine since
3228		 * sctp_constants.h will be available to the user
3229		 * land.
3230		 */
3231		sstat->sstat_state = stcb->asoc.state;
3232		sstat->sstat_assoc_id = sctp_get_associd(stcb);
3233		sstat->sstat_rwnd = stcb->asoc.peers_rwnd;
3234		sstat->sstat_unackdata = stcb->asoc.sent_queue_cnt;
3235		/*
3236		 * We can't include chunks that have been passed to
3237		 * the socket layer. Only things in queue.
3238		 */
3239		sstat->sstat_penddata = (stcb->asoc.cnt_on_reasm_queue +
3240					 stcb->asoc.cnt_on_all_streams);
3241
3242
3243		sstat->sstat_instrms = stcb->asoc.streamincnt;
3244		sstat->sstat_outstrms = stcb->asoc.streamoutcnt;
3245		sstat->sstat_fragmentation_point = sctp_get_frag_point(stcb, &stcb->asoc);
3246#ifdef HAVE_SA_LEN
3247		memcpy(&sstat->sstat_primary.spinfo_address,
3248		       &stcb->asoc.primary_destination->ro._l_addr,
3249		       ((struct sockaddr *)(&stcb->asoc.primary_destination->ro._l_addr))->sa_len);
3250#else
3251		if (stcb->asoc.primary_destination->ro._l_addr.sa.sa_family == AF_INET) {
3252			memcpy(&sstat->sstat_primary.spinfo_address,
3253			       &stcb->asoc.primary_destination->ro._l_addr,
3254			       sizeof(struct sockaddr_in));
3255		} else {
3256			memcpy(&sstat->sstat_primary.spinfo_address,
3257			       &stcb->asoc.primary_destination->ro._l_addr,
3258			       sizeof(struct sockaddr_in6));
3259		}
3260#endif
3261		net = stcb->asoc.primary_destination;
3262		((struct sockaddr_in *)&sstat->sstat_primary.spinfo_address)->sin_port = stcb->rport;
3263		/*
3264		 * Again the user can get info from sctp_constants.h
3265		 * for what the state of the network is.
3266		 */
3267		if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
3268			/* It's unconfirmed */
3269			sstat->sstat_primary.spinfo_state = SCTP_UNCONFIRMED;
3270		} else if (net->dest_state & SCTP_ADDR_REACHABLE) {
3271			/* It's active */
3272			sstat->sstat_primary.spinfo_state = SCTP_ACTIVE;
3273		} else {
3274			/* It's inactive */
3275			sstat->sstat_primary.spinfo_state = SCTP_INACTIVE;
3276		}
3277		sstat->sstat_primary.spinfo_cwnd = net->cwnd;
3278		sstat->sstat_primary.spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT;
3279		sstat->sstat_primary.spinfo_rto = net->RTO;
3280		sstat->sstat_primary.spinfo_mtu = net->mtu;
3281		sstat->sstat_primary.spinfo_assoc_id = sctp_get_associd(stcb);
3282		SCTP_TCB_UNLOCK(stcb);
3283		*optsize = sizeof(struct sctp_status);
3284		break;
3285	}
3286	case SCTP_RTOINFO:
3287	{
3288		struct sctp_rtoinfo *srto;
3289
3290		SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, *optsize);
3291		SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
3292
3293		if (stcb) {
3294			srto->srto_initial = stcb->asoc.initial_rto;
3295			srto->srto_max = stcb->asoc.maxrto;
3296			srto->srto_min = stcb->asoc.minrto;
3297			SCTP_TCB_UNLOCK(stcb);
3298		} else {
3299			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3300			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3301			    (srto->srto_assoc_id == SCTP_FUTURE_ASSOC)) {
3302				SCTP_INP_RLOCK(inp);
3303				srto->srto_initial = inp->sctp_ep.initial_rto;
3304				srto->srto_max = inp->sctp_ep.sctp_maxrto;
3305				srto->srto_min = inp->sctp_ep.sctp_minrto;
3306				SCTP_INP_RUNLOCK(inp);
3307			} else {
3308				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3309				error = EINVAL;
3310			}
3311		}
3312		if (error == 0) {
3313			*optsize = sizeof(struct sctp_rtoinfo);
3314		}
3315		break;
3316	}
3317	case SCTP_TIMEOUTS:
3318	{
3319		struct sctp_timeouts *stimo;
3320
3321		SCTP_CHECK_AND_CAST(stimo, optval, struct sctp_timeouts, *optsize);
3322		SCTP_FIND_STCB(inp, stcb, stimo->stimo_assoc_id);
3323
3324		if (stcb) {
3325			stimo->stimo_init= stcb->asoc.timoinit;
3326			stimo->stimo_data= stcb->asoc.timodata;
3327			stimo->stimo_sack= stcb->asoc.timosack;
3328			stimo->stimo_shutdown= stcb->asoc.timoshutdown;
3329			stimo->stimo_heartbeat= stcb->asoc.timoheartbeat;
3330			stimo->stimo_cookie= stcb->asoc.timocookie;
3331			stimo->stimo_shutdownack= stcb->asoc.timoshutdownack;
3332			SCTP_TCB_UNLOCK(stcb);
3333			*optsize = sizeof(struct sctp_timeouts);
3334		} else {
3335			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3336			error = EINVAL;
3337		}
3338		break;
3339	}
3340	case SCTP_ASSOCINFO:
3341	{
3342		struct sctp_assocparams *sasoc;
3343
3344		SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, *optsize);
3345		SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
3346
3347		if (stcb) {
3348			sasoc->sasoc_cookie_life = TICKS_TO_MSEC(stcb->asoc.cookie_life);
3349			sasoc->sasoc_asocmaxrxt = stcb->asoc.max_send_times;
3350			sasoc->sasoc_number_peer_destinations = stcb->asoc.numnets;
3351			sasoc->sasoc_peer_rwnd = stcb->asoc.peers_rwnd;
3352			sasoc->sasoc_local_rwnd = stcb->asoc.my_rwnd;
3353			SCTP_TCB_UNLOCK(stcb);
3354		} else {
3355			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3356			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3357			    (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC)) {
3358				SCTP_INP_RLOCK(inp);
3359				sasoc->sasoc_cookie_life = TICKS_TO_MSEC(inp->sctp_ep.def_cookie_life);
3360				sasoc->sasoc_asocmaxrxt = inp->sctp_ep.max_send_times;
3361				sasoc->sasoc_number_peer_destinations = 0;
3362				sasoc->sasoc_peer_rwnd = 0;
3363				sasoc->sasoc_local_rwnd = sbspace(&inp->sctp_socket->so_rcv);
3364				SCTP_INP_RUNLOCK(inp);
3365			} else {
3366				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3367				error = EINVAL;
3368			}
3369		}
3370		if (error == 0) {
3371			*optsize = sizeof(struct sctp_assocparams);
3372		}
3373		break;
3374	}
3375	case SCTP_DEFAULT_SEND_PARAM:
3376	{
3377		struct sctp_sndrcvinfo *s_info;
3378
3379		SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, *optsize);
3380		SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
3381
3382		if (stcb) {
3383			memcpy(s_info, &stcb->asoc.def_send, sizeof(stcb->asoc.def_send));
3384			SCTP_TCB_UNLOCK(stcb);
3385		} else {
3386			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3387			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3388			    (s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC)) {
3389				SCTP_INP_RLOCK(inp);
3390				memcpy(s_info, &inp->def_send, sizeof(inp->def_send));
3391				SCTP_INP_RUNLOCK(inp);
3392			} else {
3393				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3394				error = EINVAL;
3395			}
3396		}
3397		if (error == 0) {
3398			*optsize = sizeof(struct sctp_sndrcvinfo);
3399		}
3400		break;
3401	}
3402	case SCTP_INITMSG:
3403	{
3404		struct sctp_initmsg *sinit;
3405
3406		SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, *optsize);
3407		SCTP_INP_RLOCK(inp);
3408		sinit->sinit_num_ostreams = inp->sctp_ep.pre_open_stream_count;
3409		sinit->sinit_max_instreams = inp->sctp_ep.max_open_streams_intome;
3410		sinit->sinit_max_attempts = inp->sctp_ep.max_init_times;
3411		sinit->sinit_max_init_timeo = inp->sctp_ep.initial_init_rto_max;
3412		SCTP_INP_RUNLOCK(inp);
3413		*optsize = sizeof(struct sctp_initmsg);
3414		break;
3415	}
3416	case SCTP_PRIMARY_ADDR:
3417		/* we allow a "get" operation on this */
3418	{
3419		struct sctp_setprim *ssp;
3420
3421		SCTP_CHECK_AND_CAST(ssp, optval, struct sctp_setprim, *optsize);
3422		SCTP_FIND_STCB(inp, stcb, ssp->ssp_assoc_id);
3423
3424		if (stcb) {
3425			/* simply copy out the sockaddr_storage... */
3426			size_t len;
3427
3428			len = *optsize;
3429#ifdef HAVE_SA_LEN
3430			if (len > stcb->asoc.primary_destination->ro._l_addr.sa.sa_len)
3431				len = stcb->asoc.primary_destination->ro._l_addr.sa.sa_len;
3432#else
3433			if (stcb->asoc.primary_destination->ro._l_addr.sa.sa_family == AF_INET &&
3434			    len > sizeof(struct sockaddr_in))
3435				len = sizeof(struct sockaddr_in);
3436			else if (
3437			    stcb->asoc.primary_destination->ro._l_addr.sa.sa_family == AF_INET6 &&
3438			    len > sizeof(struct sockaddr_in6))
3439				len = sizeof(struct sockaddr_in6);
3440#endif
3441
3442			memcpy(&ssp->ssp_addr,
3443			       &stcb->asoc.primary_destination->ro._l_addr,
3444			       len);
3445			SCTP_TCB_UNLOCK(stcb);
3446			*optsize = sizeof(struct sctp_setprim);
3447		} else {
3448			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3449			error = EINVAL;
3450		}
3451		break;
3452	}
3453	case SCTP_HMAC_IDENT:
3454	{
3455		struct sctp_hmacalgo *shmac;
3456		sctp_hmaclist_t *hmaclist;
3457		uint32_t size;
3458		int i;
3459
3460		SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, *optsize);
3461
3462		SCTP_INP_RLOCK(inp);
3463		hmaclist = inp->sctp_ep.local_hmacs;
3464		if (hmaclist == NULL) {
3465			/* no HMACs to return */
3466			*optsize = sizeof(*shmac);
3467			SCTP_INP_RUNLOCK(inp);
3468			break;
3469		}
3470		/* is there room for all of the hmac ids? */
3471		size = sizeof(*shmac) + (hmaclist->num_algo *
3472					 sizeof(shmac->shmac_idents[0]));
3473		if ((size_t)(*optsize) < size) {
3474			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3475			error = EINVAL;
3476			SCTP_INP_RUNLOCK(inp);
3477			break;
3478		}
3479		/* copy in the list */
3480		shmac->shmac_number_of_idents = hmaclist->num_algo;
3481		for (i = 0; i < hmaclist->num_algo; i++) {
3482			shmac->shmac_idents[i] = hmaclist->hmac[i];
3483		}
3484		SCTP_INP_RUNLOCK(inp);
3485		*optsize = size;
3486		break;
3487	}
3488	case SCTP_AUTH_ACTIVE_KEY:
3489	{
3490		struct sctp_authkeyid *scact;
3491
3492		SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, *optsize);
3493		SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id);
3494
3495		if (stcb) {
3496			/* get the active key on the assoc */
3497			scact->scact_keynumber = stcb->asoc.authinfo.active_keyid;
3498			SCTP_TCB_UNLOCK(stcb);
3499		} else {
3500			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3501			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3502			    (scact->scact_assoc_id == SCTP_FUTURE_ASSOC)) {
3503				/* get the endpoint active key */
3504				SCTP_INP_RLOCK(inp);
3505				scact->scact_keynumber = inp->sctp_ep.default_keyid;
3506				SCTP_INP_RUNLOCK(inp);
3507			} else {
3508				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3509				error = EINVAL;
3510			}
3511		}
3512		if (error == 0) {
3513			*optsize = sizeof(struct sctp_authkeyid);
3514		}
3515		break;
3516	}
3517	case SCTP_LOCAL_AUTH_CHUNKS:
3518	{
3519		struct sctp_authchunks *sac;
3520		sctp_auth_chklist_t *chklist = NULL;
3521		size_t size = 0;
3522
3523		SCTP_CHECK_AND_CAST(sac, optval, struct sctp_authchunks, *optsize);
3524		SCTP_FIND_STCB(inp, stcb, sac->gauth_assoc_id);
3525
3526		if (stcb) {
3527			/* get off the assoc */
3528			chklist = stcb->asoc.local_auth_chunks;
3529			/* is there enough space? */
3530			size = sctp_auth_get_chklist_size(chklist);
3531			if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
3532				error = EINVAL;
3533				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3534			} else {
3535				/* copy in the chunks */
3536				(void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
3537				sac->gauth_number_of_chunks = (uint32_t)size;
3538				*optsize = sizeof(struct sctp_authchunks) + size;
3539			}
3540			SCTP_TCB_UNLOCK(stcb);
3541		} else {
3542			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3543			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3544			    (sac->gauth_assoc_id == SCTP_FUTURE_ASSOC)) {
3545				/* get off the endpoint */
3546				SCTP_INP_RLOCK(inp);
3547				chklist = inp->sctp_ep.local_auth_chunks;
3548				/* is there enough space? */
3549				size = sctp_auth_get_chklist_size(chklist);
3550				if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
3551					error = EINVAL;
3552					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3553				} else {
3554					/* copy in the chunks */
3555					(void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
3556					sac->gauth_number_of_chunks = (uint32_t)size;
3557					*optsize = sizeof(struct sctp_authchunks) + size;
3558				}
3559				SCTP_INP_RUNLOCK(inp);
3560			} else {
3561				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3562				error = EINVAL;
3563			}
3564		}
3565		break;
3566	}
3567	case SCTP_PEER_AUTH_CHUNKS:
3568	{
3569		struct sctp_authchunks *sac;
3570		sctp_auth_chklist_t *chklist = NULL;
3571		size_t size = 0;
3572
3573		SCTP_CHECK_AND_CAST(sac, optval, struct sctp_authchunks, *optsize);
3574		SCTP_FIND_STCB(inp, stcb, sac->gauth_assoc_id);
3575
3576		if (stcb) {
3577			/* get off the assoc */
3578			chklist = stcb->asoc.peer_auth_chunks;
3579			/* is there enough space? */
3580			size = sctp_auth_get_chklist_size(chklist);
3581			if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
3582				error = EINVAL;
3583				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3584			} else {
3585				/* copy in the chunks */
3586				(void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
3587				sac->gauth_number_of_chunks = (uint32_t)size;
3588				*optsize = sizeof(struct sctp_authchunks) + size;
3589			}
3590			SCTP_TCB_UNLOCK(stcb);
3591		} else {
3592		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
3593			error = ENOENT;
3594		}
3595		break;
3596	}
3597#if defined(HAVE_SCTP_PEELOFF_SOCKOPT)
3598	case SCTP_PEELOFF:
3599	{
3600		struct sctp_peeloff_opt *peeloff;
3601
3602		SCTP_CHECK_AND_CAST(peeloff, optval, struct sctp_peeloff_opt, *optsize);
3603		/* do the peeloff */
3604		error = sctp_peeloff_option(p, peeloff);
3605		if (error == 0) {
3606			*optsize = sizeof(struct sctp_peeloff_opt);
3607		}
3608	}
3609	break;
3610#endif /* HAVE_SCTP_PEELOFF_SOCKOPT */
3611	case SCTP_EVENT:
3612	{
3613		struct sctp_event *event;
3614		uint32_t event_type;
3615
3616		SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, *optsize);
3617		SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
3618
3619		switch (event->se_type) {
3620		case SCTP_ASSOC_CHANGE:
3621			event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
3622			break;
3623		case SCTP_PEER_ADDR_CHANGE:
3624			event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
3625			break;
3626		case SCTP_REMOTE_ERROR:
3627			event_type = SCTP_PCB_FLAGS_RECVPEERERR;
3628			break;
3629		case SCTP_SEND_FAILED:
3630			event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
3631			break;
3632		case SCTP_SHUTDOWN_EVENT:
3633			event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
3634			break;
3635		case SCTP_ADAPTATION_INDICATION:
3636			event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
3637			break;
3638		case SCTP_PARTIAL_DELIVERY_EVENT:
3639			event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
3640			break;
3641		case SCTP_AUTHENTICATION_EVENT:
3642			event_type = SCTP_PCB_FLAGS_AUTHEVNT;
3643			break;
3644		case SCTP_STREAM_RESET_EVENT:
3645			event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
3646			break;
3647		case SCTP_SENDER_DRY_EVENT:
3648			event_type = SCTP_PCB_FLAGS_DRYEVNT;
3649			break;
3650		case SCTP_NOTIFICATIONS_STOPPED_EVENT:
3651			event_type = 0;
3652			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
3653			error = ENOTSUP;
3654			break;
3655		case SCTP_ASSOC_RESET_EVENT:
3656			event_type = SCTP_PCB_FLAGS_ASSOC_RESETEVNT;
3657			break;
3658		case SCTP_STREAM_CHANGE_EVENT:
3659			event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT;
3660			break;
3661		case SCTP_SEND_FAILED_EVENT:
3662			event_type = SCTP_PCB_FLAGS_RECVNSENDFAILEVNT;
3663			break;
3664		default:
3665			event_type = 0;
3666			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3667			error = EINVAL;
3668			break;
3669		}
3670		if (event_type > 0) {
3671			if (stcb) {
3672				event->se_on = sctp_stcb_is_feature_on(inp, stcb, event_type);
3673				SCTP_TCB_UNLOCK(stcb);
3674			} else {
3675				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3676				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3677				    (event->se_assoc_id == SCTP_FUTURE_ASSOC)) {
3678					SCTP_INP_RLOCK(inp);
3679					event->se_on = sctp_is_feature_on(inp, event_type);
3680					SCTP_INP_RUNLOCK(inp);
3681				} else {
3682					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3683					error = EINVAL;
3684				}
3685			}
3686		}
3687		if (error == 0) {
3688			*optsize = sizeof(struct sctp_event);
3689		}
3690		break;
3691	}
3692	case SCTP_RECVRCVINFO:
3693	{
3694		int onoff;
3695
3696		if (*optsize < sizeof(int)) {
3697			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3698			error = EINVAL;
3699		} else {
3700			SCTP_INP_RLOCK(inp);
3701			onoff = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
3702			SCTP_INP_RUNLOCK(inp);
3703		}
3704		if (error == 0) {
3705			/* return the option value */
3706			*(int *)optval = onoff;
3707			*optsize = sizeof(int);
3708		}
3709		break;
3710	}
3711	case SCTP_RECVNXTINFO:
3712	{
3713		int onoff;
3714
3715		if (*optsize < sizeof(int)) {
3716			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3717			error = EINVAL;
3718		} else {
3719			SCTP_INP_RLOCK(inp);
3720			onoff = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
3721			SCTP_INP_RUNLOCK(inp);
3722		}
3723		if (error == 0) {
3724			/* return the option value */
3725			*(int *)optval = onoff;
3726			*optsize = sizeof(int);
3727		}
3728		break;
3729	}
3730	case SCTP_DEFAULT_SNDINFO:
3731	{
3732		struct sctp_sndinfo *info;
3733
3734		SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, *optsize);
3735		SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
3736
3737		if (stcb) {
3738			info->snd_sid = stcb->asoc.def_send.sinfo_stream;
3739			info->snd_flags = stcb->asoc.def_send.sinfo_flags;
3740			info->snd_flags &= 0xfff0;
3741			info->snd_ppid = stcb->asoc.def_send.sinfo_ppid;
3742			info->snd_context = stcb->asoc.def_send.sinfo_context;
3743			SCTP_TCB_UNLOCK(stcb);
3744		} else {
3745			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3746			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3747			    (info->snd_assoc_id == SCTP_FUTURE_ASSOC)) {
3748				SCTP_INP_RLOCK(inp);
3749				info->snd_sid = inp->def_send.sinfo_stream;
3750				info->snd_flags = inp->def_send.sinfo_flags;
3751				info->snd_flags &= 0xfff0;
3752				info->snd_ppid = inp->def_send.sinfo_ppid;
3753				info->snd_context = inp->def_send.sinfo_context;
3754				SCTP_INP_RUNLOCK(inp);
3755			} else {
3756				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3757				error = EINVAL;
3758			}
3759		}
3760		if (error == 0) {
3761			*optsize = sizeof(struct sctp_sndinfo);
3762		}
3763		break;
3764	}
3765	case SCTP_DEFAULT_PRINFO:
3766	{
3767		struct sctp_default_prinfo *info;
3768
3769		SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, *optsize);
3770		SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
3771
3772		if (stcb) {
3773			info->pr_policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
3774			info->pr_value = stcb->asoc.def_send.sinfo_timetolive;
3775			SCTP_TCB_UNLOCK(stcb);
3776		} else {
3777			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3778			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3779			    (info->pr_assoc_id == SCTP_FUTURE_ASSOC)) {
3780				SCTP_INP_RLOCK(inp);
3781				info->pr_policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
3782				info->pr_value = inp->def_send.sinfo_timetolive;
3783				SCTP_INP_RUNLOCK(inp);
3784			} else {
3785				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3786				error = EINVAL;
3787			}
3788		}
3789		if (error == 0) {
3790			*optsize = sizeof(struct sctp_default_prinfo);
3791		}
3792		break;
3793	}
3794	case SCTP_PEER_ADDR_THLDS:
3795	{
3796		struct sctp_paddrthlds *thlds;
3797		struct sctp_nets *net;
3798
3799		SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, *optsize);
3800		SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
3801
3802		net = NULL;
3803		if (stcb) {
3804			net = sctp_findnet(stcb, (struct sockaddr *)&thlds->spt_address);
3805		} else {
3806			/* We increment here since sctp_findassociation_ep_addr() wil
3807			 * do a decrement if it finds the stcb as long as the locked
3808			 * tcb (last argument) is NOT a TCB.. aka NULL.
3809			 */
3810			SCTP_INP_INCR_REF(inp);
3811			stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&thlds->spt_address, &net, NULL, NULL);
3812			if (stcb == NULL) {
3813				SCTP_INP_DECR_REF(inp);
3814			}
3815		}
3816		if (stcb && (net == NULL)) {
3817			struct sockaddr *sa;
3818
3819			sa = (struct sockaddr *)&thlds->spt_address;
3820#ifdef INET
3821			if (sa->sa_family == AF_INET) {
3822				struct sockaddr_in *sin;
3823
3824				sin = (struct sockaddr_in *)sa;
3825				if (sin->sin_addr.s_addr) {
3826					error = EINVAL;
3827					SCTP_TCB_UNLOCK(stcb);
3828					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3829					break;
3830				}
3831			} else
3832#endif
3833#ifdef INET6
3834			if (sa->sa_family == AF_INET6) {
3835				struct sockaddr_in6 *sin6;
3836
3837				sin6 = (struct sockaddr_in6 *)sa;
3838				if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
3839					error = EINVAL;
3840					SCTP_TCB_UNLOCK(stcb);
3841					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3842					break;
3843				}
3844			} else
3845#endif
3846#if defined(__Userspace__)
3847			if (sa->sa_family == AF_CONN) {
3848				struct sockaddr_conn *sconn;
3849
3850				sconn = (struct sockaddr_conn *)sa;
3851				if (sconn->sconn_addr != NULL) {
3852					error = EINVAL;
3853					SCTP_TCB_UNLOCK(stcb);
3854					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3855					break;
3856				}
3857			} else
3858#endif
3859			{
3860				error = EAFNOSUPPORT;
3861				SCTP_TCB_UNLOCK(stcb);
3862				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3863				break;
3864			}
3865		}
3866
3867		if (stcb) {
3868			if (net) {
3869				thlds->spt_pathmaxrxt = net->failure_threshold;
3870				thlds->spt_pathpfthld = net->pf_threshold;
3871			} else {
3872				thlds->spt_pathmaxrxt = stcb->asoc.def_net_failure;
3873				thlds->spt_pathpfthld = stcb->asoc.def_net_pf_threshold;
3874			}
3875			thlds->spt_assoc_id = sctp_get_associd(stcb);
3876			SCTP_TCB_UNLOCK(stcb);
3877		} else {
3878			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3879			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3880			    (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC)) {
3881				/* Use endpoint defaults */
3882				SCTP_INP_RLOCK(inp);
3883				thlds->spt_pathmaxrxt = inp->sctp_ep.def_net_failure;
3884				thlds->spt_pathpfthld = inp->sctp_ep.def_net_pf_threshold;
3885				SCTP_INP_RUNLOCK(inp);
3886			} else {
3887				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3888				error = EINVAL;
3889			}
3890		}
3891		if (error == 0) {
3892			*optsize = sizeof(struct sctp_paddrthlds);
3893		}
3894		break;
3895	}
3896	case SCTP_REMOTE_UDP_ENCAPS_PORT:
3897	{
3898		struct sctp_udpencaps *encaps;
3899		struct sctp_nets *net;
3900
3901		SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, *optsize);
3902		SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
3903
3904		if (stcb) {
3905			net = sctp_findnet(stcb, (struct sockaddr *)&encaps->sue_address);
3906		} else {
3907			/* We increment here since sctp_findassociation_ep_addr() wil
3908			 * do a decrement if it finds the stcb as long as the locked
3909			 * tcb (last argument) is NOT a TCB.. aka NULL.
3910			 */
3911			net = NULL;
3912			SCTP_INP_INCR_REF(inp);
3913			stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&encaps->sue_address, &net, NULL, NULL);
3914			if (stcb == NULL) {
3915				SCTP_INP_DECR_REF(inp);
3916			}
3917		}
3918		if (stcb && (net == NULL)) {
3919			struct sockaddr *sa;
3920
3921			sa = (struct sockaddr *)&encaps->sue_address;
3922#ifdef INET
3923			if (sa->sa_family == AF_INET) {
3924				struct sockaddr_in *sin;
3925
3926				sin = (struct sockaddr_in *)sa;
3927				if (sin->sin_addr.s_addr) {
3928					error = EINVAL;
3929					SCTP_TCB_UNLOCK(stcb);
3930					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3931					break;
3932				}
3933			} else
3934#endif
3935#ifdef INET6
3936			if (sa->sa_family == AF_INET6) {
3937				struct sockaddr_in6 *sin6;
3938
3939				sin6 = (struct sockaddr_in6 *)sa;
3940				if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
3941					error = EINVAL;
3942					SCTP_TCB_UNLOCK(stcb);
3943					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3944					break;
3945				}
3946			} else
3947#endif
3948#if defined(__Userspace__)
3949			if (sa->sa_family == AF_CONN) {
3950				struct sockaddr_conn *sconn;
3951
3952				sconn = (struct sockaddr_conn *)sa;
3953				if (sconn->sconn_addr != NULL) {
3954					error = EINVAL;
3955					SCTP_TCB_UNLOCK(stcb);
3956					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3957					break;
3958				}
3959			} else
3960#endif
3961			{
3962				error = EAFNOSUPPORT;
3963				SCTP_TCB_UNLOCK(stcb);
3964				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3965				break;
3966			}
3967		}
3968
3969		if (stcb) {
3970			if (net) {
3971				encaps->sue_port = net->port;
3972			} else {
3973				encaps->sue_port = stcb->asoc.port;
3974			}
3975			SCTP_TCB_UNLOCK(stcb);
3976		} else {
3977			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3978			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3979			    (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC)) {
3980				SCTP_INP_RLOCK(inp);
3981				encaps->sue_port = inp->sctp_ep.port;
3982				SCTP_INP_RUNLOCK(inp);
3983			} else {
3984				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3985				error = EINVAL;
3986			}
3987		}
3988		if (error == 0) {
3989			*optsize = sizeof(struct sctp_udpencaps);
3990		}
3991		break;
3992	}
3993	case SCTP_ENABLE_STREAM_RESET:
3994	{
3995		struct sctp_assoc_value *av;
3996
3997		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
3998		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3999
4000		if (stcb) {
4001			av->assoc_value = (uint32_t)stcb->asoc.local_strreset_support;
4002			SCTP_TCB_UNLOCK(stcb);
4003		} else {
4004			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4005			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4006			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
4007				SCTP_INP_RLOCK(inp);
4008				av->assoc_value = (uint32_t)inp->local_strreset_support;
4009				SCTP_INP_RUNLOCK(inp);
4010			} else {
4011				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4012				error = EINVAL;
4013			}
4014		}
4015		if (error == 0) {
4016			*optsize = sizeof(struct sctp_assoc_value);
4017		}
4018		break;
4019	}
4020	default:
4021		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
4022		error = ENOPROTOOPT;
4023		break;
4024	} /* end switch (sopt->sopt_name) */
4025	if (error) {
4026		*optsize = 0;
4027	}
4028	return (error);
4029}
4030
4031#if defined(__Panda__) || defined(__Userspace__)
4032int
4033#else
4034static int
4035#endif
4036sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
4037	    void *p)
4038{
4039	int error, set_opt;
4040	uint32_t *mopt;
4041	struct sctp_tcb *stcb = NULL;
4042	struct sctp_inpcb *inp = NULL;
4043	uint32_t vrf_id;
4044
4045	if (optval == NULL) {
4046		SCTP_PRINTF("optval is NULL\n");
4047		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4048		return (EINVAL);
4049	}
4050	inp = (struct sctp_inpcb *)so->so_pcb;
4051	if (inp == NULL) {
4052		SCTP_PRINTF("inp is NULL?\n");
4053		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4054		return (EINVAL);
4055	}
4056	vrf_id = inp->def_vrf_id;
4057
4058	error = 0;
4059	switch (optname) {
4060	case SCTP_NODELAY:
4061	case SCTP_AUTOCLOSE:
4062	case SCTP_AUTO_ASCONF:
4063	case SCTP_EXPLICIT_EOR:
4064	case SCTP_DISABLE_FRAGMENTS:
4065	case SCTP_USE_EXT_RCVINFO:
4066	case SCTP_I_WANT_MAPPED_V4_ADDR:
4067		/* copy in the option value */
4068		SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
4069		set_opt = 0;
4070		if (error)
4071			break;
4072		switch (optname) {
4073		case SCTP_DISABLE_FRAGMENTS:
4074			set_opt = SCTP_PCB_FLAGS_NO_FRAGMENT;
4075			break;
4076		case SCTP_AUTO_ASCONF:
4077			/*
4078			 * NOTE: we don't really support this flag
4079			 */
4080			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
4081				/* only valid for bound all sockets */
4082				if ((SCTP_BASE_SYSCTL(sctp_auto_asconf) == 0) &&
4083				    (*mopt != 0)) {
4084					/* forbidden by admin */
4085					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EPERM);
4086					return (EPERM);
4087				}
4088				set_opt = SCTP_PCB_FLAGS_AUTO_ASCONF;
4089			} else {
4090				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4091				return (EINVAL);
4092			}
4093			break;
4094		case SCTP_EXPLICIT_EOR:
4095			set_opt = SCTP_PCB_FLAGS_EXPLICIT_EOR;
4096			break;
4097		case SCTP_USE_EXT_RCVINFO:
4098			set_opt = SCTP_PCB_FLAGS_EXT_RCVINFO;
4099			break;
4100		case SCTP_I_WANT_MAPPED_V4_ADDR:
4101			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
4102				set_opt = SCTP_PCB_FLAGS_NEEDS_MAPPED_V4;
4103			} else {
4104				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4105				return (EINVAL);
4106			}
4107			break;
4108		case SCTP_NODELAY:
4109			set_opt = SCTP_PCB_FLAGS_NODELAY;
4110			break;
4111		case SCTP_AUTOCLOSE:
4112			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4113			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
4114				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4115				return (EINVAL);
4116			}
4117			set_opt = SCTP_PCB_FLAGS_AUTOCLOSE;
4118			/*
4119			 * The value is in ticks. Note this does not effect
4120			 * old associations, only new ones.
4121			 */
4122			inp->sctp_ep.auto_close_time = SEC_TO_TICKS(*mopt);
4123			break;
4124		}
4125		SCTP_INP_WLOCK(inp);
4126		if (*mopt != 0) {
4127			sctp_feature_on(inp, set_opt);
4128		} else {
4129			sctp_feature_off(inp, set_opt);
4130		}
4131		SCTP_INP_WUNLOCK(inp);
4132		break;
4133	case SCTP_REUSE_PORT:
4134	{
4135		SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
4136		if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND)  == 0) {
4137			/* Can't set it after we are bound */
4138			error = EINVAL;
4139			break;
4140		}
4141		if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
4142			/* Can't do this for a 1-m socket */
4143			error = EINVAL;
4144			break;
4145		}
4146		if (optval)
4147			sctp_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE);
4148		else
4149			sctp_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE);
4150		break;
4151	}
4152	case SCTP_PARTIAL_DELIVERY_POINT:
4153	{
4154		uint32_t *value;
4155
4156		SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
4157		if (*value > SCTP_SB_LIMIT_RCV(so)) {
4158			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4159			error = EINVAL;
4160			break;
4161		}
4162		inp->partial_delivery_point = *value;
4163		break;
4164	}
4165	case SCTP_FRAGMENT_INTERLEAVE:
4166		/* not yet until we re-write sctp_recvmsg() */
4167	{
4168		uint32_t *level;
4169
4170		SCTP_CHECK_AND_CAST(level, optval, uint32_t, optsize);
4171		if (*level == SCTP_FRAG_LEVEL_2) {
4172			sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
4173			sctp_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
4174		} else if (*level == SCTP_FRAG_LEVEL_1) {
4175			sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
4176			sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
4177		} else if (*level == SCTP_FRAG_LEVEL_0) {
4178			sctp_feature_off(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
4179			sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
4180
4181		} else {
4182			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4183			error = EINVAL;
4184		}
4185		break;
4186	}
4187	case SCTP_CMT_ON_OFF:
4188		if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
4189			struct sctp_assoc_value *av;
4190
4191			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4192			if (av->assoc_value > SCTP_CMT_MAX) {
4193				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4194				error = EINVAL;
4195				break;
4196			}
4197			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4198			if (stcb) {
4199				stcb->asoc.sctp_cmt_on_off = av->assoc_value;
4200				SCTP_TCB_UNLOCK(stcb);
4201			} else {
4202				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4203				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4204				    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
4205				    (av->assoc_id == SCTP_ALL_ASSOC)) {
4206					SCTP_INP_WLOCK(inp);
4207					inp->sctp_cmt_on_off = av->assoc_value;
4208					SCTP_INP_WUNLOCK(inp);
4209				}
4210				if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4211				    (av->assoc_id == SCTP_ALL_ASSOC)) {
4212					SCTP_INP_RLOCK(inp);
4213					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4214						SCTP_TCB_LOCK(stcb);
4215						stcb->asoc.sctp_cmt_on_off = av->assoc_value;
4216						SCTP_TCB_UNLOCK(stcb);
4217					}
4218					SCTP_INP_RUNLOCK(inp);
4219				}
4220			}
4221		} else {
4222			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
4223			error = ENOPROTOOPT;
4224		}
4225		break;
4226	case SCTP_PLUGGABLE_CC:
4227	{
4228		struct sctp_assoc_value *av;
4229		struct sctp_nets *net;
4230
4231		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4232		if ((av->assoc_value != SCTP_CC_RFC2581) &&
4233		    (av->assoc_value != SCTP_CC_HSTCP) &&
4234		    (av->assoc_value != SCTP_CC_HTCP) &&
4235		    (av->assoc_value != SCTP_CC_RTCC)) {
4236			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4237			error = EINVAL;
4238			break;
4239		}
4240		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4241		if (stcb) {
4242			stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
4243			stcb->asoc.congestion_control_module = av->assoc_value;
4244			if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
4245				TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4246					stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
4247				}
4248			}
4249			SCTP_TCB_UNLOCK(stcb);
4250		} else {
4251			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4252			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4253			    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
4254			    (av->assoc_id == SCTP_ALL_ASSOC)) {
4255				SCTP_INP_WLOCK(inp);
4256				inp->sctp_ep.sctp_default_cc_module = av->assoc_value;
4257				SCTP_INP_WUNLOCK(inp);
4258			}
4259			if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4260			    (av->assoc_id == SCTP_ALL_ASSOC)) {
4261				SCTP_INP_RLOCK(inp);
4262				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4263					SCTP_TCB_LOCK(stcb);
4264					stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
4265					stcb->asoc.congestion_control_module = av->assoc_value;
4266					if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
4267						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4268							stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
4269						}
4270					}
4271					SCTP_TCB_UNLOCK(stcb);
4272				}
4273				SCTP_INP_RUNLOCK(inp);
4274			}
4275		}
4276		break;
4277	}
4278	case SCTP_CC_OPTION:
4279	{
4280		struct sctp_cc_option *cc_opt;
4281
4282		SCTP_CHECK_AND_CAST(cc_opt, optval, struct sctp_cc_option, optsize);
4283		SCTP_FIND_STCB(inp, stcb, cc_opt->aid_value.assoc_id);
4284		if (stcb == NULL) {
4285			if (cc_opt->aid_value.assoc_id == SCTP_CURRENT_ASSOC) {
4286				SCTP_INP_RLOCK(inp);
4287				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4288					SCTP_TCB_LOCK(stcb);
4289					if (stcb->asoc.cc_functions.sctp_cwnd_socket_option) {
4290						(*stcb->asoc.cc_functions.sctp_cwnd_socket_option)(stcb, 1, cc_opt);
4291					}
4292					SCTP_TCB_UNLOCK(stcb);
4293				}
4294				SCTP_INP_RUNLOCK(inp);
4295			} else {
4296				error = EINVAL;
4297			}
4298		} else {
4299			if (stcb->asoc.cc_functions.sctp_cwnd_socket_option == NULL) {
4300				error = ENOTSUP;
4301			} else {
4302				error = (*stcb->asoc.cc_functions.sctp_cwnd_socket_option)(stcb, 1,
4303											   cc_opt);
4304			}
4305			SCTP_TCB_UNLOCK(stcb);
4306		}
4307		break;
4308	}
4309	case SCTP_PLUGGABLE_SS:
4310	{
4311		struct sctp_assoc_value *av;
4312
4313		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4314		if ((av->assoc_value != SCTP_SS_DEFAULT) &&
4315		    (av->assoc_value != SCTP_SS_ROUND_ROBIN) &&
4316		    (av->assoc_value != SCTP_SS_ROUND_ROBIN_PACKET) &&
4317		    (av->assoc_value != SCTP_SS_PRIORITY) &&
4318		    (av->assoc_value != SCTP_SS_FAIR_BANDWITH) &&
4319		    (av->assoc_value != SCTP_SS_FIRST_COME)) {
4320			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4321			error = EINVAL;
4322			break;
4323		}
4324		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4325		if (stcb) {
4326			stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1);
4327			stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
4328			stcb->asoc.stream_scheduling_module = av->assoc_value;
4329			stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
4330			SCTP_TCB_UNLOCK(stcb);
4331		} else {
4332			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4333			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4334			    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
4335			    (av->assoc_id == SCTP_ALL_ASSOC)) {
4336				SCTP_INP_WLOCK(inp);
4337				inp->sctp_ep.sctp_default_ss_module = av->assoc_value;
4338				SCTP_INP_WUNLOCK(inp);
4339			}
4340			if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4341			    (av->assoc_id == SCTP_ALL_ASSOC)) {
4342				SCTP_INP_RLOCK(inp);
4343				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4344					SCTP_TCB_LOCK(stcb);
4345					stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1);
4346					stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
4347					stcb->asoc.stream_scheduling_module = av->assoc_value;
4348					stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
4349					SCTP_TCB_UNLOCK(stcb);
4350				}
4351				SCTP_INP_RUNLOCK(inp);
4352			}
4353		}
4354		break;
4355	}
4356	case SCTP_SS_VALUE:
4357	{
4358		struct sctp_stream_value *av;
4359
4360		SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, optsize);
4361		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4362		if (stcb) {
4363			if (stcb->asoc.ss_functions.sctp_ss_set_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id],
4364			                                              av->stream_value) < 0) {
4365				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4366				error = EINVAL;
4367			}
4368			SCTP_TCB_UNLOCK(stcb);
4369		} else {
4370			if (av->assoc_id == SCTP_CURRENT_ASSOC) {
4371				SCTP_INP_RLOCK(inp);
4372				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4373					SCTP_TCB_LOCK(stcb);
4374					stcb->asoc.ss_functions.sctp_ss_set_value(stcb,
4375					                                          &stcb->asoc,
4376					                                          &stcb->asoc.strmout[av->stream_id],
4377					                                          av->stream_value);
4378					SCTP_TCB_UNLOCK(stcb);
4379				}
4380				SCTP_INP_RUNLOCK(inp);
4381
4382			} else {
4383				/* Can't set stream value without association */
4384				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4385				error = EINVAL;
4386			}
4387		}
4388		break;
4389	}
4390	case SCTP_CLR_STAT_LOG:
4391		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4392		error = EOPNOTSUPP;
4393		break;
4394	case SCTP_CONTEXT:
4395	{
4396		struct sctp_assoc_value *av;
4397
4398		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4399		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4400
4401		if (stcb) {
4402			stcb->asoc.context = av->assoc_value;
4403			SCTP_TCB_UNLOCK(stcb);
4404		} else {
4405			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4406			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4407			    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
4408			    (av->assoc_id == SCTP_ALL_ASSOC)) {
4409				SCTP_INP_WLOCK(inp);
4410				inp->sctp_context = av->assoc_value;
4411				SCTP_INP_WUNLOCK(inp);
4412			}
4413			if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4414			    (av->assoc_id == SCTP_ALL_ASSOC)) {
4415				SCTP_INP_RLOCK(inp);
4416				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4417					SCTP_TCB_LOCK(stcb);
4418					stcb->asoc.context = av->assoc_value;
4419					SCTP_TCB_UNLOCK(stcb);
4420				}
4421				SCTP_INP_RUNLOCK(inp);
4422			}
4423		}
4424		break;
4425	}
4426	case SCTP_VRF_ID:
4427	{
4428		uint32_t *default_vrfid;
4429#ifdef SCTP_MVRF
4430		int i;
4431#endif
4432		SCTP_CHECK_AND_CAST(default_vrfid, optval, uint32_t, optsize);
4433		if (*default_vrfid > SCTP_MAX_VRF_ID) {
4434			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4435			error = EINVAL;
4436			break;
4437		}
4438#ifdef SCTP_MVRF
4439		for (i = 0; i < inp->num_vrfs; i++) {
4440			/* The VRF must be in the VRF list */
4441			if (*default_vrfid == inp->m_vrf_ids[i]) {
4442				SCTP_INP_WLOCK(inp);
4443 				inp->def_vrf_id = *default_vrfid;
4444				SCTP_INP_WUNLOCK(inp);
4445				goto sctp_done;
4446			}
4447		}
4448		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4449		error = EINVAL;
4450#else
4451		inp->def_vrf_id = *default_vrfid;
4452#endif
4453#ifdef SCTP_MVRF
4454	sctp_done:
4455#endif
4456		break;
4457	}
4458	case SCTP_DEL_VRF_ID:
4459	{
4460#ifdef SCTP_MVRF
4461		uint32_t *del_vrfid;
4462		int i, fnd = 0;
4463
4464		SCTP_CHECK_AND_CAST(del_vrfid, optval, uint32_t, optsize);
4465		if (*del_vrfid > SCTP_MAX_VRF_ID) {
4466			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4467			error = EINVAL;
4468			break;
4469		}
4470		if (inp->num_vrfs == 1) {
4471			/* Can't delete last one */
4472			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4473			error = EINVAL;
4474			break;
4475		}
4476		if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) {
4477			/* Can't add more once you are bound */
4478			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4479			error = EINVAL;
4480			break;
4481		}
4482		SCTP_INP_WLOCK(inp);
4483		for (i = 0; i < inp->num_vrfs; i++) {
4484			if (*del_vrfid == inp->m_vrf_ids[i]) {
4485				fnd = 1;
4486				break;
4487			}
4488		}
4489		if (!fnd) {
4490			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4491			error = EINVAL;
4492			break;
4493		}
4494		if (i != (inp->num_vrfs - 1)) {
4495			/* Take bottom one and move to this slot */
4496			inp->m_vrf_ids[i] = inp->m_vrf_ids[(inp->num_vrfs-1)];
4497		}
4498		if (*del_vrfid == inp->def_vrf_id) {
4499			/* Take the first one as the new default */
4500			inp->def_vrf_id = inp->m_vrf_ids[0];
4501		}
4502		/* Drop the number by one killing last one */
4503		inp->num_vrfs--;
4504#else
4505		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4506		error = EOPNOTSUPP;
4507#endif
4508		break;
4509	}
4510	case SCTP_ADD_VRF_ID:
4511	{
4512#ifdef SCTP_MVRF
4513		uint32_t *add_vrfid;
4514		int i;
4515
4516		SCTP_CHECK_AND_CAST(add_vrfid, optval, uint32_t, optsize);
4517		if (*add_vrfid > SCTP_MAX_VRF_ID) {
4518			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4519			error = EINVAL;
4520			break;
4521		}
4522		if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) {
4523			/* Can't add more once you are bound */
4524			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4525			error = EINVAL;
4526			break;
4527		}
4528		SCTP_INP_WLOCK(inp);
4529		/* Verify its not already here */
4530		for (i = 0; i < inp->num_vrfs; i++) {
4531			if (*add_vrfid == inp->m_vrf_ids[i]) {
4532				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4533				error = EALREADY;
4534				SCTP_INP_WUNLOCK(inp);
4535				break;
4536			}
4537		}
4538		if ((inp->num_vrfs + 1) > inp->vrf_size) {
4539			/* need to grow array */
4540			uint32_t *tarray;
4541			SCTP_MALLOC(tarray, uint32_t *,
4542				    (sizeof(uint32_t) * (inp->vrf_size + SCTP_DEFAULT_VRF_SIZE)),
4543				    SCTP_M_MVRF);
4544			if (tarray == NULL) {
4545				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4546				error = ENOMEM;
4547				SCTP_INP_WUNLOCK(inp);
4548				break;
4549			}
4550			memcpy(tarray, inp->m_vrf_ids, (sizeof(uint32_t) * inp->vrf_size));
4551			SCTP_FREE(inp->m_vrf_ids, SCTP_M_MVRF);
4552			inp->m_vrf_ids = tarray;
4553			inp->vrf_size += SCTP_DEFAULT_VRF_SIZE;
4554		}
4555		inp->m_vrf_ids[inp->num_vrfs] = *add_vrfid;
4556		inp->num_vrfs++;
4557		SCTP_INP_WUNLOCK(inp);
4558#else
4559		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4560		error = EOPNOTSUPP;
4561#endif
4562	 	break;
4563	}
4564	case SCTP_DELAYED_SACK:
4565	{
4566		struct sctp_sack_info *sack;
4567
4568		SCTP_CHECK_AND_CAST(sack, optval, struct sctp_sack_info, optsize);
4569		SCTP_FIND_STCB(inp, stcb, sack->sack_assoc_id);
4570		if (sack->sack_delay) {
4571			if (sack->sack_delay > SCTP_MAX_SACK_DELAY)
4572				sack->sack_delay = SCTP_MAX_SACK_DELAY;
4573			if (MSEC_TO_TICKS(sack->sack_delay) < 1) {
4574				sack->sack_delay = TICKS_TO_MSEC(1);
4575			}
4576		}
4577		if (stcb) {
4578			if (sack->sack_delay) {
4579				stcb->asoc.delayed_ack = sack->sack_delay;
4580			}
4581			if (sack->sack_freq) {
4582				stcb->asoc.sack_freq = sack->sack_freq;
4583			}
4584			SCTP_TCB_UNLOCK(stcb);
4585		} else {
4586			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4587			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4588			    (sack->sack_assoc_id == SCTP_FUTURE_ASSOC) ||
4589			    (sack->sack_assoc_id == SCTP_ALL_ASSOC)) {
4590				SCTP_INP_WLOCK(inp);
4591				if (sack->sack_delay) {
4592					inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV] = MSEC_TO_TICKS(sack->sack_delay);
4593				}
4594				if (sack->sack_freq) {
4595					inp->sctp_ep.sctp_sack_freq = sack->sack_freq;
4596				}
4597				SCTP_INP_WUNLOCK(inp);
4598			}
4599			if ((sack->sack_assoc_id == SCTP_CURRENT_ASSOC) ||
4600			    (sack->sack_assoc_id == SCTP_ALL_ASSOC)) {
4601				SCTP_INP_RLOCK(inp);
4602				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4603					SCTP_TCB_LOCK(stcb);
4604					if (sack->sack_delay) {
4605						stcb->asoc.delayed_ack = sack->sack_delay;
4606					}
4607					if (sack->sack_freq) {
4608						stcb->asoc.sack_freq = sack->sack_freq;
4609					}
4610					SCTP_TCB_UNLOCK(stcb);
4611				}
4612				SCTP_INP_RUNLOCK(inp);
4613			}
4614		}
4615		break;
4616	}
4617	case SCTP_AUTH_CHUNK:
4618	{
4619		struct sctp_authchunk *sauth;
4620
4621		SCTP_CHECK_AND_CAST(sauth, optval, struct sctp_authchunk, optsize);
4622
4623		SCTP_INP_WLOCK(inp);
4624		if (sctp_auth_add_chunk(sauth->sauth_chunk, inp->sctp_ep.local_auth_chunks)) {
4625			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4626			error = EINVAL;
4627		}
4628		SCTP_INP_WUNLOCK(inp);
4629		break;
4630	}
4631	case SCTP_AUTH_KEY:
4632	{
4633		struct sctp_authkey *sca;
4634		struct sctp_keyhead *shared_keys;
4635		sctp_sharedkey_t *shared_key;
4636		sctp_key_t *key = NULL;
4637		size_t size;
4638
4639		SCTP_CHECK_AND_CAST(sca, optval, struct sctp_authkey, optsize);
4640		if (sca->sca_keylength == 0) {
4641			size = optsize - sizeof(struct sctp_authkey);
4642		} else {
4643		        if (sca->sca_keylength + sizeof(struct sctp_authkey) <= optsize) {
4644				size = sca->sca_keylength;
4645			} else {
4646				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4647				error = EINVAL;
4648				break;
4649			}
4650		}
4651		SCTP_FIND_STCB(inp, stcb, sca->sca_assoc_id);
4652
4653		if (stcb) {
4654			shared_keys = &stcb->asoc.shared_keys;
4655			/* clear the cached keys for this key id */
4656			sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
4657			/*
4658			 * create the new shared key and
4659			 * insert/replace it
4660			 */
4661			if (size > 0) {
4662				key = sctp_set_key(sca->sca_key, (uint32_t) size);
4663				if (key == NULL) {
4664					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4665					error = ENOMEM;
4666					SCTP_TCB_UNLOCK(stcb);
4667					break;
4668				}
4669			}
4670			shared_key = sctp_alloc_sharedkey();
4671			if (shared_key == NULL) {
4672				sctp_free_key(key);
4673				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4674				error = ENOMEM;
4675				SCTP_TCB_UNLOCK(stcb);
4676				break;
4677			}
4678			shared_key->key = key;
4679			shared_key->keyid = sca->sca_keynumber;
4680			error = sctp_insert_sharedkey(shared_keys, shared_key);
4681			SCTP_TCB_UNLOCK(stcb);
4682		} else {
4683			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4684			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4685			    (sca->sca_assoc_id == SCTP_FUTURE_ASSOC) ||
4686			    (sca->sca_assoc_id == SCTP_ALL_ASSOC)) {
4687				SCTP_INP_WLOCK(inp);
4688				shared_keys = &inp->sctp_ep.shared_keys;
4689				/*
4690				 * clear the cached keys on all assocs for
4691				 * this key id
4692				 */
4693				sctp_clear_cachedkeys_ep(inp, sca->sca_keynumber);
4694				/*
4695				 * create the new shared key and
4696				 * insert/replace it
4697				 */
4698				if (size > 0) {
4699					key = sctp_set_key(sca->sca_key, (uint32_t) size);
4700					if (key == NULL) {
4701						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4702						error = ENOMEM;
4703						SCTP_INP_WUNLOCK(inp);
4704						break;
4705					}
4706				}
4707				shared_key = sctp_alloc_sharedkey();
4708				if (shared_key == NULL) {
4709					sctp_free_key(key);
4710					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4711					error = ENOMEM;
4712					SCTP_INP_WUNLOCK(inp);
4713					break;
4714				}
4715				shared_key->key = key;
4716				shared_key->keyid = sca->sca_keynumber;
4717				error = sctp_insert_sharedkey(shared_keys, shared_key);
4718				SCTP_INP_WUNLOCK(inp);
4719			}
4720			if ((sca->sca_assoc_id == SCTP_CURRENT_ASSOC) ||
4721			    (sca->sca_assoc_id == SCTP_ALL_ASSOC)) {
4722				SCTP_INP_RLOCK(inp);
4723				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4724					SCTP_TCB_LOCK(stcb);
4725					shared_keys = &stcb->asoc.shared_keys;
4726					/* clear the cached keys for this key id */
4727					sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
4728					/*
4729					 * create the new shared key and
4730					 * insert/replace it
4731					 */
4732					if (size > 0) {
4733						key = sctp_set_key(sca->sca_key, (uint32_t) size);
4734						if (key == NULL) {
4735							SCTP_TCB_UNLOCK(stcb);
4736							continue;
4737						}
4738					}
4739					shared_key = sctp_alloc_sharedkey();
4740					if (shared_key == NULL) {
4741						sctp_free_key(key);
4742						SCTP_TCB_UNLOCK(stcb);
4743						continue;
4744					}
4745					shared_key->key = key;
4746					shared_key->keyid = sca->sca_keynumber;
4747					error = sctp_insert_sharedkey(shared_keys, shared_key);
4748					SCTP_TCB_UNLOCK(stcb);
4749				}
4750				SCTP_INP_RUNLOCK(inp);
4751			}
4752		}
4753		break;
4754	}
4755	case SCTP_HMAC_IDENT:
4756	{
4757		struct sctp_hmacalgo *shmac;
4758		sctp_hmaclist_t *hmaclist;
4759		uint16_t hmacid;
4760		uint32_t i;
4761
4762		SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, optsize);
4763		if (optsize < sizeof(struct sctp_hmacalgo) + shmac->shmac_number_of_idents * sizeof(uint16_t)) {
4764			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4765			error = EINVAL;
4766			break;
4767		}
4768
4769		hmaclist = sctp_alloc_hmaclist(shmac->shmac_number_of_idents);
4770		if (hmaclist == NULL) {
4771			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4772			error = ENOMEM;
4773			break;
4774		}
4775		for (i = 0; i < shmac->shmac_number_of_idents; i++) {
4776			hmacid = shmac->shmac_idents[i];
4777			if (sctp_auth_add_hmacid(hmaclist, hmacid)) {
4778				/* invalid HMACs were found */;
4779				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4780				error = EINVAL;
4781				sctp_free_hmaclist(hmaclist);
4782				goto sctp_set_hmac_done;
4783			}
4784		}
4785		for (i = 0; i < hmaclist->num_algo; i++) {
4786			if (hmaclist->hmac[i] == SCTP_AUTH_HMAC_ID_SHA1) {
4787				/* already in list */
4788				break;
4789			}
4790		}
4791		if (i == hmaclist->num_algo) {
4792			/* not found in list */
4793			sctp_free_hmaclist(hmaclist);
4794			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4795			error = EINVAL;
4796			break;
4797		}
4798		/* set it on the endpoint */
4799		SCTP_INP_WLOCK(inp);
4800		if (inp->sctp_ep.local_hmacs)
4801			sctp_free_hmaclist(inp->sctp_ep.local_hmacs);
4802		inp->sctp_ep.local_hmacs = hmaclist;
4803		SCTP_INP_WUNLOCK(inp);
4804	sctp_set_hmac_done:
4805		break;
4806	}
4807	case SCTP_AUTH_ACTIVE_KEY:
4808	{
4809		struct sctp_authkeyid *scact;
4810
4811		SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, optsize);
4812		SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id);
4813
4814		/* set the active key on the right place */
4815		if (stcb) {
4816			/* set the active key on the assoc */
4817			if (sctp_auth_setactivekey(stcb,
4818						   scact->scact_keynumber)) {
4819				SCTP_LTRACE_ERR_RET(inp, NULL, NULL,
4820						    SCTP_FROM_SCTP_USRREQ,
4821						    EINVAL);
4822				error = EINVAL;
4823			}
4824			SCTP_TCB_UNLOCK(stcb);
4825		} else {
4826			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4827			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4828			    (scact->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
4829			    (scact->scact_assoc_id == SCTP_ALL_ASSOC)) {
4830				SCTP_INP_WLOCK(inp);
4831				if (sctp_auth_setactivekey_ep(inp, scact->scact_keynumber)) {
4832					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4833					error = EINVAL;
4834				}
4835				SCTP_INP_WUNLOCK(inp);
4836			}
4837			if ((scact->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
4838			    (scact->scact_assoc_id == SCTP_ALL_ASSOC)) {
4839				SCTP_INP_RLOCK(inp);
4840				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4841					SCTP_TCB_LOCK(stcb);
4842					sctp_auth_setactivekey(stcb, scact->scact_keynumber);
4843					SCTP_TCB_UNLOCK(stcb);
4844				}
4845				SCTP_INP_RUNLOCK(inp);
4846			}
4847		}
4848		break;
4849	}
4850	case SCTP_AUTH_DELETE_KEY:
4851	{
4852		struct sctp_authkeyid *scdel;
4853
4854		SCTP_CHECK_AND_CAST(scdel, optval, struct sctp_authkeyid, optsize);
4855		SCTP_FIND_STCB(inp, stcb, scdel->scact_assoc_id);
4856
4857		/* delete the key from the right place */
4858		if (stcb) {
4859			if (sctp_delete_sharedkey(stcb, scdel->scact_keynumber)) {
4860				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4861				error = EINVAL;
4862			}
4863			SCTP_TCB_UNLOCK(stcb);
4864		} else {
4865			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4866			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4867			    (scdel->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
4868			    (scdel->scact_assoc_id == SCTP_ALL_ASSOC)) {
4869				SCTP_INP_WLOCK(inp);
4870				if (sctp_delete_sharedkey_ep(inp, scdel->scact_keynumber)) {
4871					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4872					error = EINVAL;
4873				}
4874				SCTP_INP_WUNLOCK(inp);
4875			}
4876			if ((scdel->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
4877			    (scdel->scact_assoc_id == SCTP_ALL_ASSOC)) {
4878				SCTP_INP_RLOCK(inp);
4879				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4880					SCTP_TCB_LOCK(stcb);
4881					sctp_delete_sharedkey(stcb, scdel->scact_keynumber);
4882					SCTP_TCB_UNLOCK(stcb);
4883				}
4884				SCTP_INP_RUNLOCK(inp);
4885			}
4886		}
4887		break;
4888	}
4889	case SCTP_AUTH_DEACTIVATE_KEY:
4890	{
4891		struct sctp_authkeyid *keyid;
4892
4893		SCTP_CHECK_AND_CAST(keyid, optval, struct sctp_authkeyid, optsize);
4894		SCTP_FIND_STCB(inp, stcb, keyid->scact_assoc_id);
4895
4896		/* deactivate the key from the right place */
4897		if (stcb) {
4898			if (sctp_deact_sharedkey(stcb, keyid->scact_keynumber)) {
4899				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4900				error = EINVAL;
4901			}
4902			SCTP_TCB_UNLOCK(stcb);
4903		} else {
4904			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4905			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4906			    (keyid->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
4907			    (keyid->scact_assoc_id == SCTP_ALL_ASSOC)) {
4908				SCTP_INP_WLOCK(inp);
4909				if (sctp_deact_sharedkey_ep(inp, keyid->scact_keynumber)) {
4910					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4911					error = EINVAL;
4912				}
4913				SCTP_INP_WUNLOCK(inp);
4914			}
4915			if ((keyid->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
4916			    (keyid->scact_assoc_id == SCTP_ALL_ASSOC)) {
4917				SCTP_INP_RLOCK(inp);
4918				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4919					SCTP_TCB_LOCK(stcb);
4920					sctp_deact_sharedkey(stcb, keyid->scact_keynumber);
4921					SCTP_TCB_UNLOCK(stcb);
4922				}
4923				SCTP_INP_RUNLOCK(inp);
4924			}
4925		}
4926		break;
4927	}
4928	case SCTP_ENABLE_STREAM_RESET:
4929	{
4930		struct sctp_assoc_value *av;
4931
4932		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4933		if (av->assoc_value & (~SCTP_ENABLE_VALUE_MASK)) {
4934		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4935			error = EINVAL;
4936			break;
4937		}
4938		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4939		if (stcb) {
4940			stcb->asoc.local_strreset_support = (uint8_t)av->assoc_value;
4941			SCTP_TCB_UNLOCK(stcb);
4942		} else {
4943			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4944			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4945			    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
4946			    (av->assoc_id == SCTP_ALL_ASSOC)) {
4947				SCTP_INP_WLOCK(inp);
4948				inp->local_strreset_support = (uint8_t)av->assoc_value;
4949				SCTP_INP_WUNLOCK(inp);
4950			}
4951			if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4952			    (av->assoc_id == SCTP_ALL_ASSOC)) {
4953				SCTP_INP_RLOCK(inp);
4954				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4955					SCTP_TCB_LOCK(stcb);
4956					stcb->asoc.local_strreset_support = (uint8_t)av->assoc_value;
4957					SCTP_TCB_UNLOCK(stcb);
4958				}
4959				SCTP_INP_RUNLOCK(inp);
4960			}
4961
4962		}
4963		break;
4964	}
4965	case SCTP_RESET_STREAMS:
4966	{
4967		struct sctp_reset_streams *strrst;
4968		int i, send_out = 0;
4969		int send_in = 0;
4970
4971		SCTP_CHECK_AND_CAST(strrst, optval, struct sctp_reset_streams, optsize);
4972		SCTP_FIND_STCB(inp, stcb, strrst->srs_assoc_id);
4973		if (stcb == NULL) {
4974		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4975			error = ENOENT;
4976			break;
4977		}
4978		if (stcb->asoc.peer_supports_strreset == 0) {
4979			/*
4980			 * Peer does not support the chunk type.
4981			 */
4982			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4983			error = EOPNOTSUPP;
4984			SCTP_TCB_UNLOCK(stcb);
4985			break;
4986		}
4987		if (stcb->asoc.stream_reset_outstanding) {
4988			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4989			error = EALREADY;
4990			SCTP_TCB_UNLOCK(stcb);
4991			break;
4992		}
4993		if (strrst->srs_flags & SCTP_STREAM_RESET_INCOMING) {
4994			send_in = 1;
4995		}
4996		if (strrst->srs_flags & SCTP_STREAM_RESET_OUTGOING) {
4997			send_out = 1;
4998		}
4999		if ((send_in == 0) && (send_out == 0)) {
5000			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5001			error = EINVAL;
5002			SCTP_TCB_UNLOCK(stcb);
5003			break;
5004		}
5005		for (i = 0; i < strrst->srs_number_streams; i++) {
5006			if ((send_in) &&
5007			    (strrst->srs_stream_list[i] > stcb->asoc.streamincnt)) {
5008				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5009				error = EINVAL;
5010				break;
5011			}
5012			if ((send_out) &&
5013			    (strrst->srs_stream_list[i] > stcb->asoc.streamoutcnt)) {
5014				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5015				error = EINVAL;
5016				break;
5017			}
5018		}
5019		if (error) {
5020			SCTP_TCB_UNLOCK(stcb);
5021			break;
5022		}
5023		error = sctp_send_str_reset_req(stcb, strrst->srs_number_streams,
5024						strrst->srs_stream_list,
5025						send_out, send_in, 0, 0, 0, 0, 0);
5026
5027		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
5028		SCTP_TCB_UNLOCK(stcb);
5029		break;
5030	}
5031	case SCTP_ADD_STREAMS:
5032	{
5033		struct sctp_add_streams *stradd;
5034		uint8_t addstream = 0;
5035		uint16_t add_o_strmcnt = 0;
5036		uint16_t add_i_strmcnt = 0;
5037
5038		SCTP_CHECK_AND_CAST(stradd, optval, struct sctp_add_streams, optsize);
5039		SCTP_FIND_STCB(inp, stcb, stradd->sas_assoc_id);
5040		if (stcb == NULL) {
5041		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
5042			error = ENOENT;
5043			break;
5044		}
5045		if (stcb->asoc.peer_supports_strreset == 0) {
5046			/*
5047			 * Peer does not support the chunk type.
5048			 */
5049			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
5050			error = EOPNOTSUPP;
5051			SCTP_TCB_UNLOCK(stcb);
5052			break;
5053		}
5054		if (stcb->asoc.stream_reset_outstanding) {
5055			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
5056			error = EALREADY;
5057			SCTP_TCB_UNLOCK(stcb);
5058			break;
5059		}
5060		if ((stradd->sas_outstrms == 0) &&
5061		    (stradd->sas_instrms == 0)) {
5062			error = EINVAL;
5063			goto skip_stuff;
5064		}
5065		if (stradd->sas_outstrms) {
5066			addstream = 1;
5067			/* We allocate here */
5068			add_o_strmcnt = stradd->sas_outstrms;
5069			if ((((int)add_o_strmcnt) + ((int)stcb->asoc.streamoutcnt)) > 0x0000ffff) {
5070				/* You can't have more than 64k */
5071				error = EINVAL;
5072				goto skip_stuff;
5073			}
5074		}
5075		if (stradd->sas_instrms) {
5076			int cnt;
5077
5078			addstream |= 2;
5079			/* We allocate inside sctp_send_str_reset_req() */
5080			add_i_strmcnt = stradd->sas_instrms;
5081			cnt = add_i_strmcnt;
5082			cnt += stcb->asoc.streamincnt;
5083			if (cnt > 0x0000ffff) {
5084				/* You can't have more than 64k */
5085				error = EINVAL;
5086				goto skip_stuff;
5087			}
5088			if (cnt > (int)stcb->asoc.max_inbound_streams) {
5089				/* More than you are allowed */
5090				error = EINVAL;
5091				goto skip_stuff;
5092			}
5093		}
5094		error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 0, addstream, add_o_strmcnt, add_i_strmcnt, 0);
5095		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
5096	skip_stuff:
5097		SCTP_TCB_UNLOCK(stcb);
5098		break;
5099	}
5100	case SCTP_RESET_ASSOC:
5101	{
5102		uint32_t *value;
5103
5104		SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
5105		SCTP_FIND_STCB(inp, stcb, (sctp_assoc_t) *value);
5106		if (stcb == NULL) {
5107		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
5108			error = ENOENT;
5109			break;
5110		}
5111		if (stcb->asoc.peer_supports_strreset == 0) {
5112			/*
5113			 * Peer does not support the chunk type.
5114			 */
5115			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
5116			error = EOPNOTSUPP;
5117			SCTP_TCB_UNLOCK(stcb);
5118			break;
5119		}
5120		if (stcb->asoc.stream_reset_outstanding) {
5121			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
5122			error = EALREADY;
5123			SCTP_TCB_UNLOCK(stcb);
5124			break;
5125		}
5126		error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 1, 0, 0, 0, 0);
5127		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
5128		SCTP_TCB_UNLOCK(stcb);
5129		break;
5130	}
5131	case SCTP_CONNECT_X:
5132		if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
5133			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5134			error = EINVAL;
5135			break;
5136		}
5137		error = sctp_do_connect_x(so, inp, optval, optsize, p, 0);
5138		break;
5139	case SCTP_CONNECT_X_DELAYED:
5140		if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
5141			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5142			error = EINVAL;
5143			break;
5144		}
5145		error = sctp_do_connect_x(so, inp, optval, optsize, p, 1);
5146		break;
5147	case SCTP_CONNECT_X_COMPLETE:
5148	{
5149		struct sockaddr *sa;
5150		struct sctp_nets *net;
5151
5152		/* FIXME MT: check correct? */
5153		SCTP_CHECK_AND_CAST(sa, optval, struct sockaddr, optsize);
5154
5155		/* find tcb */
5156		if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
5157			SCTP_INP_RLOCK(inp);
5158			stcb = LIST_FIRST(&inp->sctp_asoc_list);
5159			if (stcb) {
5160				SCTP_TCB_LOCK(stcb);
5161				net = sctp_findnet(stcb, sa);
5162			}
5163			SCTP_INP_RUNLOCK(inp);
5164		} else {
5165			/* We increment here since sctp_findassociation_ep_addr() wil
5166			 * do a decrement if it finds the stcb as long as the locked
5167			 * tcb (last argument) is NOT a TCB.. aka NULL.
5168			 */
5169			SCTP_INP_INCR_REF(inp);
5170			stcb = sctp_findassociation_ep_addr(&inp, sa, &net, NULL, NULL);
5171			if (stcb == NULL) {
5172				SCTP_INP_DECR_REF(inp);
5173			}
5174		}
5175
5176		if (stcb == NULL) {
5177			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
5178			error = ENOENT;
5179			break;
5180		}
5181		if (stcb->asoc.delayed_connection == 1) {
5182			stcb->asoc.delayed_connection = 0;
5183			(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
5184			sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb,
5185					stcb->asoc.primary_destination,
5186					SCTP_FROM_SCTP_USRREQ+SCTP_LOC_9);
5187			sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
5188		} else {
5189			/*
5190			 * already expired or did not use delayed
5191			 * connectx
5192			 */
5193			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
5194			error = EALREADY;
5195		}
5196		SCTP_TCB_UNLOCK(stcb);
5197		break;
5198	}
5199	case SCTP_MAX_BURST:
5200	{
5201#if defined(__FreeBSD__) && __FreeBSD_version < 900000
5202		uint8_t *burst;
5203
5204		SCTP_CHECK_AND_CAST(burst, optval, uint8_t, optsize);
5205
5206		SCTP_INP_WLOCK(inp);
5207		inp->sctp_ep.max_burst = *burst;
5208		SCTP_INP_WUNLOCK(inp);
5209#else
5210		struct sctp_assoc_value *av;
5211
5212		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
5213		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
5214
5215		if (stcb) {
5216			stcb->asoc.max_burst = av->assoc_value;
5217			SCTP_TCB_UNLOCK(stcb);
5218		} else {
5219			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5220			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5221			    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
5222			    (av->assoc_id == SCTP_ALL_ASSOC)) {
5223				SCTP_INP_WLOCK(inp);
5224				inp->sctp_ep.max_burst = av->assoc_value;
5225				SCTP_INP_WUNLOCK(inp);
5226			}
5227			if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
5228			    (av->assoc_id == SCTP_ALL_ASSOC)) {
5229				SCTP_INP_RLOCK(inp);
5230				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5231					SCTP_TCB_LOCK(stcb);
5232					stcb->asoc.max_burst = av->assoc_value;
5233					SCTP_TCB_UNLOCK(stcb);
5234				}
5235				SCTP_INP_RUNLOCK(inp);
5236			}
5237		}
5238#endif
5239		break;
5240	}
5241	case SCTP_MAXSEG:
5242	{
5243		struct sctp_assoc_value *av;
5244		int ovh;
5245
5246		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
5247		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
5248
5249		if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
5250			ovh = SCTP_MED_OVERHEAD;
5251		} else {
5252			ovh = SCTP_MED_V4_OVERHEAD;
5253		}
5254		if (stcb) {
5255			if (av->assoc_value) {
5256				stcb->asoc.sctp_frag_point = (av->assoc_value + ovh);
5257			} else {
5258				stcb->asoc.sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
5259			}
5260			SCTP_TCB_UNLOCK(stcb);
5261		} else {
5262			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5263			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5264			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
5265				SCTP_INP_WLOCK(inp);
5266				/* FIXME MT: I think this is not in tune with the API ID */
5267				if (av->assoc_value) {
5268					inp->sctp_frag_point = (av->assoc_value + ovh);
5269				} else {
5270					inp->sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
5271				}
5272				SCTP_INP_WUNLOCK(inp);
5273			} else {
5274				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5275				error = EINVAL;
5276			}
5277		}
5278		break;
5279	}
5280	case SCTP_EVENTS:
5281	{
5282		struct sctp_event_subscribe *events;
5283
5284		SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, optsize);
5285
5286		SCTP_INP_WLOCK(inp);
5287		if (events->sctp_data_io_event) {
5288			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
5289		} else {
5290			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
5291		}
5292
5293		if (events->sctp_association_event) {
5294			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
5295		} else {
5296			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
5297		}
5298
5299		if (events->sctp_address_event) {
5300			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
5301		} else {
5302			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
5303		}
5304
5305		if (events->sctp_send_failure_event) {
5306			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
5307		} else {
5308			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
5309		}
5310
5311		if (events->sctp_peer_error_event) {
5312			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPEERERR);
5313		} else {
5314			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPEERERR);
5315		}
5316
5317		if (events->sctp_shutdown_event) {
5318			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
5319		} else {
5320			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
5321		}
5322
5323		if (events->sctp_partial_delivery_event) {
5324			sctp_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
5325		} else {
5326			sctp_feature_off(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
5327		}
5328
5329		if (events->sctp_adaptation_layer_event) {
5330			sctp_feature_on(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
5331		} else {
5332			sctp_feature_off(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
5333		}
5334
5335		if (events->sctp_authentication_event) {
5336			sctp_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT);
5337		} else {
5338			sctp_feature_off(inp, SCTP_PCB_FLAGS_AUTHEVNT);
5339		}
5340
5341		if (events->sctp_sender_dry_event) {
5342			sctp_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT);
5343		} else {
5344			sctp_feature_off(inp, SCTP_PCB_FLAGS_DRYEVNT);
5345		}
5346
5347		if (events->sctp_stream_reset_event) {
5348			sctp_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
5349		} else {
5350			sctp_feature_off(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
5351		}
5352		SCTP_INP_WUNLOCK(inp);
5353
5354		SCTP_INP_RLOCK(inp);
5355		LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5356			SCTP_TCB_LOCK(stcb);
5357			if (events->sctp_association_event) {
5358				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
5359			} else {
5360				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
5361			}
5362			if (events->sctp_address_event) {
5363				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
5364			} else {
5365				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
5366			}
5367			if (events->sctp_send_failure_event) {
5368				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
5369			} else {
5370				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
5371			}
5372			if (events->sctp_peer_error_event) {
5373				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
5374			} else {
5375				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
5376			}
5377			if (events->sctp_shutdown_event) {
5378				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
5379			} else {
5380				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
5381			}
5382			if (events->sctp_partial_delivery_event) {
5383				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
5384			} else {
5385				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
5386			}
5387			if (events->sctp_adaptation_layer_event) {
5388				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
5389			} else {
5390				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
5391			}
5392			if (events->sctp_authentication_event) {
5393				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
5394			} else {
5395				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
5396			}
5397			if (events->sctp_sender_dry_event) {
5398				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
5399			} else {
5400				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
5401			}
5402			if (events->sctp_stream_reset_event) {
5403				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
5404			} else {
5405				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
5406			}
5407			SCTP_TCB_UNLOCK(stcb);
5408		}
5409		/* Send up the sender dry event only for 1-to-1 style sockets. */
5410		if (events->sctp_sender_dry_event) {
5411			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5412			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
5413				stcb = LIST_FIRST(&inp->sctp_asoc_list);
5414				if (stcb) {
5415					SCTP_TCB_LOCK(stcb);
5416					if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
5417					    TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
5418					    (stcb->asoc.stream_queue_cnt == 0)) {
5419						sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb,  0, NULL, SCTP_SO_LOCKED);
5420					}
5421					SCTP_TCB_UNLOCK(stcb);
5422				}
5423			}
5424		}
5425		SCTP_INP_RUNLOCK(inp);
5426		break;
5427	}
5428	case SCTP_ADAPTATION_LAYER:
5429	{
5430		struct sctp_setadaptation *adap_bits;
5431
5432		SCTP_CHECK_AND_CAST(adap_bits, optval, struct sctp_setadaptation, optsize);
5433		SCTP_INP_WLOCK(inp);
5434		inp->sctp_ep.adaptation_layer_indicator = adap_bits->ssb_adaptation_ind;
5435		inp->sctp_ep.adaptation_layer_indicator_provided = 1;
5436		SCTP_INP_WUNLOCK(inp);
5437		break;
5438	}
5439#ifdef SCTP_DEBUG
5440	case SCTP_SET_INITIAL_DBG_SEQ:
5441	{
5442		uint32_t *vvv;
5443
5444		SCTP_CHECK_AND_CAST(vvv, optval, uint32_t, optsize);
5445		SCTP_INP_WLOCK(inp);
5446		inp->sctp_ep.initial_sequence_debug = *vvv;
5447		SCTP_INP_WUNLOCK(inp);
5448		break;
5449	}
5450#endif
5451	case SCTP_DEFAULT_SEND_PARAM:
5452	{
5453		struct sctp_sndrcvinfo *s_info;
5454
5455		SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, optsize);
5456		SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
5457
5458		if (stcb) {
5459			if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
5460				memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
5461			} else {
5462				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5463				error = EINVAL;
5464			}
5465			SCTP_TCB_UNLOCK(stcb);
5466		} else {
5467			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5468			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5469			    (s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC) ||
5470			    (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)) {
5471				SCTP_INP_WLOCK(inp);
5472				memcpy(&inp->def_send, s_info, min(optsize, sizeof(inp->def_send)));
5473				SCTP_INP_WUNLOCK(inp);
5474			}
5475			if ((s_info->sinfo_assoc_id == SCTP_CURRENT_ASSOC) ||
5476			    (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)) {
5477				SCTP_INP_RLOCK(inp);
5478				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5479					SCTP_TCB_LOCK(stcb);
5480					if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
5481						memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
5482					}
5483					SCTP_TCB_UNLOCK(stcb);
5484				}
5485				SCTP_INP_RUNLOCK(inp);
5486			}
5487		}
5488		break;
5489	}
5490	case SCTP_PEER_ADDR_PARAMS:
5491	{
5492		struct sctp_paddrparams *paddrp;
5493		struct sctp_nets *net;
5494
5495		SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, optsize);
5496		SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
5497		net = NULL;
5498		if (stcb) {
5499			net = sctp_findnet(stcb, (struct sockaddr *)&paddrp->spp_address);
5500		} else {
5501			/* We increment here since sctp_findassociation_ep_addr() wil
5502			 * do a decrement if it finds the stcb as long as the locked
5503			 * tcb (last argument) is NOT a TCB.. aka NULL.
5504			 */
5505			SCTP_INP_INCR_REF(inp);
5506			stcb = sctp_findassociation_ep_addr(&inp,
5507							    (struct sockaddr *)&paddrp->spp_address,
5508							    &net, NULL, NULL);
5509			if (stcb == NULL) {
5510				SCTP_INP_DECR_REF(inp);
5511			}
5512		}
5513		if (stcb && (net == NULL)) {
5514			struct sockaddr *sa;
5515
5516			sa = (struct sockaddr *)&paddrp->spp_address;
5517#ifdef INET
5518			if (sa->sa_family == AF_INET) {
5519
5520				struct sockaddr_in *sin;
5521				sin = (struct sockaddr_in *)sa;
5522				if (sin->sin_addr.s_addr) {
5523					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5524					SCTP_TCB_UNLOCK(stcb);
5525					error = EINVAL;
5526					break;
5527				}
5528			} else
5529#endif
5530#ifdef INET6
5531			if (sa->sa_family == AF_INET6) {
5532				struct sockaddr_in6 *sin6;
5533
5534				sin6 = (struct sockaddr_in6 *)sa;
5535				if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
5536					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5537					SCTP_TCB_UNLOCK(stcb);
5538					error = EINVAL;
5539					break;
5540				}
5541			} else
5542#endif
5543#if defined(__Userspace__)
5544			if (sa->sa_family == AF_CONN) {
5545				struct sockaddr_conn *sconn;
5546
5547				sconn = (struct sockaddr_conn *)sa;
5548				if (sconn->sconn_addr != NULL) {
5549					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5550					SCTP_TCB_UNLOCK(stcb);
5551					error = EINVAL;
5552					break;
5553				}
5554			} else
5555#endif
5556			{
5557				error = EAFNOSUPPORT;
5558				SCTP_TCB_UNLOCK(stcb);
5559				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
5560				break;
5561			}
5562		}
5563		/* sanity checks */
5564		if ((paddrp->spp_flags & SPP_HB_ENABLE) && (paddrp->spp_flags & SPP_HB_DISABLE)) {
5565			if (stcb)
5566				SCTP_TCB_UNLOCK(stcb);
5567			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5568			return (EINVAL);
5569		}
5570
5571		if ((paddrp->spp_flags & SPP_PMTUD_ENABLE) && (paddrp->spp_flags & SPP_PMTUD_DISABLE)) {
5572			if (stcb)
5573				SCTP_TCB_UNLOCK(stcb);
5574			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5575			return (EINVAL);
5576		}
5577
5578		if (stcb) {
5579			/************************TCB SPECIFIC SET ******************/
5580			/*
5581			 * do we change the timer for HB, we run
5582			 * only one?
5583			 */
5584			int ovh = 0;
5585
5586			if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
5587				ovh = SCTP_MED_OVERHEAD;
5588			} else {
5589				ovh = SCTP_MED_V4_OVERHEAD;
5590			}
5591
5592			/* network sets ? */
5593			if (net) {
5594				/************************NET SPECIFIC SET ******************/
5595				if (paddrp->spp_flags & SPP_HB_DISABLE) {
5596					if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
5597					    !(net->dest_state & SCTP_ADDR_NOHB)) {
5598						sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
5599								SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
5600					}
5601					net->dest_state |= SCTP_ADDR_NOHB;
5602				}
5603				if (paddrp->spp_flags & SPP_HB_ENABLE) {
5604					if (paddrp->spp_hbinterval) {
5605						net->heart_beat_delay = paddrp->spp_hbinterval;
5606					} else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
5607						net->heart_beat_delay = 0;
5608					}
5609					sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
5610					                SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
5611					sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
5612					net->dest_state &= ~SCTP_ADDR_NOHB;
5613				}
5614				if (paddrp->spp_flags & SPP_HB_DEMAND) {
5615					/* on demand HB */
5616					sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5617					sctp_chunk_output(inp, stcb,  SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED);
5618					sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
5619				}
5620				if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
5621					if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
5622						sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
5623								SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
5624					}
5625					net->dest_state |= SCTP_ADDR_NO_PMTUD;
5626					net->mtu = paddrp->spp_pathmtu + ovh;
5627					if (net->mtu < stcb->asoc.smallest_mtu) {
5628						sctp_pathmtu_adjustment(stcb, net->mtu);
5629					}
5630				}
5631				if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
5632					if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
5633						sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
5634					}
5635					net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
5636				}
5637				if (paddrp->spp_pathmaxrxt) {
5638					if (net->dest_state & SCTP_ADDR_PF) {
5639						if (net->error_count > paddrp->spp_pathmaxrxt) {
5640							net->dest_state &= ~SCTP_ADDR_PF;
5641						}
5642					} else {
5643						if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
5644						    (net->error_count > net->pf_threshold)) {
5645							net->dest_state |= SCTP_ADDR_PF;
5646							sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5647							sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
5648							sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
5649						}
5650					}
5651					if (net->dest_state & SCTP_ADDR_REACHABLE) {
5652						if (net->error_count > paddrp->spp_pathmaxrxt) {
5653					    		net->dest_state &= ~SCTP_ADDR_REACHABLE;
5654							sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
5655						}
5656					} else {
5657						if (net->error_count <= paddrp->spp_pathmaxrxt) {
5658							net->dest_state |= SCTP_ADDR_REACHABLE;
5659							sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
5660						}
5661					}
5662					net->failure_threshold = paddrp->spp_pathmaxrxt;
5663				}
5664				if (paddrp->spp_flags & SPP_DSCP) {
5665					net->dscp = paddrp->spp_dscp & 0xfc;
5666					net->dscp |= 0x01;
5667				}
5668#ifdef INET6
5669				if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
5670					if (net->ro._l_addr.sa.sa_family == AF_INET6) {
5671						net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5672						net->flowlabel |= 0x80000000;
5673					}
5674				}
5675#endif
5676			} else {
5677				/************************ASSOC ONLY -- NO NET SPECIFIC SET ******************/
5678				if (paddrp->spp_pathmaxrxt) {
5679					stcb->asoc.def_net_failure = paddrp->spp_pathmaxrxt;
5680					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5681						if (net->dest_state & SCTP_ADDR_PF) {
5682							if (net->error_count > paddrp->spp_pathmaxrxt) {
5683								net->dest_state &= ~SCTP_ADDR_PF;
5684							}
5685						} else {
5686							if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
5687							    (net->error_count > net->pf_threshold)) {
5688								net->dest_state |= SCTP_ADDR_PF;
5689								sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5690								sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
5691								sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
5692							}
5693						}
5694						if (net->dest_state & SCTP_ADDR_REACHABLE) {
5695							if (net->error_count > paddrp->spp_pathmaxrxt) {
5696						    		net->dest_state &= ~SCTP_ADDR_REACHABLE;
5697								sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
5698							}
5699						} else {
5700							if (net->error_count <= paddrp->spp_pathmaxrxt) {
5701								net->dest_state |= SCTP_ADDR_REACHABLE;
5702								sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
5703							}
5704						}
5705						net->failure_threshold = paddrp->spp_pathmaxrxt;
5706					}
5707				}
5708
5709				if (paddrp->spp_flags & SPP_HB_ENABLE) {
5710					if (paddrp->spp_hbinterval) {
5711						stcb->asoc.heart_beat_delay = paddrp->spp_hbinterval;
5712					} else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
5713						stcb->asoc.heart_beat_delay = 0;
5714					}
5715					/* Turn back on the timer */
5716					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5717						if (paddrp->spp_hbinterval) {
5718							net->heart_beat_delay = paddrp->spp_hbinterval;
5719						} else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
5720							net->heart_beat_delay = 0;
5721						}
5722						if (net->dest_state & SCTP_ADDR_NOHB) {
5723							net->dest_state &= ~SCTP_ADDR_NOHB;
5724						}
5725						sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
5726								SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
5727						sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
5728					}
5729					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5730				}
5731				if (paddrp->spp_flags & SPP_HB_DISABLE) {
5732					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5733						if (!(net->dest_state & SCTP_ADDR_NOHB)) {
5734							net->dest_state |= SCTP_ADDR_NOHB;
5735							if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED)) {
5736								sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
5737							}
5738						}
5739					}
5740					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5741				}
5742				if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
5743					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5744						if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
5745							sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
5746									SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
5747						}
5748						net->dest_state |= SCTP_ADDR_NO_PMTUD;
5749						net->mtu = paddrp->spp_pathmtu + ovh;
5750						if (net->mtu < stcb->asoc.smallest_mtu) {
5751							sctp_pathmtu_adjustment(stcb, net->mtu);
5752						}
5753					}
5754					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5755				}
5756				if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
5757					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5758						if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
5759							sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
5760						}
5761						net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
5762					}
5763					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5764				}
5765				if (paddrp->spp_flags & SPP_DSCP) {
5766					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5767						net->dscp = paddrp->spp_dscp & 0xfc;
5768						net->dscp |= 0x01;
5769					}
5770					stcb->asoc.default_dscp = paddrp->spp_dscp & 0xfc;
5771					stcb->asoc.default_dscp |= 0x01;
5772				}
5773#ifdef INET6
5774				if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
5775					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5776						if (net->ro._l_addr.sa.sa_family == AF_INET6) {
5777							net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5778							net->flowlabel |= 0x80000000;
5779						}
5780					}
5781					stcb->asoc.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5782					stcb->asoc.default_flowlabel |= 0x80000000;
5783				}
5784#endif
5785			}
5786			SCTP_TCB_UNLOCK(stcb);
5787		} else {
5788			/************************NO TCB, SET TO default stuff ******************/
5789			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5790			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5791			    (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC)) {
5792				SCTP_INP_WLOCK(inp);
5793				/*
5794				 * For the TOS/FLOWLABEL stuff you set it
5795				 * with the options on the socket
5796				 */
5797				if (paddrp->spp_pathmaxrxt) {
5798					inp->sctp_ep.def_net_failure = paddrp->spp_pathmaxrxt;
5799				}
5800
5801				if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO)
5802					inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
5803				else if (paddrp->spp_hbinterval) {
5804					if (paddrp->spp_hbinterval > SCTP_MAX_HB_INTERVAL)
5805						paddrp->spp_hbinterval= SCTP_MAX_HB_INTERVAL;
5806					inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
5807				}
5808
5809				if (paddrp->spp_flags & SPP_HB_ENABLE) {
5810					if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
5811						inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
5812					} else if (paddrp->spp_hbinterval) {
5813						inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
5814					}
5815					sctp_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5816				} else if (paddrp->spp_flags & SPP_HB_DISABLE) {
5817					sctp_feature_on(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5818				}
5819				if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
5820					sctp_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5821				} else if (paddrp->spp_flags & SPP_PMTUD_DISABLE) {
5822					sctp_feature_on(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5823				}
5824				if (paddrp->spp_flags & SPP_DSCP) {
5825					inp->sctp_ep.default_dscp = paddrp->spp_dscp & 0xfc;
5826					inp->sctp_ep.default_dscp |= 0x01;
5827				}
5828#ifdef INET6
5829				if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
5830					if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
5831						inp->sctp_ep.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5832						inp->sctp_ep.default_flowlabel |= 0x80000000;
5833					}
5834				}
5835#endif
5836				SCTP_INP_WUNLOCK(inp);
5837			} else {
5838				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5839				error = EINVAL;
5840			}
5841		}
5842		break;
5843	}
5844	case SCTP_RTOINFO:
5845	{
5846		struct sctp_rtoinfo *srto;
5847		uint32_t new_init, new_min, new_max;
5848
5849		SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, optsize);
5850		SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
5851
5852		if (stcb) {
5853			if (srto->srto_initial)
5854				new_init = srto->srto_initial;
5855			else
5856				new_init = stcb->asoc.initial_rto;
5857			if (srto->srto_max)
5858				new_max = srto->srto_max;
5859			else
5860				new_max = stcb->asoc.maxrto;
5861			if (srto->srto_min)
5862				new_min = srto->srto_min;
5863			else
5864				new_min = stcb->asoc.minrto;
5865			if ((new_min <= new_init) && (new_init <= new_max)) {
5866				stcb->asoc.initial_rto = new_init;
5867				stcb->asoc.maxrto = new_max;
5868				stcb->asoc.minrto = new_min;
5869			} else {
5870				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5871				error = EINVAL;
5872			}
5873			SCTP_TCB_UNLOCK(stcb);
5874		} else {
5875			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5876			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5877			    (srto->srto_assoc_id == SCTP_FUTURE_ASSOC)) {
5878				SCTP_INP_WLOCK(inp);
5879				if (srto->srto_initial)
5880					new_init = srto->srto_initial;
5881				else
5882					new_init = inp->sctp_ep.initial_rto;
5883				if (srto->srto_max)
5884					new_max = srto->srto_max;
5885				else
5886					new_max = inp->sctp_ep.sctp_maxrto;
5887				if (srto->srto_min)
5888					new_min = srto->srto_min;
5889				else
5890					new_min = inp->sctp_ep.sctp_minrto;
5891				if ((new_min <= new_init) && (new_init <= new_max)) {
5892					inp->sctp_ep.initial_rto = new_init;
5893					inp->sctp_ep.sctp_maxrto = new_max;
5894					inp->sctp_ep.sctp_minrto = new_min;
5895				} else {
5896					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5897					error = EINVAL;
5898				}
5899				SCTP_INP_WUNLOCK(inp);
5900			} else {
5901				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5902				error = EINVAL;
5903			}
5904		}
5905		break;
5906	}
5907	case SCTP_ASSOCINFO:
5908	{
5909		struct sctp_assocparams *sasoc;
5910
5911		SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, optsize);
5912		SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
5913		if (sasoc->sasoc_cookie_life) {
5914			/* boundary check the cookie life */
5915			if (sasoc->sasoc_cookie_life < 1000)
5916				sasoc->sasoc_cookie_life = 1000;
5917			if (sasoc->sasoc_cookie_life > SCTP_MAX_COOKIE_LIFE) {
5918				sasoc->sasoc_cookie_life = SCTP_MAX_COOKIE_LIFE;
5919			}
5920		}
5921		if (stcb) {
5922			if (sasoc->sasoc_asocmaxrxt)
5923				stcb->asoc.max_send_times = sasoc->sasoc_asocmaxrxt;
5924			if (sasoc->sasoc_cookie_life) {
5925				stcb->asoc.cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
5926			}
5927			SCTP_TCB_UNLOCK(stcb);
5928		} else {
5929			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5930			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5931			    (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC)) {
5932				SCTP_INP_WLOCK(inp);
5933				if (sasoc->sasoc_asocmaxrxt)
5934					inp->sctp_ep.max_send_times = sasoc->sasoc_asocmaxrxt;
5935				if (sasoc->sasoc_cookie_life) {
5936					inp->sctp_ep.def_cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
5937				}
5938				SCTP_INP_WUNLOCK(inp);
5939			} else {
5940				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5941				error = EINVAL;
5942			}
5943		}
5944		break;
5945	}
5946	case SCTP_INITMSG:
5947	{
5948		struct sctp_initmsg *sinit;
5949
5950		SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, optsize);
5951		SCTP_INP_WLOCK(inp);
5952		if (sinit->sinit_num_ostreams)
5953			inp->sctp_ep.pre_open_stream_count = sinit->sinit_num_ostreams;
5954
5955		if (sinit->sinit_max_instreams)
5956			inp->sctp_ep.max_open_streams_intome = sinit->sinit_max_instreams;
5957
5958		if (sinit->sinit_max_attempts)
5959			inp->sctp_ep.max_init_times = sinit->sinit_max_attempts;
5960
5961		if (sinit->sinit_max_init_timeo)
5962			inp->sctp_ep.initial_init_rto_max = sinit->sinit_max_init_timeo;
5963		SCTP_INP_WUNLOCK(inp);
5964		break;
5965	}
5966	case SCTP_PRIMARY_ADDR:
5967	{
5968		struct sctp_setprim *spa;
5969		struct sctp_nets *net;
5970
5971		SCTP_CHECK_AND_CAST(spa, optval, struct sctp_setprim, optsize);
5972		SCTP_FIND_STCB(inp, stcb, spa->ssp_assoc_id);
5973
5974		net = NULL;
5975		if (stcb) {
5976			net = sctp_findnet(stcb, (struct sockaddr *)&spa->ssp_addr);
5977		} else {
5978			/* We increment here since sctp_findassociation_ep_addr() wil
5979			 * do a decrement if it finds the stcb as long as the locked
5980			 * tcb (last argument) is NOT a TCB.. aka NULL.
5981			 */
5982			SCTP_INP_INCR_REF(inp);
5983			stcb = sctp_findassociation_ep_addr(&inp,
5984							    (struct sockaddr *)&spa->ssp_addr,
5985							    &net, NULL, NULL);
5986			if (stcb == NULL) {
5987				SCTP_INP_DECR_REF(inp);
5988			}
5989		}
5990
5991		if ((stcb) && (net)) {
5992			if ((net != stcb->asoc.primary_destination) &&
5993			    (!(net->dest_state & SCTP_ADDR_UNCONFIRMED))) {
5994				/* Ok we need to set it */
5995				if (sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net) == 0) {
5996					if ((stcb->asoc.alternate) &&
5997					    (!(net->dest_state & SCTP_ADDR_PF)) &&
5998					    (net->dest_state & SCTP_ADDR_REACHABLE)) {
5999						sctp_free_remote_addr(stcb->asoc.alternate);
6000						stcb->asoc.alternate = NULL;
6001					}
6002				}
6003			}
6004		} else {
6005			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6006			error = EINVAL;
6007		}
6008		if (stcb) {
6009			SCTP_TCB_UNLOCK(stcb);
6010		}
6011		break;
6012	}
6013	case SCTP_SET_DYNAMIC_PRIMARY:
6014	{
6015		union sctp_sockstore *ss;
6016#ifdef SCTP_MVRF
6017		int i, fnd = 0;
6018#endif
6019#if !defined(__Windows__) && !defined(__Userspace__)
6020#if defined(__APPLE__)
6021		struct proc *proc;
6022#endif
6023#ifdef __FreeBSD__
6024#if __FreeBSD_version > 602000
6025		error = priv_check(curthread,
6026				   PRIV_NETINET_RESERVEDPORT);
6027#elif __FreeBSD_version >= 500000
6028		error = suser((struct thread *)p);
6029#else
6030		error = suser(p);
6031#endif
6032#elif defined(__APPLE__)
6033		proc = (struct proc *)p;
6034		if (p) {
6035			error = suser(proc->p_ucred, &proc->p_acflag);
6036		} else {
6037			break;
6038		}
6039#else
6040		error = suser(p, 0);
6041#endif
6042#endif
6043		if (error)
6044			break;
6045
6046		SCTP_CHECK_AND_CAST(ss, optval, union sctp_sockstore, optsize);
6047		/* SUPER USER CHECK? */
6048#ifdef SCTP_MVRF
6049		for (i = 0; i < inp->num_vrfs; i++) {
6050			if (vrf_id == inp->m_vrf_ids[i]) {
6051				fnd = 1;
6052				break;
6053			}
6054		}
6055		if (!fnd) {
6056			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6057			error = EINVAL;
6058			break;
6059		}
6060#endif
6061		error = sctp_dynamic_set_primary(&ss->sa, vrf_id);
6062		break;
6063	}
6064	case SCTP_SET_PEER_PRIMARY_ADDR:
6065	{
6066		struct sctp_setpeerprim *sspp;
6067
6068		SCTP_CHECK_AND_CAST(sspp, optval, struct sctp_setpeerprim, optsize);
6069		SCTP_FIND_STCB(inp, stcb, sspp->sspp_assoc_id);
6070		if (stcb != NULL) {
6071			struct sctp_ifa *ifa;
6072			ifa = sctp_find_ifa_by_addr((struct sockaddr *)&sspp->sspp_addr,
6073						    stcb->asoc.vrf_id, SCTP_ADDR_NOT_LOCKED);
6074			if (ifa == NULL) {
6075				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6076				error = EINVAL;
6077				goto out_of_it;
6078			}
6079			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
6080				/* Must validate the ifa found is in our ep */
6081				struct sctp_laddr *laddr;
6082				int found = 0;
6083				LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
6084					if (laddr->ifa == NULL) {
6085						SCTPDBG(SCTP_DEBUG_OUTPUT1, "%s: NULL ifa\n",
6086							__FUNCTION__);
6087						continue;
6088					}
6089					if (laddr->ifa == ifa) {
6090						found = 1;
6091						break;
6092					}
6093				}
6094				if (!found) {
6095					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6096					error = EINVAL;
6097					goto out_of_it;
6098				}
6099			}
6100			if (sctp_set_primary_ip_address_sa(stcb,
6101							   (struct sockaddr *)&sspp->sspp_addr) != 0) {
6102				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6103				error = EINVAL;
6104			}
6105		out_of_it:
6106			SCTP_TCB_UNLOCK(stcb);
6107		} else {
6108			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6109			error = EINVAL;
6110		}
6111		break;
6112	}
6113	case SCTP_BINDX_ADD_ADDR:
6114	{
6115		struct sctp_getaddresses *addrs;
6116#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
6117		struct thread *td;
6118
6119		td = (struct thread *)p;
6120#endif
6121		SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses,
6122				    optsize);
6123#ifdef INET
6124		if (addrs->addr->sa_family == AF_INET) {
6125			if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in)) {
6126				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6127				error = EINVAL;
6128				break;
6129			}
6130#if defined(__FreeBSD__) && __FreeBSD_version >= 800000
6131			if (td != NULL && (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)(addrs->addr))->sin_addr)))) {
6132				SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
6133				break;
6134			}
6135#endif
6136		} else
6137#endif
6138#ifdef INET6
6139		if (addrs->addr->sa_family == AF_INET6) {
6140			if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6)) {
6141				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6142				error = EINVAL;
6143				break;
6144			}
6145#if defined(__FreeBSD__) && __FreeBSD_version >= 800000
6146			if (td != NULL && (error = prison_local_ip6(td->td_ucred, &(((struct sockaddr_in6 *)(addrs->addr))->sin6_addr),
6147											   (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
6148			  SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
6149			  break;
6150			}
6151#endif
6152		} else
6153#endif
6154		{
6155		       error = EAFNOSUPPORT;
6156  		       break;
6157		}
6158		sctp_bindx_add_address(so, inp, addrs->addr,
6159				       addrs->sget_assoc_id, vrf_id,
6160				       &error, p);
6161		break;
6162	}
6163	case SCTP_BINDX_REM_ADDR:
6164	{
6165		struct sctp_getaddresses *addrs;
6166#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
6167		struct thread *td;
6168		td = (struct thread *)p;
6169
6170#endif
6171		SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses, optsize);
6172#ifdef INET
6173		if (addrs->addr->sa_family == AF_INET) {
6174			if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in)) {
6175				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6176				error = EINVAL;
6177				break;
6178			}
6179#if defined(__FreeBSD__) && __FreeBSD_version >= 800000
6180		if (td != NULL && (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)(addrs->addr))->sin_addr)))) {
6181				SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
6182				break;
6183			}
6184#endif
6185		} else
6186#endif
6187#ifdef INET6
6188		if (addrs->addr->sa_family == AF_INET6) {
6189			if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6)) {
6190				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6191				error = EINVAL;
6192				break;
6193			}
6194#if defined(__FreeBSD__) && __FreeBSD_version >= 800000
6195			if (td != NULL &&
6196			    (error = prison_local_ip6(td->td_ucred,
6197			                              &(((struct sockaddr_in6 *)(addrs->addr))->sin6_addr),
6198			                              (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
6199				SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
6200				break;
6201			}
6202#endif
6203		} else
6204#endif
6205		{
6206			error = EAFNOSUPPORT;
6207			break;
6208		}
6209		sctp_bindx_delete_address(inp, addrs->addr,
6210					  addrs->sget_assoc_id, vrf_id,
6211					  &error);
6212		break;
6213	}
6214#ifdef __APPLE__
6215	case SCTP_LISTEN_FIX:
6216		/* only applies to one-to-many sockets */
6217		if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
6218			/* make sure the ACCEPTCONN flag is OFF */
6219			so->so_options &= ~SO_ACCEPTCONN;
6220		} else {
6221			/* otherwise, not allowed */
6222			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6223			error = EINVAL;
6224		}
6225		break;
6226#endif				/* __APPLE__ */
6227	case SCTP_EVENT:
6228	{
6229		struct sctp_event *event;
6230		uint32_t event_type;
6231
6232		SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, optsize);
6233		SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
6234		switch (event->se_type) {
6235		case SCTP_ASSOC_CHANGE:
6236			event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
6237			break;
6238		case SCTP_PEER_ADDR_CHANGE:
6239			event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
6240			break;
6241		case SCTP_REMOTE_ERROR:
6242			event_type = SCTP_PCB_FLAGS_RECVPEERERR;
6243			break;
6244		case SCTP_SEND_FAILED:
6245			event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
6246			break;
6247		case SCTP_SHUTDOWN_EVENT:
6248			event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
6249			break;
6250		case SCTP_ADAPTATION_INDICATION:
6251			event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
6252			break;
6253		case SCTP_PARTIAL_DELIVERY_EVENT:
6254			event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
6255			break;
6256		case SCTP_AUTHENTICATION_EVENT:
6257			event_type = SCTP_PCB_FLAGS_AUTHEVNT;
6258			break;
6259		case SCTP_STREAM_RESET_EVENT:
6260			event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
6261			break;
6262		case SCTP_SENDER_DRY_EVENT:
6263			event_type = SCTP_PCB_FLAGS_DRYEVNT;
6264			break;
6265		case SCTP_NOTIFICATIONS_STOPPED_EVENT:
6266			event_type = 0;
6267			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
6268			error = ENOTSUP;
6269			break;
6270		case SCTP_ASSOC_RESET_EVENT:
6271			event_type = SCTP_PCB_FLAGS_ASSOC_RESETEVNT;
6272			break;
6273		case SCTP_STREAM_CHANGE_EVENT:
6274			event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT;
6275			break;
6276		case SCTP_SEND_FAILED_EVENT:
6277			event_type = SCTP_PCB_FLAGS_RECVNSENDFAILEVNT;
6278			break;
6279		default:
6280			event_type = 0;
6281			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6282			error = EINVAL;
6283			break;
6284		}
6285		if (event_type > 0) {
6286			if (stcb) {
6287				if (event->se_on) {
6288					sctp_stcb_feature_on(inp, stcb, event_type);
6289					if (event_type == SCTP_PCB_FLAGS_DRYEVNT) {
6290						if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
6291						    TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
6292						    (stcb->asoc.stream_queue_cnt == 0)) {
6293							sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb,  0, NULL, SCTP_SO_LOCKED);
6294						}
6295					}
6296				} else {
6297					sctp_stcb_feature_off(inp, stcb, event_type);
6298				}
6299				SCTP_TCB_UNLOCK(stcb);
6300			} else {
6301				/*
6302				 * We don't want to send up a storm of events,
6303				 * so return an error for sender dry events
6304				 */
6305				if ((event_type == SCTP_PCB_FLAGS_DRYEVNT) &&
6306				    ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) == 0) &&
6307				    ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
6308				    ((event->se_assoc_id == SCTP_ALL_ASSOC) ||
6309				     (event->se_assoc_id == SCTP_CURRENT_ASSOC))) {
6310					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
6311					error = ENOTSUP;
6312					break;
6313				}
6314				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6315				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6316				    (event->se_assoc_id == SCTP_FUTURE_ASSOC) ||
6317				    (event->se_assoc_id == SCTP_ALL_ASSOC)) {
6318					SCTP_INP_WLOCK(inp);
6319					if (event->se_on) {
6320						sctp_feature_on(inp, event_type);
6321					} else {
6322						sctp_feature_off(inp, event_type);
6323					}
6324					SCTP_INP_WUNLOCK(inp);
6325				}
6326				if ((event->se_assoc_id == SCTP_CURRENT_ASSOC) ||
6327				    (event->se_assoc_id == SCTP_ALL_ASSOC)) {
6328					SCTP_INP_RLOCK(inp);
6329					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
6330						SCTP_TCB_LOCK(stcb);
6331						if (event->se_on) {
6332							sctp_stcb_feature_on(inp, stcb, event_type);
6333						} else {
6334							sctp_stcb_feature_off(inp, stcb, event_type);
6335						}
6336						SCTP_TCB_UNLOCK(stcb);
6337					}
6338					SCTP_INP_RUNLOCK(inp);
6339				}
6340			}
6341		}
6342		break;
6343	}
6344	case SCTP_RECVRCVINFO:
6345	{
6346		int *onoff;
6347
6348		SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
6349		SCTP_INP_WLOCK(inp);
6350		if (*onoff != 0) {
6351			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
6352		} else {
6353			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
6354		}
6355		SCTP_INP_WUNLOCK(inp);
6356		break;
6357	}
6358	case SCTP_RECVNXTINFO:
6359	{
6360		int *onoff;
6361
6362		SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
6363		SCTP_INP_WLOCK(inp);
6364		if (*onoff != 0) {
6365			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
6366		} else {
6367			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
6368		}
6369		SCTP_INP_WUNLOCK(inp);
6370		break;
6371	}
6372	case SCTP_DEFAULT_SNDINFO:
6373	{
6374		struct sctp_sndinfo *info;
6375		uint16_t policy;
6376
6377		SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, optsize);
6378		SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
6379
6380		if (stcb) {
6381			if (info->snd_sid < stcb->asoc.streamoutcnt) {
6382				stcb->asoc.def_send.sinfo_stream = info->snd_sid;
6383				policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
6384				stcb->asoc.def_send.sinfo_flags = info->snd_flags;
6385				stcb->asoc.def_send.sinfo_flags |= policy;
6386				stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
6387				stcb->asoc.def_send.sinfo_context = info->snd_context;
6388			} else {
6389				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6390				error = EINVAL;
6391			}
6392			SCTP_TCB_UNLOCK(stcb);
6393		} else {
6394			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6395			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6396			    (info->snd_assoc_id == SCTP_FUTURE_ASSOC) ||
6397			    (info->snd_assoc_id == SCTP_ALL_ASSOC)) {
6398				SCTP_INP_WLOCK(inp);
6399				inp->def_send.sinfo_stream = info->snd_sid;
6400				policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
6401				inp->def_send.sinfo_flags = info->snd_flags;
6402				inp->def_send.sinfo_flags |= policy;
6403				inp->def_send.sinfo_ppid = info->snd_ppid;
6404				inp->def_send.sinfo_context = info->snd_context;
6405				SCTP_INP_WUNLOCK(inp);
6406			}
6407			if ((info->snd_assoc_id == SCTP_CURRENT_ASSOC) ||
6408			    (info->snd_assoc_id == SCTP_ALL_ASSOC)) {
6409				SCTP_INP_RLOCK(inp);
6410				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
6411					SCTP_TCB_LOCK(stcb);
6412					if (info->snd_sid < stcb->asoc.streamoutcnt) {
6413						stcb->asoc.def_send.sinfo_stream = info->snd_sid;
6414						policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
6415						stcb->asoc.def_send.sinfo_flags = info->snd_flags;
6416						stcb->asoc.def_send.sinfo_flags |= policy;
6417						stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
6418						stcb->asoc.def_send.sinfo_context = info->snd_context;
6419					}
6420					SCTP_TCB_UNLOCK(stcb);
6421				}
6422				SCTP_INP_RUNLOCK(inp);
6423			}
6424		}
6425		break;
6426	}
6427	case SCTP_DEFAULT_PRINFO:
6428	{
6429		struct sctp_default_prinfo *info;
6430
6431		SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, optsize);
6432		SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
6433
6434		if (PR_SCTP_INVALID_POLICY(info->pr_policy)) {
6435			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6436			error = EINVAL;
6437			break;
6438		}
6439		if (stcb) {
6440			stcb->asoc.def_send.sinfo_flags &= 0xfff0;
6441			stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
6442			stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
6443			SCTP_TCB_UNLOCK(stcb);
6444		} else {
6445			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6446			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6447			    (info->pr_assoc_id == SCTP_FUTURE_ASSOC) ||
6448			    (info->pr_assoc_id == SCTP_ALL_ASSOC)) {
6449				SCTP_INP_WLOCK(inp);
6450				inp->def_send.sinfo_flags &= 0xfff0;
6451				inp->def_send.sinfo_flags |= info->pr_policy;
6452				inp->def_send.sinfo_timetolive = info->pr_value;
6453				SCTP_INP_WUNLOCK(inp);
6454			}
6455			if ((info->pr_assoc_id == SCTP_CURRENT_ASSOC) ||
6456			    (info->pr_assoc_id == SCTP_ALL_ASSOC)) {
6457				SCTP_INP_RLOCK(inp);
6458				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
6459					SCTP_TCB_LOCK(stcb);
6460					stcb->asoc.def_send.sinfo_flags &= 0xfff0;
6461					stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
6462					stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
6463					SCTP_TCB_UNLOCK(stcb);
6464				}
6465				SCTP_INP_RUNLOCK(inp);
6466			}
6467		}
6468		break;
6469	}
6470	case SCTP_PEER_ADDR_THLDS:
6471		/* Applies to the specific association */
6472	{
6473		struct sctp_paddrthlds *thlds;
6474		struct sctp_nets *net;
6475
6476		SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, optsize);
6477		SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
6478		net = NULL;
6479		if (stcb) {
6480			net = sctp_findnet(stcb, (struct sockaddr *)&thlds->spt_assoc_id);
6481		} else {
6482			/* We increment here since sctp_findassociation_ep_addr() wil
6483			 * do a decrement if it finds the stcb as long as the locked
6484			 * tcb (last argument) is NOT a TCB.. aka NULL.
6485			 */
6486			SCTP_INP_INCR_REF(inp);
6487			stcb = sctp_findassociation_ep_addr(&inp,
6488							    (struct sockaddr *)&thlds->spt_assoc_id,
6489							    &net, NULL, NULL);
6490			if (stcb == NULL) {
6491				SCTP_INP_DECR_REF(inp);
6492			}
6493		}
6494		if (stcb && (net == NULL)) {
6495			struct sockaddr *sa;
6496
6497			sa = (struct sockaddr *)&thlds->spt_assoc_id;
6498#ifdef INET
6499			if (sa->sa_family == AF_INET) {
6500
6501				struct sockaddr_in *sin;
6502				sin = (struct sockaddr_in *)sa;
6503				if (sin->sin_addr.s_addr) {
6504					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6505					SCTP_TCB_UNLOCK(stcb);
6506					error = EINVAL;
6507					break;
6508				}
6509			} else
6510#endif
6511#ifdef INET6
6512			if (sa->sa_family == AF_INET6) {
6513				struct sockaddr_in6 *sin6;
6514
6515				sin6 = (struct sockaddr_in6 *)sa;
6516				if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
6517					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6518					SCTP_TCB_UNLOCK(stcb);
6519					error = EINVAL;
6520					break;
6521				}
6522			} else
6523#endif
6524#if defined(__Userspace__)
6525			if (sa->sa_family == AF_CONN) {
6526				struct sockaddr_conn *sconn;
6527
6528				sconn = (struct sockaddr_conn *)sa;
6529				if (sconn->sconn_addr != NULL) {
6530					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6531					SCTP_TCB_UNLOCK(stcb);
6532					error = EINVAL;
6533					break;
6534				}
6535			} else
6536#endif
6537			{
6538				error = EAFNOSUPPORT;
6539				SCTP_TCB_UNLOCK(stcb);
6540				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6541				break;
6542			}
6543		}
6544		if (stcb) {
6545			if (net) {
6546				if (net->dest_state & SCTP_ADDR_PF) {
6547					if ((net->failure_threshold > thlds->spt_pathmaxrxt) ||
6548					    (net->failure_threshold <= thlds->spt_pathpfthld)) {
6549						net->dest_state &= ~SCTP_ADDR_PF;
6550					}
6551				} else {
6552					if ((net->failure_threshold > thlds->spt_pathpfthld) &&
6553					    (net->failure_threshold <= thlds->spt_pathmaxrxt)) {
6554					    	net->dest_state |= SCTP_ADDR_PF;
6555						sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
6556						sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
6557						sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
6558					}
6559				}
6560				if (net->dest_state & SCTP_ADDR_REACHABLE) {
6561					if (net->failure_threshold > thlds->spt_pathmaxrxt) {
6562						net->dest_state &= ~SCTP_ADDR_REACHABLE;
6563						sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
6564					}
6565				} else {
6566					if (net->failure_threshold <= thlds->spt_pathmaxrxt) {
6567						net->dest_state |= SCTP_ADDR_REACHABLE;
6568						sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
6569					}
6570				}
6571				net->failure_threshold = thlds->spt_pathmaxrxt;
6572				net->pf_threshold = thlds->spt_pathpfthld;
6573			} else {
6574				TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6575					if (net->dest_state & SCTP_ADDR_PF) {
6576						if ((net->failure_threshold > thlds->spt_pathmaxrxt) ||
6577						    (net->failure_threshold <= thlds->spt_pathpfthld)) {
6578							net->dest_state &= ~SCTP_ADDR_PF;
6579						}
6580					} else {
6581						if ((net->failure_threshold > thlds->spt_pathpfthld) &&
6582						    (net->failure_threshold <= thlds->spt_pathmaxrxt)) {
6583						    	net->dest_state |= SCTP_ADDR_PF;
6584							sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
6585							sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
6586							sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
6587						}
6588					}
6589					if (net->dest_state & SCTP_ADDR_REACHABLE) {
6590						if (net->failure_threshold > thlds->spt_pathmaxrxt) {
6591							net->dest_state &= ~SCTP_ADDR_REACHABLE;
6592							sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
6593						}
6594					} else {
6595						if (net->failure_threshold <= thlds->spt_pathmaxrxt) {
6596							net->dest_state |= SCTP_ADDR_REACHABLE;
6597							sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
6598						}
6599					}
6600					net->failure_threshold = thlds->spt_pathmaxrxt;
6601					net->pf_threshold = thlds->spt_pathpfthld;
6602				}
6603				stcb->asoc.def_net_failure = thlds->spt_pathmaxrxt;
6604				stcb->asoc.def_net_pf_threshold = thlds->spt_pathpfthld;
6605			}
6606		} else {
6607			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6608			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6609			    (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC)) {
6610				SCTP_INP_WLOCK(inp);
6611				inp->sctp_ep.def_net_failure = thlds->spt_pathmaxrxt;
6612				inp->sctp_ep.def_net_pf_threshold = thlds->spt_pathpfthld;
6613				SCTP_INP_WUNLOCK(inp);
6614			} else {
6615				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6616				error = EINVAL;
6617			}
6618		}
6619		break;
6620	}
6621	case SCTP_REMOTE_UDP_ENCAPS_PORT:
6622	{
6623		struct sctp_udpencaps *encaps;
6624		struct sctp_nets *net;
6625
6626		SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, optsize);
6627		SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
6628		if (stcb) {
6629			net = sctp_findnet(stcb, (struct sockaddr *)&encaps->sue_address);
6630		} else {
6631			/* We increment here since sctp_findassociation_ep_addr() wil
6632			 * do a decrement if it finds the stcb as long as the locked
6633			 * tcb (last argument) is NOT a TCB.. aka NULL.
6634			 */
6635			net = NULL;
6636			SCTP_INP_INCR_REF(inp);
6637			stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&encaps->sue_address, &net, NULL, NULL);
6638			if (stcb == NULL) {
6639				SCTP_INP_DECR_REF(inp);
6640			}
6641		}
6642		if (stcb && (net == NULL)) {
6643			struct sockaddr *sa;
6644
6645			sa = (struct sockaddr *)&encaps->sue_address;
6646#ifdef INET
6647			if (sa->sa_family == AF_INET) {
6648
6649				struct sockaddr_in *sin;
6650				sin = (struct sockaddr_in *)sa;
6651				if (sin->sin_addr.s_addr) {
6652					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6653					SCTP_TCB_UNLOCK(stcb);
6654					error = EINVAL;
6655					break;
6656				}
6657			} else
6658#endif
6659#ifdef INET6
6660			if (sa->sa_family == AF_INET6) {
6661				struct sockaddr_in6 *sin6;
6662
6663				sin6 = (struct sockaddr_in6 *)sa;
6664				if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
6665					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6666					SCTP_TCB_UNLOCK(stcb);
6667					error = EINVAL;
6668					break;
6669				}
6670			} else
6671#endif
6672#if defined(__Userspace__)
6673			if (sa->sa_family == AF_CONN) {
6674				struct sockaddr_conn *sconn;
6675
6676				sconn = (struct sockaddr_conn *)sa;
6677				if (sconn->sconn_addr != NULL) {
6678					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6679					SCTP_TCB_UNLOCK(stcb);
6680					error = EINVAL;
6681					break;
6682				}
6683			} else
6684#endif
6685			{
6686					error = EAFNOSUPPORT;
6687					SCTP_TCB_UNLOCK(stcb);
6688					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6689					break;
6690				}
6691		}
6692
6693		if (stcb) {
6694			if (net) {
6695				net->port = encaps->sue_port;
6696			} else {
6697				stcb->asoc.port = encaps->sue_port;
6698			}
6699			SCTP_TCB_UNLOCK(stcb);
6700		} else {
6701			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6702			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6703			    (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC)) {
6704				SCTP_INP_WLOCK(inp);
6705				inp->sctp_ep.port = encaps->sue_port;
6706				SCTP_INP_WUNLOCK(inp);
6707			} else {
6708				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6709				error = EINVAL;
6710			}
6711		}
6712		break;
6713	}
6714	default:
6715		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
6716		error = ENOPROTOOPT;
6717		break;
6718	} /* end switch (opt) */
6719	return (error);
6720}
6721
6722#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
6723int
6724sctp_ctloutput(struct socket *so, struct sockopt *sopt)
6725{
6726	void *optval = NULL;
6727	size_t optsize = 0;
6728	void *p;
6729	int error = 0;
6730
6731	if (sopt->sopt_level != IPPROTO_SCTP) {
6732		/* wrong proto level... send back up to IP */
6733#ifdef INET6
6734		if (INP_CHECK_SOCKAF(so, AF_INET6))
6735			error = ip6_ctloutput(so, sopt);
6736#endif				/* INET6 */
6737#if defined(INET) && defined(INET6)
6738		else
6739#endif
6740#ifdef INET
6741			error = ip_ctloutput(so, sopt);
6742#endif
6743		return (error);
6744	}
6745	optsize = sopt->sopt_valsize;
6746	if (optsize) {
6747		SCTP_MALLOC(optval, void *, optsize, SCTP_M_SOCKOPT);
6748		if (optval == NULL) {
6749			SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS);
6750			return (ENOBUFS);
6751		}
6752		error = sooptcopyin(sopt, optval, optsize, optsize);
6753		if (error) {
6754			SCTP_FREE(optval, SCTP_M_SOCKOPT);
6755			goto out;
6756		}
6757	}
6758#if (defined(__FreeBSD__) && __FreeBSD_version >= 500000) || defined(__Windows__)
6759	p = (void *)sopt->sopt_td;
6760#else
6761	p = (void *)sopt->sopt_p;
6762#endif
6763	if (sopt->sopt_dir == SOPT_SET) {
6764		error = sctp_setopt(so, sopt->sopt_name, optval, optsize, p);
6765	} else if (sopt->sopt_dir == SOPT_GET) {
6766		error = sctp_getopt(so, sopt->sopt_name, optval, &optsize, p);
6767	} else {
6768		SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6769		error = EINVAL;
6770	}
6771	if ((error == 0) && (optval != NULL)) {
6772		error = sooptcopyout(sopt, optval, optsize);
6773		SCTP_FREE(optval, SCTP_M_SOCKOPT);
6774	} else if (optval != NULL) {
6775		SCTP_FREE(optval, SCTP_M_SOCKOPT);
6776	}
6777out:
6778	return (error);
6779}
6780#endif
6781
6782#ifdef INET
6783#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
6784static int
6785sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
6786{
6787#else
6788#if defined(__FreeBSD__) || defined(__APPLE__)
6789static int
6790sctp_connect(struct socket *so, struct sockaddr *addr, struct proc *p)
6791{
6792#elif defined(__Panda__) || defined(__Userspace__)
6793int
6794sctp_connect(struct socket *so, struct sockaddr *addr)
6795{
6796	void *p = NULL;
6797#elif defined(__Windows__)
6798static int
6799sctp_connect(struct socket *so, struct sockaddr *addr, PKTHREAD p)
6800{
6801#else
6802static int
6803sctp_connect(struct socket *so, struct mbuf *nam, struct proc *p)
6804{
6805	struct sockaddr *addr = mtod(nam, struct sockaddr *);
6806
6807#endif
6808#endif
6809#ifdef SCTP_MVRF
6810	int i, fnd = 0;
6811#endif
6812	int error = 0;
6813	int create_lock_on = 0;
6814	uint32_t vrf_id;
6815	struct sctp_inpcb *inp;
6816	struct sctp_tcb *stcb = NULL;
6817
6818	inp = (struct sctp_inpcb *)so->so_pcb;
6819	if (inp == NULL) {
6820		/* I made the same as TCP since we are not setup? */
6821		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6822		return (ECONNRESET);
6823	}
6824	if (addr == NULL) {
6825		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6826		return EINVAL;
6827	}
6828
6829#if defined(__Userspace__)
6830        /* TODO __Userspace__ falls into this code for IPv6 stuff at the moment... */
6831#endif
6832#if !defined(__Windows__) && !defined(__Userspace_os_Linux) && !defined(__Userspace_os_Windows)
6833	switch (addr->sa_family) {
6834#ifdef INET6
6835	case AF_INET6:
6836	{
6837#if defined(__FreeBSD__) && __FreeBSD_version >= 800000
6838		struct sockaddr_in6 *sin6p;
6839
6840#endif
6841		if (addr->sa_len != sizeof(struct sockaddr_in6)) {
6842			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6843			return (EINVAL);
6844		}
6845#if defined(__FreeBSD__) && __FreeBSD_version >= 800000
6846		sin6p = (struct sockaddr_in6 *)addr;
6847		if (p != NULL && (error = prison_remote_ip6(p->td_ucred, &sin6p->sin6_addr)) != 0) {
6848			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6849			return (error);
6850		}
6851#endif
6852		break;
6853	}
6854#endif
6855#ifdef INET
6856	case AF_INET:
6857	{
6858#if defined(__FreeBSD__) && __FreeBSD_version >= 800000
6859		struct sockaddr_in *sinp;
6860
6861#endif
6862#if !defined(__Userspace_os_Windows)
6863		if (addr->sa_len != sizeof(struct sockaddr_in)) {
6864			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6865			return (EINVAL);
6866		}
6867#endif
6868#if defined(__FreeBSD__) && __FreeBSD_version >= 800000
6869		sinp = (struct sockaddr_in *)addr;
6870		if (p != NULL && (error = prison_remote_ip4(p->td_ucred, &sinp->sin_addr)) != 0) {
6871			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6872			return (error);
6873		}
6874#endif
6875		break;
6876	}
6877#endif
6878	default:
6879		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
6880 		return (EAFNOSUPPORT);
6881	}
6882#endif
6883	SCTP_INP_INCR_REF(inp);
6884	SCTP_ASOC_CREATE_LOCK(inp);
6885	create_lock_on = 1;
6886
6887
6888	if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
6889	    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
6890		/* Should I really unlock ? */
6891		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
6892	        error = EFAULT;
6893		goto out_now;
6894	}
6895#ifdef INET6
6896	if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
6897	    (addr->sa_family == AF_INET6)) {
6898		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6899		error = EINVAL;
6900		goto out_now;
6901	}
6902#endif
6903#if defined(__Userspace__)
6904	if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_CONN) &&
6905	    (addr->sa_family != AF_CONN)) {
6906		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6907		error = EINVAL;
6908		goto out_now;
6909	}
6910#endif
6911	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
6912	    SCTP_PCB_FLAGS_UNBOUND) {
6913		/* Bind a ephemeral port */
6914		error = sctp_inpcb_bind(so, NULL, NULL, p);
6915		if (error) {
6916			goto out_now;
6917		}
6918	}
6919	/* Now do we connect? */
6920	if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
6921	    (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
6922		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6923		error = EINVAL;
6924		goto out_now;
6925	}
6926	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
6927	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
6928		/* We are already connected AND the TCP model */
6929		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
6930		error = EADDRINUSE;
6931		goto out_now;
6932	}
6933	if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
6934		SCTP_INP_RLOCK(inp);
6935		stcb = LIST_FIRST(&inp->sctp_asoc_list);
6936		SCTP_INP_RUNLOCK(inp);
6937	} else {
6938		/* We increment here since sctp_findassociation_ep_addr() will
6939		 * do a decrement if it finds the stcb as long as the locked
6940		 * tcb (last argument) is NOT a TCB.. aka NULL.
6941		 */
6942		SCTP_INP_INCR_REF(inp);
6943		stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
6944		if (stcb == NULL) {
6945			SCTP_INP_DECR_REF(inp);
6946		} else {
6947			SCTP_TCB_UNLOCK(stcb);
6948		}
6949	}
6950	if (stcb != NULL) {
6951		/* Already have or am bring up an association */
6952		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
6953		error = EALREADY;
6954		goto out_now;
6955	}
6956
6957	vrf_id = inp->def_vrf_id;
6958#ifdef SCTP_MVRF
6959	for (i = 0; i < inp->num_vrfs; i++) {
6960		if (vrf_id == inp->m_vrf_ids[i]) {
6961			fnd = 1;
6962			break;
6963		}
6964	}
6965	if (!fnd) {
6966		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6967		error = EINVAL;
6968		goto out_now;
6969	}
6970#endif
6971	/* We are GOOD to go */
6972	stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, p);
6973	if (stcb == NULL) {
6974		/* Gak! no memory */
6975		goto out_now;
6976	}
6977	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
6978		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
6979		/* Set the connected flag so we can queue data */
6980		soisconnecting(so);
6981	}
6982	SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
6983	(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
6984
6985	/* initialize authentication parameters for the assoc */
6986	sctp_initialize_auth_params(inp, stcb);
6987
6988	sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
6989	SCTP_TCB_UNLOCK(stcb);
6990 out_now:
6991	if (create_lock_on) {
6992		SCTP_ASOC_CREATE_UNLOCK(inp);
6993	}
6994
6995	SCTP_INP_DECR_REF(inp);
6996	return (error);
6997}
6998#endif
6999
7000#if defined(__Userspace__)
7001int
7002sctpconn_connect(struct socket *so, struct sockaddr *addr)
7003{
7004#ifdef SCTP_MVRF
7005	int i, fnd = 0;
7006#endif
7007	void *p = NULL;
7008	int error = 0;
7009	int create_lock_on = 0;
7010	uint32_t vrf_id;
7011	struct sctp_inpcb *inp;
7012	struct sctp_tcb *stcb = NULL;
7013
7014	inp = (struct sctp_inpcb *)so->so_pcb;
7015	if (inp == NULL) {
7016		/* I made the same as TCP since we are not setup? */
7017		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7018		return (ECONNRESET);
7019	}
7020	if (addr == NULL) {
7021		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7022		return EINVAL;
7023	}
7024	switch (addr->sa_family) {
7025#ifdef INET
7026	case AF_INET:
7027#ifdef HAVE_SA_LEN
7028		if (addr->sa_len != sizeof(struct sockaddr_in)) {
7029			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7030			return (EINVAL);
7031		}
7032#endif
7033		break;
7034#endif
7035#ifdef INET6
7036	case AF_INET6:
7037#ifdef HAVE_SA_LEN
7038		if (addr->sa_len != sizeof(struct sockaddr_in6)) {
7039			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7040			return (EINVAL);
7041		}
7042#endif
7043		break;
7044#endif
7045	case AF_CONN:
7046#ifdef HAVE_SA_LEN
7047		if (addr->sa_len != sizeof(struct sockaddr_conn)) {
7048			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7049			return (EINVAL);
7050		}
7051#endif
7052		break;
7053	default:
7054		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
7055 		return (EAFNOSUPPORT);
7056	}
7057	SCTP_INP_INCR_REF(inp);
7058	SCTP_ASOC_CREATE_LOCK(inp);
7059	create_lock_on = 1;
7060
7061
7062	if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
7063	    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
7064		/* Should I really unlock ? */
7065		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
7066	        error = EFAULT;
7067		goto out_now;
7068	}
7069#ifdef INET6
7070	if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
7071	    (addr->sa_family == AF_INET6)) {
7072		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7073		error = EINVAL;
7074		goto out_now;
7075	}
7076#endif
7077	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == SCTP_PCB_FLAGS_UNBOUND) {
7078		/* Bind a ephemeral port */
7079		error = sctp_inpcb_bind(so, NULL, NULL, p);
7080		if (error) {
7081			goto out_now;
7082		}
7083	}
7084	/* Now do we connect? */
7085	if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
7086	    (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
7087		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7088		error = EINVAL;
7089		goto out_now;
7090	}
7091	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
7092	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
7093		/* We are already connected AND the TCP model */
7094		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
7095		error = EADDRINUSE;
7096		goto out_now;
7097	}
7098	if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
7099		SCTP_INP_RLOCK(inp);
7100		stcb = LIST_FIRST(&inp->sctp_asoc_list);
7101		SCTP_INP_RUNLOCK(inp);
7102	} else {
7103		/* We increment here since sctp_findassociation_ep_addr() will
7104		 * do a decrement if it finds the stcb as long as the locked
7105		 * tcb (last argument) is NOT a TCB.. aka NULL.
7106		 */
7107		SCTP_INP_INCR_REF(inp);
7108		stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
7109		if (stcb == NULL) {
7110			SCTP_INP_DECR_REF(inp);
7111		} else {
7112			SCTP_TCB_UNLOCK(stcb);
7113		}
7114	}
7115	if (stcb != NULL) {
7116		/* Already have or am bring up an association */
7117		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
7118		error = EALREADY;
7119		goto out_now;
7120	}
7121
7122	vrf_id = inp->def_vrf_id;
7123#ifdef SCTP_MVRF
7124	for (i = 0; i < inp->num_vrfs; i++) {
7125		if (vrf_id == inp->m_vrf_ids[i]) {
7126			fnd = 1;
7127			break;
7128		}
7129	}
7130	if (!fnd) {
7131		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7132		error = EINVAL;
7133		goto out_now;
7134	}
7135#endif
7136	/* We are GOOD to go */
7137	stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, p);
7138	if (stcb == NULL) {
7139		/* Gak! no memory */
7140		goto out_now;
7141	}
7142	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
7143		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
7144		/* Set the connected flag so we can queue data */
7145		soisconnecting(so);
7146	}
7147	SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
7148	(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
7149
7150	/* initialize authentication parameters for the assoc */
7151	sctp_initialize_auth_params(inp, stcb);
7152
7153	sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
7154	SCTP_TCB_UNLOCK(stcb);
7155 out_now:
7156	if (create_lock_on) {
7157		SCTP_ASOC_CREATE_UNLOCK(inp);
7158	}
7159
7160	SCTP_INP_DECR_REF(inp);
7161	return (error);
7162}
7163#endif
7164int
7165#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
7166#if __FreeBSD_version >= 700000
7167sctp_listen(struct socket *so, int backlog, struct thread *p)
7168#else
7169sctp_listen(struct socket *so, struct thread *p)
7170#endif
7171#elif defined(__Windows__)
7172sctp_listen(struct socket *so, int backlog, PKTHREAD p)
7173#elif defined(__Userspace__)
7174sctp_listen(struct socket *so, int backlog, struct proc *p)
7175#else
7176sctp_listen(struct socket *so, struct proc *p)
7177#endif
7178{
7179	/*
7180	 * Note this module depends on the protocol processing being called
7181	 * AFTER any socket level flags and backlog are applied to the
7182	 * socket. The traditional way that the socket flags are applied is
7183	 * AFTER protocol processing. We have made a change to the
7184	 * sys/kern/uipc_socket.c module to reverse this but this MUST be in
7185	 * place if the socket API for SCTP is to work properly.
7186	 */
7187
7188	int error = 0;
7189	struct sctp_inpcb *inp;
7190
7191	inp = (struct sctp_inpcb *)so->so_pcb;
7192	if (inp == NULL) {
7193		/* I made the same as TCP since we are not setup? */
7194		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7195		return (ECONNRESET);
7196	}
7197	if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) {
7198		/* See if we have a listener */
7199		struct sctp_inpcb *tinp;
7200		union sctp_sockstore store, *sp;
7201
7202		sp = &store;
7203		if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
7204			/* not bound all */
7205			struct sctp_laddr *laddr;
7206
7207			LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
7208				memcpy(&store, &laddr->ifa->address, sizeof(store));
7209				switch (sp->sa.sa_family) {
7210#ifdef INET
7211				case AF_INET:
7212					sp->sin.sin_port = inp->sctp_lport;
7213					break;
7214#endif
7215#ifdef INET6
7216				case AF_INET6:
7217					sp->sin6.sin6_port = inp->sctp_lport;
7218					break;
7219#endif
7220#if defined(__Userspace__)
7221				case AF_CONN:
7222					sp->sconn.sconn_port = inp->sctp_lport;
7223					break;
7224#endif
7225				default:
7226					break;
7227				}
7228				tinp = sctp_pcb_findep(&sp->sa, 0, 0, inp->def_vrf_id);
7229				if (tinp && (tinp != inp) &&
7230				    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
7231				    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
7232				    (tinp->sctp_socket->so_qlimit)) {
7233					/* we have a listener already and its not this inp. */
7234					SCTP_INP_DECR_REF(tinp);
7235					return (EADDRINUSE);
7236				} else if (tinp) {
7237					SCTP_INP_DECR_REF(tinp);
7238				}
7239			}
7240		} else {
7241			/* Setup a local addr bound all */
7242			memset(&store, 0, sizeof(store));
7243			switch (sp->sa.sa_family) {
7244#ifdef INET
7245			case AF_INET:
7246				store.sin.sin_port = inp->sctp_lport;
7247				break;
7248#endif
7249#ifdef INET6
7250			case AF_INET6:
7251				sp->sin6.sin6_port = inp->sctp_lport;
7252				break;
7253#endif
7254#if defined(__Userspace__)
7255			case AF_CONN:
7256				sp->sconn.sconn_port = inp->sctp_lport;
7257				break;
7258#endif
7259			default:
7260				break;
7261			}
7262#ifdef INET6
7263			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
7264				store.sa.sa_family = AF_INET6;
7265#ifdef HAVE_SA_LEN
7266				store.sa.sa_len = sizeof(struct sockaddr_in6);
7267#endif
7268			}
7269#endif
7270#ifdef INET
7271			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
7272				store.sa.sa_family = AF_INET;
7273#ifdef HAVE_SA_LEN
7274				store.sa.sa_len = sizeof(struct sockaddr_in);
7275#endif
7276			}
7277#endif
7278			tinp = sctp_pcb_findep(&sp->sa, 0, 0, inp->def_vrf_id);
7279			if (tinp && (tinp != inp) &&
7280			    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
7281			    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
7282			    (tinp->sctp_socket->so_qlimit)) {
7283				/* we have a listener already and its not this inp. */
7284				SCTP_INP_DECR_REF(tinp);
7285				return (EADDRINUSE);
7286			} else if (tinp) {
7287				SCTP_INP_DECR_REF(inp);
7288			}
7289		}
7290	}
7291	SCTP_INP_RLOCK(inp);
7292#ifdef SCTP_LOCK_LOGGING
7293	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) {
7294		sctp_log_lock(inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_SOCK);
7295	}
7296#endif
7297	SOCK_LOCK(so);
7298#if (defined(__FreeBSD__) && __FreeBSD_version > 500000) || defined(__Userspace__)
7299	error = solisten_proto_check(so);
7300	if (error) {
7301		SOCK_UNLOCK(so);
7302		SCTP_INP_RUNLOCK(inp);
7303		return (error);
7304	}
7305#endif
7306	if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) &&
7307	    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
7308		/* The unlucky case
7309		 * - We are in the tcp pool with this guy.
7310		 * - Someone else is in the main inp slot.
7311		 * - We must move this guy (the listener) to the main slot
7312		 * - We must then move the guy that was listener to the TCP Pool.
7313		 */
7314		if (sctp_swap_inpcb_for_listen(inp)) {
7315			goto in_use;
7316		}
7317	}
7318
7319	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
7320	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
7321		/* We are already connected AND the TCP model */
7322	in_use:
7323		SCTP_INP_RUNLOCK(inp);
7324		SOCK_UNLOCK(so);
7325		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
7326		return (EADDRINUSE);
7327	}
7328	SCTP_INP_RUNLOCK(inp);
7329	if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
7330		/* We must do a bind. */
7331		SOCK_UNLOCK(so);
7332		if ((error = sctp_inpcb_bind(so, NULL, NULL, p))) {
7333			/* bind error, probably perm */
7334			return (error);
7335		}
7336		SOCK_LOCK(so);
7337	}
7338#if (defined(__FreeBSD__) && __FreeBSD_version > 500000) || defined(__Windows__) || defined(__Userspace__)
7339#if __FreeBSD_version >= 700000 || defined(__Windows__) || defined(__Userspace__)
7340	/* It appears for 7.0 and on, we must always call this. */
7341	solisten_proto(so, backlog);
7342#else
7343	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) == 0) {
7344		solisten_proto(so);
7345	}
7346#endif
7347#endif
7348	if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
7349		/* remove the ACCEPTCONN flag for one-to-many sockets */
7350#if defined(__Userspace__)
7351		so->so_options &= ~SCTP_SO_ACCEPTCONN;
7352#else
7353		so->so_options &= ~SO_ACCEPTCONN;
7354#endif
7355	}
7356
7357#if __FreeBSD_version >= 700000 || defined(__Windows__) || defined(__Userspace__)
7358	if (backlog == 0) {
7359		/* turning off listen */
7360#if defined(__Userspace__)
7361		so->so_options &= ~SCTP_SO_ACCEPTCONN;
7362#else
7363		so->so_options &= ~SO_ACCEPTCONN;
7364#endif
7365	}
7366#endif
7367	SOCK_UNLOCK(so);
7368	return (error);
7369}
7370
7371static int sctp_defered_wakeup_cnt = 0;
7372
7373int
7374#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
7375sctp_accept(struct socket *so, struct sockaddr **addr)
7376{
7377#elif defined(__Panda__)
7378sctp_accept(struct socket *so, struct sockaddr *addr, int *namelen,
7379	    void *accept_info, int *accept_info_len)
7380{
7381#else
7382sctp_accept(struct socket *so, struct mbuf *nam)
7383{
7384	struct sockaddr *addr = mtod(nam, struct sockaddr *);
7385#endif
7386	struct sctp_tcb *stcb;
7387	struct sctp_inpcb *inp;
7388	union sctp_sockstore store;
7389#ifdef INET6
7390#ifdef SCTP_KAME
7391	int error;
7392#endif /* SCTP_KAME */
7393#endif
7394	inp = (struct sctp_inpcb *)so->so_pcb;
7395
7396	if (inp == NULL) {
7397		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7398		return (ECONNRESET);
7399	}
7400	SCTP_INP_RLOCK(inp);
7401	if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
7402		SCTP_INP_RUNLOCK(inp);
7403		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
7404		return (EOPNOTSUPP);
7405	}
7406	if (so->so_state & SS_ISDISCONNECTED) {
7407		SCTP_INP_RUNLOCK(inp);
7408		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ECONNABORTED);
7409		return (ECONNABORTED);
7410	}
7411	stcb = LIST_FIRST(&inp->sctp_asoc_list);
7412	if (stcb == NULL) {
7413		SCTP_INP_RUNLOCK(inp);
7414		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7415		return (ECONNRESET);
7416	}
7417	SCTP_TCB_LOCK(stcb);
7418	SCTP_INP_RUNLOCK(inp);
7419	store = stcb->asoc.primary_destination->ro._l_addr;
7420	stcb->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE;
7421	SCTP_TCB_UNLOCK(stcb);
7422	switch (store.sa.sa_family) {
7423#ifdef INET
7424	case AF_INET:
7425	{
7426		struct sockaddr_in *sin;
7427
7428#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
7429		SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
7430		if (sin == NULL)
7431			return (ENOMEM);
7432#else
7433		sin = (struct sockaddr_in *)addr;
7434		bzero((caddr_t)sin, sizeof(*sin));
7435#endif
7436		sin->sin_family = AF_INET;
7437#ifdef HAVE_SIN_LEN
7438		sin->sin_len = sizeof(*sin);
7439#endif
7440		sin->sin_port = store.sin.sin_port;
7441		sin->sin_addr = store.sin.sin_addr;
7442#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
7443		*addr = (struct sockaddr *)sin;
7444#elif !defined(__Panda__)
7445		SCTP_BUF_LEN(nam) = sizeof(*sin);
7446#endif
7447		break;
7448	}
7449#endif
7450#ifdef INET6
7451	case AF_INET6:
7452	{
7453		struct sockaddr_in6 *sin6;
7454
7455#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
7456		SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
7457		if (sin6 == NULL)
7458			return (ENOMEM);
7459#else
7460		sin6 = (struct sockaddr_in6 *)addr;
7461		bzero((caddr_t)sin6, sizeof(*sin6));
7462#endif
7463		sin6->sin6_family = AF_INET6;
7464#ifdef HAVE_SIN6_LEN
7465		sin6->sin6_len = sizeof(*sin6);
7466#endif
7467		sin6->sin6_port = store.sin6.sin6_port;
7468		sin6->sin6_addr = store.sin6.sin6_addr;
7469#if defined(SCTP_EMBEDDED_V6_SCOPE)
7470#ifdef SCTP_KAME
7471		if ((error = sa6_recoverscope(sin6)) != 0) {
7472			SCTP_FREE_SONAME(sin6);
7473			return (error);
7474		}
7475#else
7476		if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
7477			/*
7478			 * sin6->sin6_scope_id =
7479			 * ntohs(sin6->sin6_addr.s6_addr16[1]);
7480			 */
7481			in6_recoverscope(sin6, &sin6->sin6_addr, NULL);	/* skip ifp check */
7482		else
7483			sin6->sin6_scope_id = 0;	/* XXX */
7484#endif /* SCTP_KAME */
7485#endif /* SCTP_EMBEDDED_V6_SCOPE */
7486#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
7487		*addr = (struct sockaddr *)sin6;
7488#elif !defined(__Panda__)
7489		SCTP_BUF_LEN(nam) = sizeof(*sin6);
7490#endif
7491		break;
7492	}
7493#endif
7494#if defined(__Userspace__)
7495	case AF_CONN:
7496	{
7497		struct sockaddr_conn *sconn;
7498
7499		SCTP_MALLOC_SONAME(sconn, struct sockaddr_conn *, sizeof(struct sockaddr_conn));
7500		if (sconn == NULL) {
7501			return (ENOMEM);
7502		}
7503		sconn->sconn_family = AF_CONN;
7504#ifdef HAVE_SCONN_LEN
7505		sconn->sconn_len = sizeof(struct sockaddr_conn);
7506#endif
7507		sconn->sconn_port = store.sconn.sconn_port;
7508		sconn->sconn_addr = store.sconn.sconn_addr;
7509		*addr = (struct sockaddr *)sconn;
7510		break;
7511	}
7512#endif
7513	default:
7514		/* TSNH */
7515		break;
7516	}
7517	/* Wake any delayed sleep action */
7518	if (inp->sctp_flags & SCTP_PCB_FLAGS_DONT_WAKE) {
7519		SCTP_INP_WLOCK(inp);
7520		inp->sctp_flags &= ~SCTP_PCB_FLAGS_DONT_WAKE;
7521		if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEOUTPUT) {
7522			inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEOUTPUT;
7523			SCTP_INP_WUNLOCK(inp);
7524			SOCKBUF_LOCK(&inp->sctp_socket->so_snd);
7525			if (sowriteable(inp->sctp_socket)) {
7526#if defined(__Userspace__)
7527                            /*__Userspace__ calling sowwakup_locked because of SOCKBUF_LOCK above. */
7528#endif
7529#if defined(__FreeBSD__) || defined(__Windows__) || defined(__Userspace__)
7530				sowwakeup_locked(inp->sctp_socket);
7531#else
7532#if defined(__APPLE__)
7533				/* socket is locked */
7534#endif
7535				sowwakeup(inp->sctp_socket);
7536#endif
7537			} else {
7538				SOCKBUF_UNLOCK(&inp->sctp_socket->so_snd);
7539			}
7540			SCTP_INP_WLOCK(inp);
7541		}
7542		if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEINPUT) {
7543			inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEINPUT;
7544			SCTP_INP_WUNLOCK(inp);
7545			SOCKBUF_LOCK(&inp->sctp_socket->so_rcv);
7546			if (soreadable(inp->sctp_socket)) {
7547				sctp_defered_wakeup_cnt++;
7548#if defined(__Userspace__)
7549                                /*__Userspace__ calling sorwakup_locked because of SOCKBUF_LOCK above */
7550#endif
7551#if defined(__FreeBSD__) || defined(__Windows__) || defined(__Userspace__)
7552				sorwakeup_locked(inp->sctp_socket);
7553#else
7554#if defined(__APPLE__)
7555				/* socket is locked */
7556#endif
7557				sorwakeup(inp->sctp_socket);
7558#endif
7559			} else {
7560				SOCKBUF_UNLOCK(&inp->sctp_socket->so_rcv);
7561			}
7562			SCTP_INP_WLOCK(inp);
7563		}
7564		SCTP_INP_WUNLOCK(inp);
7565	}
7566	if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
7567		SCTP_TCB_LOCK(stcb);
7568		sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_7);
7569	}
7570	return (0);
7571}
7572
7573#ifdef INET
7574int
7575#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
7576sctp_ingetaddr(struct socket *so, struct sockaddr **addr)
7577{
7578	struct sockaddr_in *sin;
7579#elif defined(__Panda__)
7580sctp_ingetaddr(struct socket *so, struct sockaddr *addr)
7581{
7582	struct sockaddr_in *sin = (struct sockaddr_in *)addr;
7583#else
7584sctp_ingetaddr(struct socket *so, struct mbuf *nam)
7585{
7586	struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
7587#endif
7588	uint32_t vrf_id;
7589	struct sctp_inpcb *inp;
7590	struct sctp_ifa *sctp_ifa;
7591
7592	/*
7593	 * Do the malloc first in case it blocks.
7594	 */
7595#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
7596	SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
7597	if (sin == NULL)
7598		return (ENOMEM);
7599#elif defined(__Panda__)
7600	bzero(sin, sizeof(*sin));
7601#else
7602	SCTP_BUF_LEN(nam) = sizeof(*sin);
7603	memset(sin, 0, sizeof(*sin));
7604#endif
7605	sin->sin_family = AF_INET;
7606#ifdef HAVE_SIN_LEN
7607	sin->sin_len = sizeof(*sin);
7608#endif
7609	inp = (struct sctp_inpcb *)so->so_pcb;
7610	if (!inp) {
7611#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
7612		SCTP_FREE_SONAME(sin);
7613#endif
7614		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7615		return (ECONNRESET);
7616	}
7617	SCTP_INP_RLOCK(inp);
7618	sin->sin_port = inp->sctp_lport;
7619	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
7620		if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
7621			struct sctp_tcb *stcb;
7622			struct sockaddr_in *sin_a;
7623			struct sctp_nets *net;
7624			int fnd;
7625
7626			stcb = LIST_FIRST(&inp->sctp_asoc_list);
7627			if (stcb == NULL) {
7628				goto notConn;
7629			}
7630			fnd = 0;
7631			sin_a = NULL;
7632			SCTP_TCB_LOCK(stcb);
7633			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
7634				sin_a = (struct sockaddr_in *)&net->ro._l_addr;
7635				if (sin_a == NULL)
7636					/* this will make coverity happy */
7637					continue;
7638
7639				if (sin_a->sin_family == AF_INET) {
7640					fnd = 1;
7641					break;
7642				}
7643			}
7644			if ((!fnd) || (sin_a == NULL)) {
7645				/* punt */
7646				SCTP_TCB_UNLOCK(stcb);
7647				goto notConn;
7648			}
7649
7650			vrf_id = inp->def_vrf_id;
7651			sctp_ifa = sctp_source_address_selection(inp,
7652								 stcb,
7653								 (sctp_route_t *)&net->ro,
7654								 net, 0, vrf_id);
7655			if (sctp_ifa) {
7656				sin->sin_addr = sctp_ifa->address.sin.sin_addr;
7657				sctp_free_ifa(sctp_ifa);
7658			}
7659			SCTP_TCB_UNLOCK(stcb);
7660		} else {
7661			/* For the bound all case you get back 0 */
7662	notConn:
7663			sin->sin_addr.s_addr = 0;
7664		}
7665
7666	} else {
7667		/* Take the first IPv4 address in the list */
7668		struct sctp_laddr *laddr;
7669		int fnd = 0;
7670
7671		LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
7672			if (laddr->ifa->address.sa.sa_family == AF_INET) {
7673				struct sockaddr_in *sin_a;
7674
7675				sin_a = (struct sockaddr_in *)&laddr->ifa->address.sa;
7676				sin->sin_addr = sin_a->sin_addr;
7677				fnd = 1;
7678				break;
7679			}
7680		}
7681		if (!fnd) {
7682#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
7683			SCTP_FREE_SONAME(sin);
7684#endif
7685			SCTP_INP_RUNLOCK(inp);
7686			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
7687			return (ENOENT);
7688		}
7689	}
7690	SCTP_INP_RUNLOCK(inp);
7691#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
7692	(*addr) = (struct sockaddr *)sin;
7693#endif
7694	return (0);
7695}
7696
7697int
7698#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
7699sctp_peeraddr(struct socket *so, struct sockaddr **addr)
7700{
7701	struct sockaddr_in *sin;
7702#elif defined(__Panda__)
7703sctp_peeraddr(struct socket *so, struct sockaddr *addr)
7704{
7705	struct sockaddr_in *sin = (struct sockaddr_in *)addr;
7706#else
7707sctp_peeraddr(struct socket *so, struct mbuf *nam)
7708{
7709	struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
7710
7711#endif
7712	int fnd;
7713	struct sockaddr_in *sin_a;
7714	struct sctp_inpcb *inp;
7715	struct sctp_tcb *stcb;
7716	struct sctp_nets *net;
7717
7718	/* Do the malloc first in case it blocks. */
7719#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
7720	SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
7721	if (sin == NULL)
7722		return (ENOMEM);
7723#elif defined(__Panda__)
7724	memset(sin, 0, sizeof(*sin));
7725#else
7726	SCTP_BUF_LEN(nam) = sizeof(*sin);
7727	memset(sin, 0, sizeof(*sin));
7728#endif
7729	sin->sin_family = AF_INET;
7730#ifdef HAVE_SIN_LEN
7731	sin->sin_len = sizeof(*sin);
7732#endif
7733
7734	inp = (struct sctp_inpcb *)so->so_pcb;
7735	if ((inp == NULL) ||
7736	    ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
7737		/* UDP type and listeners will drop out here */
7738#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
7739		SCTP_FREE_SONAME(sin);
7740#endif
7741		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
7742		return (ENOTCONN);
7743	}
7744	SCTP_INP_RLOCK(inp);
7745	stcb = LIST_FIRST(&inp->sctp_asoc_list);
7746	if (stcb) {
7747		SCTP_TCB_LOCK(stcb);
7748	}
7749	SCTP_INP_RUNLOCK(inp);
7750	if (stcb == NULL) {
7751#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
7752		SCTP_FREE_SONAME(sin);
7753#endif
7754		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7755		return (ECONNRESET);
7756	}
7757	fnd = 0;
7758	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
7759		sin_a = (struct sockaddr_in *)&net->ro._l_addr;
7760		if (sin_a->sin_family == AF_INET) {
7761			fnd = 1;
7762			sin->sin_port = stcb->rport;
7763			sin->sin_addr = sin_a->sin_addr;
7764			break;
7765		}
7766	}
7767	SCTP_TCB_UNLOCK(stcb);
7768	if (!fnd) {
7769		/* No IPv4 address */
7770#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
7771		SCTP_FREE_SONAME(sin);
7772#endif
7773		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
7774		return (ENOENT);
7775	}
7776#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
7777	(*addr) = (struct sockaddr *)sin;
7778#endif
7779	return (0);
7780}
7781
7782#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
7783struct pr_usrreqs sctp_usrreqs = {
7784#if defined(__FreeBSD__)
7785	.pru_abort = sctp_abort,
7786	.pru_accept = sctp_accept,
7787	.pru_attach = sctp_attach,
7788	.pru_bind = sctp_bind,
7789	.pru_connect = sctp_connect,
7790	.pru_control = in_control,
7791#if __FreeBSD_version >= 690000
7792	.pru_close = sctp_close,
7793	.pru_detach = sctp_close,
7794	.pru_sopoll = sopoll_generic,
7795	.pru_flush = sctp_flush,
7796#else
7797	.pru_detach = sctp_detach,
7798	.pru_sopoll = sopoll,
7799#endif
7800	.pru_disconnect = sctp_disconnect,
7801	.pru_listen = sctp_listen,
7802	.pru_peeraddr = sctp_peeraddr,
7803	.pru_send = sctp_sendm,
7804	.pru_shutdown = sctp_shutdown,
7805	.pru_sockaddr = sctp_ingetaddr,
7806	.pru_sosend = sctp_sosend,
7807	.pru_soreceive = sctp_soreceive
7808#elif defined(__APPLE__)
7809	.pru_abort = sctp_abort,
7810	.pru_accept = sctp_accept,
7811	.pru_attach = sctp_attach,
7812	.pru_bind = sctp_bind,
7813	.pru_connect = sctp_connect,
7814	.pru_connect2 = pru_connect2_notsupp,
7815	.pru_control = in_control,
7816	.pru_detach = sctp_detach,
7817	.pru_disconnect = sctp_disconnect,
7818	.pru_listen = sctp_listen,
7819	.pru_peeraddr = sctp_peeraddr,
7820	.pru_rcvd = NULL,
7821	.pru_rcvoob = pru_rcvoob_notsupp,
7822	.pru_send = sctp_sendm,
7823	.pru_sense = pru_sense_null,
7824	.pru_shutdown = sctp_shutdown,
7825	.pru_sockaddr = sctp_ingetaddr,
7826	.pru_sosend = sctp_sosend,
7827	.pru_soreceive = sctp_soreceive,
7828	.pru_sopoll = sopoll
7829#elif defined(__Windows__)
7830	sctp_abort,
7831	sctp_accept,
7832	sctp_attach,
7833	sctp_bind,
7834	sctp_connect,
7835	pru_connect2_notsupp,
7836	NULL,
7837	NULL,
7838	sctp_disconnect,
7839	sctp_listen,
7840	sctp_peeraddr,
7841	NULL,
7842	pru_rcvoob_notsupp,
7843	NULL,
7844	pru_sense_null,
7845	sctp_shutdown,
7846	sctp_flush,
7847	sctp_ingetaddr,
7848	sctp_sosend,
7849	sctp_soreceive,
7850	sopoll_generic,
7851	NULL,
7852	sctp_close
7853#endif
7854};
7855#elif !defined(__Panda__) && !defined(__Userspace__)
7856int
7857sctp_usrreq(so, req, m, nam, control)
7858	struct socket *so;
7859	int req;
7860	struct mbuf *m, *nam, *control;
7861{
7862	struct proc *p = curproc;
7863	uint32_t vrf_id;
7864	struct sctp_vrf *vrf;
7865	int error;
7866	int family;
7867	struct sctp_inpcb *inp = (struct sctp_inpcb *)so->so_pcb;
7868
7869	error = 0;
7870	family = so->so_proto->pr_domain->dom_family;
7871	if (req == PRU_CONTROL) {
7872		switch (family) {
7873		case PF_INET:
7874			error = in_control(so, (long)m, (caddr_t)nam,
7875			    (struct ifnet *)control);
7876			break;
7877#ifdef INET6
7878		case PF_INET6:
7879			error = in6_control(so, (long)m, (caddr_t)nam,
7880			    (struct ifnet *)control, p);
7881			break;
7882#endif
7883		default:
7884			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
7885			error = EAFNOSUPPORT;
7886		}
7887		return (error);
7888	}
7889	switch (req) {
7890	case PRU_ATTACH:
7891		error = sctp_attach(so, family, p);
7892		break;
7893	case PRU_DETACH:
7894		error = sctp_detach(so);
7895		break;
7896	case PRU_BIND:
7897		if (nam == NULL) {
7898			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7899			return (EINVAL);
7900		}
7901		error = sctp_bind(so, nam, p);
7902		break;
7903	case PRU_LISTEN:
7904		error = sctp_listen(so, p);
7905		break;
7906	case PRU_CONNECT:
7907		if (nam == NULL) {
7908			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7909			return (EINVAL);
7910		}
7911		error = sctp_connect(so, nam, p);
7912		break;
7913	case PRU_DISCONNECT:
7914		error = sctp_disconnect(so);
7915		break;
7916	case PRU_ACCEPT:
7917		if (nam == NULL) {
7918			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7919			return (EINVAL);
7920		}
7921		error = sctp_accept(so, nam);
7922		break;
7923	case PRU_SHUTDOWN:
7924		error = sctp_shutdown(so);
7925		break;
7926
7927	case PRU_RCVD:
7928		/*
7929		 * For Open and Net BSD, this is real ugly. The mbuf *nam
7930		 * that is passed (by soreceive()) is the int flags c ast as
7931		 * a (mbuf *) yuck!
7932		 */
7933		break;
7934
7935	case PRU_SEND:
7936		/* Flags are ignored */
7937		{
7938			struct sockaddr *addr;
7939
7940			if (nam == NULL)
7941				addr = NULL;
7942			else
7943				addr = mtod(nam, struct sockaddr *);
7944
7945			error = sctp_sendm(so, 0, m, addr, control, p);
7946		}
7947		break;
7948	case PRU_ABORT:
7949		error = sctp_abort(so);
7950		break;
7951
7952	case PRU_SENSE:
7953		error = 0;
7954		break;
7955	case PRU_RCVOOB:
7956		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
7957		error = EAFNOSUPPORT;
7958		break;
7959	case PRU_SENDOOB:
7960		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
7961		error = EAFNOSUPPORT;
7962		break;
7963	case PRU_PEERADDR:
7964		error = sctp_peeraddr(so, nam);
7965		break;
7966	case PRU_SOCKADDR:
7967		error = sctp_ingetaddr(so, nam);
7968		break;
7969	case PRU_SLOWTIMO:
7970		error = 0;
7971		break;
7972	default:
7973		break;
7974	}
7975	return (error);
7976}
7977
7978#endif
7979#endif
7980
7981#if defined(__Userspace__)
7982int
7983register_recv_cb(struct socket *so,
7984                 int (*receive_cb)(struct socket *sock, union sctp_sockstore addr, void *data,
7985                 size_t datalen, struct sctp_rcvinfo, int flags, void *ulp_info))
7986{
7987	struct sctp_inpcb *inp;
7988
7989	inp = (struct sctp_inpcb *) so->so_pcb;
7990	if (inp == NULL) {
7991		return (0);
7992	}
7993	SCTP_INP_WLOCK(inp);
7994	inp->recv_callback = receive_cb;
7995	SCTP_INP_WUNLOCK(inp);
7996	return (1);
7997}
7998
7999int
8000register_send_cb(struct socket *so, uint32_t sb_threshold, int (*send_cb)(struct socket *sock, uint32_t sb_free))
8001{
8002	struct sctp_inpcb *inp;
8003
8004	inp = (struct sctp_inpcb *) so->so_pcb;
8005	if (inp == NULL) {
8006		return (0);
8007	}
8008	SCTP_INP_WLOCK(inp);
8009	inp->send_callback = send_cb;
8010	inp->send_sb_threshold = sb_threshold;
8011	SCTP_INP_WUNLOCK(inp);
8012	/* FIXME change to current amount free. This will be the full buffer
8013	 * the first time this is registered but it could be only a portion
8014	 * of the send buffer if this is called a second time e.g. if the
8015	 * threshold changes.
8016	 */
8017	return (1);
8018}
8019
8020int
8021register_ulp_info (struct socket *so, void *ulp_info)
8022{
8023	struct sctp_inpcb *inp;
8024
8025	inp = (struct sctp_inpcb *) so->so_pcb;
8026	if (inp == NULL) {
8027		return (0);
8028	}
8029	SCTP_INP_WLOCK(inp);
8030	inp->ulp_info = ulp_info;
8031	SCTP_INP_WUNLOCK(inp);
8032	return (1);
8033}
8034#endif
8035