sctp_usrreq.c revision 228391
1/*-
2 * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved.
3 * Copyright (c) 2008-2011, by Randall Stewart. All rights reserved.
4 * Copyright (c) 2008-2011, 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/* $KAME: sctp_usrreq.c,v 1.48 2005/03/07 23:26:08 itojun Exp $	 */
34
35#include <sys/cdefs.h>
36__FBSDID("$FreeBSD: head/sys/netinet/sctp_usrreq.c 228391 2011-12-10 10:52:54Z tuexen $");
37#include <netinet/sctp_os.h>
38#include <sys/proc.h>
39#include <netinet/sctp_pcb.h>
40#include <netinet/sctp_header.h>
41#include <netinet/sctp_var.h>
42#if defined(INET6)
43#endif
44#include <netinet/sctp_sysctl.h>
45#include <netinet/sctp_output.h>
46#include <netinet/sctp_uio.h>
47#include <netinet/sctp_asconf.h>
48#include <netinet/sctputil.h>
49#include <netinet/sctp_indata.h>
50#include <netinet/sctp_timer.h>
51#include <netinet/sctp_auth.h>
52#include <netinet/sctp_bsd_addr.h>
53#include <netinet/udp.h>
54
55
56
57extern struct sctp_cc_functions sctp_cc_functions[];
58extern struct sctp_ss_functions sctp_ss_functions[];
59
60void
61sctp_init(void)
62{
63	u_long sb_max_adj;
64
65	/* Initialize and modify the sysctled variables */
66	sctp_init_sysctls();
67	if ((nmbclusters / 8) > SCTP_ASOC_MAX_CHUNKS_ON_QUEUE)
68		SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue) = (nmbclusters / 8);
69	/*
70	 * Allow a user to take no more than 1/2 the number of clusters or
71	 * the SB_MAX whichever is smaller for the send window.
72	 */
73	sb_max_adj = (u_long)((u_quad_t) (SB_MAX) * MCLBYTES / (MSIZE + MCLBYTES));
74	SCTP_BASE_SYSCTL(sctp_sendspace) = min(sb_max_adj,
75	    (((uint32_t) nmbclusters / 2) * SCTP_DEFAULT_MAXSEGMENT));
76	/*
77	 * Now for the recv window, should we take the same amount? or
78	 * should I do 1/2 the SB_MAX instead in the SB_MAX min above. For
79	 * now I will just copy.
80	 */
81	SCTP_BASE_SYSCTL(sctp_recvspace) = SCTP_BASE_SYSCTL(sctp_sendspace);
82
83	SCTP_BASE_VAR(first_time) = 0;
84	SCTP_BASE_VAR(sctp_pcb_initialized) = 0;
85	sctp_pcb_init();
86#if defined(SCTP_PACKET_LOGGING)
87	SCTP_BASE_VAR(packet_log_writers) = 0;
88	SCTP_BASE_VAR(packet_log_end) = 0;
89	bzero(&SCTP_BASE_VAR(packet_log_buffer), SCTP_PACKET_LOG_SIZE);
90#endif
91
92
93}
94
95void
96sctp_finish(void)
97{
98	sctp_pcb_finish();
99}
100
101
102
103void
104sctp_pathmtu_adjustment(struct sctp_inpcb *inp,
105    struct sctp_tcb *stcb,
106    struct sctp_nets *net,
107    uint16_t nxtsz)
108{
109	struct sctp_tmit_chunk *chk;
110	uint16_t overhead;
111
112	/* Adjust that too */
113	stcb->asoc.smallest_mtu = nxtsz;
114	/* now off to subtract IP_DF flag if needed */
115	overhead = IP_HDR_SIZE;
116	if (sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.peer_auth_chunks)) {
117		overhead += sctp_get_auth_chunk_len(stcb->asoc.peer_hmac_id);
118	}
119	TAILQ_FOREACH(chk, &stcb->asoc.send_queue, sctp_next) {
120		if ((chk->send_size + overhead) > nxtsz) {
121			chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
122		}
123	}
124	TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
125		if ((chk->send_size + overhead) > nxtsz) {
126			/*
127			 * For this guy we also mark for immediate resend
128			 * since we sent to big of chunk
129			 */
130			chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
131			if (chk->sent < SCTP_DATAGRAM_RESEND) {
132				sctp_flight_size_decrease(chk);
133				sctp_total_flight_decrease(stcb, chk);
134			}
135			if (chk->sent != SCTP_DATAGRAM_RESEND) {
136				sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
137			}
138			chk->sent = SCTP_DATAGRAM_RESEND;
139			chk->rec.data.doing_fast_retransmit = 0;
140			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) {
141				sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_PMTU,
142				    chk->whoTo->flight_size,
143				    chk->book_size,
144				    (uintptr_t) chk->whoTo,
145				    chk->rec.data.TSN_seq);
146			}
147			/* Clear any time so NO RTT is being done */
148			chk->do_rtt = 0;
149		}
150	}
151}
152
153#ifdef INET
154static void
155sctp_notify_mbuf(struct sctp_inpcb *inp,
156    struct sctp_tcb *stcb,
157    struct sctp_nets *net,
158    struct ip *ip,
159    struct sctphdr *sh)
160{
161	struct icmp *icmph;
162	int totsz, tmr_stopped = 0;
163	uint16_t nxtsz;
164
165	/* protection */
166	if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
167	    (ip == NULL) || (sh == NULL)) {
168		if (stcb != NULL) {
169			SCTP_TCB_UNLOCK(stcb);
170		}
171		return;
172	}
173	/* First job is to verify the vtag matches what I would send */
174	if (ntohl(sh->v_tag) != (stcb->asoc.peer_vtag)) {
175		SCTP_TCB_UNLOCK(stcb);
176		return;
177	}
178	icmph = (struct icmp *)((caddr_t)ip - (sizeof(struct icmp) -
179	    sizeof(struct ip)));
180	if (icmph->icmp_type != ICMP_UNREACH) {
181		/* We only care about unreachable */
182		SCTP_TCB_UNLOCK(stcb);
183		return;
184	}
185	if (icmph->icmp_code != ICMP_UNREACH_NEEDFRAG) {
186		/* not a unreachable message due to frag. */
187		SCTP_TCB_UNLOCK(stcb);
188		return;
189	}
190	totsz = ip->ip_len;
191
192	nxtsz = ntohs(icmph->icmp_nextmtu);
193	if (nxtsz == 0) {
194		/*
195		 * old type router that does not tell us what the next size
196		 * mtu is. Rats we will have to guess (in a educated fashion
197		 * of course)
198		 */
199		nxtsz = sctp_get_prev_mtu(totsz);
200	}
201	/* Stop any PMTU timer */
202	if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
203		tmr_stopped = 1;
204		sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
205		    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_1);
206	}
207	/* Adjust destination size limit */
208	if (net->mtu > nxtsz) {
209		net->mtu = nxtsz;
210		if (net->port) {
211			net->mtu -= sizeof(struct udphdr);
212		}
213	}
214	/* now what about the ep? */
215	if (stcb->asoc.smallest_mtu > nxtsz) {
216		sctp_pathmtu_adjustment(inp, stcb, net, nxtsz);
217	}
218	if (tmr_stopped)
219		sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
220
221	SCTP_TCB_UNLOCK(stcb);
222}
223
224#endif
225
226void
227sctp_notify(struct sctp_inpcb *inp,
228    struct ip *ip,
229    struct sctphdr *sh,
230    struct sockaddr *to,
231    struct sctp_tcb *stcb,
232    struct sctp_nets *net)
233{
234#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
235	struct socket *so;
236
237#endif
238	/* protection */
239	int reason;
240	struct icmp *icmph;
241
242
243	if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
244	    (sh == NULL) || (to == NULL)) {
245		if (stcb)
246			SCTP_TCB_UNLOCK(stcb);
247		return;
248	}
249	/* First job is to verify the vtag matches what I would send */
250	if (ntohl(sh->v_tag) != (stcb->asoc.peer_vtag)) {
251		SCTP_TCB_UNLOCK(stcb);
252		return;
253	}
254	icmph = (struct icmp *)((caddr_t)ip - (sizeof(struct icmp) -
255	    sizeof(struct ip)));
256	if (icmph->icmp_type != ICMP_UNREACH) {
257		/* We only care about unreachable */
258		SCTP_TCB_UNLOCK(stcb);
259		return;
260	}
261	if ((icmph->icmp_code == ICMP_UNREACH_NET) ||
262	    (icmph->icmp_code == ICMP_UNREACH_HOST) ||
263	    (icmph->icmp_code == ICMP_UNREACH_NET_UNKNOWN) ||
264	    (icmph->icmp_code == ICMP_UNREACH_HOST_UNKNOWN) ||
265	    (icmph->icmp_code == ICMP_UNREACH_ISOLATED) ||
266	    (icmph->icmp_code == ICMP_UNREACH_NET_PROHIB) ||
267	    (icmph->icmp_code == ICMP_UNREACH_HOST_PROHIB) ||
268	    (icmph->icmp_code == ICMP_UNREACH_FILTER_PROHIB)) {
269
270		/*
271		 * Hmm reachablity problems we must examine closely. If its
272		 * not reachable, we may have lost a network. Or if there is
273		 * NO protocol at the other end named SCTP. well we consider
274		 * it a OOTB abort.
275		 */
276		if (net->dest_state & SCTP_ADDR_REACHABLE) {
277			/* Ok that destination is NOT reachable */
278			net->dest_state &= ~SCTP_ADDR_REACHABLE;
279			net->dest_state &= ~SCTP_ADDR_PF;
280			sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
281			    stcb, SCTP_FAILED_THRESHOLD,
282			    (void *)net, SCTP_SO_NOT_LOCKED);
283		}
284		SCTP_TCB_UNLOCK(stcb);
285	} else if ((icmph->icmp_code == ICMP_UNREACH_PROTOCOL) ||
286	    (icmph->icmp_code == ICMP_UNREACH_PORT)) {
287		/*
288		 * Here the peer is either playing tricks on us, including
289		 * an address that belongs to someone who does not support
290		 * SCTP OR was a userland implementation that shutdown and
291		 * now is dead. In either case treat it like a OOTB abort
292		 * with no TCB
293		 */
294		reason = SCTP_PEER_FAULTY;
295		sctp_abort_notification(stcb, reason, SCTP_SO_NOT_LOCKED);
296#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
297		so = SCTP_INP_SO(inp);
298		atomic_add_int(&stcb->asoc.refcnt, 1);
299		SCTP_TCB_UNLOCK(stcb);
300		SCTP_SOCKET_LOCK(so, 1);
301		SCTP_TCB_LOCK(stcb);
302		atomic_subtract_int(&stcb->asoc.refcnt, 1);
303#endif
304		(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_2);
305#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
306		SCTP_SOCKET_UNLOCK(so, 1);
307		/* SCTP_TCB_UNLOCK(stcb); MT: I think this is not needed. */
308#endif
309		/* no need to unlock here, since the TCB is gone */
310	} else {
311		SCTP_TCB_UNLOCK(stcb);
312	}
313}
314
315#ifdef INET
316void
317sctp_ctlinput(cmd, sa, vip)
318	int cmd;
319	struct sockaddr *sa;
320	void *vip;
321{
322	struct ip *ip = vip;
323	struct sctphdr *sh;
324	uint32_t vrf_id;
325
326	/* FIX, for non-bsd is this right? */
327	vrf_id = SCTP_DEFAULT_VRFID;
328	if (sa->sa_family != AF_INET ||
329	    ((struct sockaddr_in *)sa)->sin_addr.s_addr == INADDR_ANY) {
330		return;
331	}
332	if (PRC_IS_REDIRECT(cmd)) {
333		ip = 0;
334	} else if ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0) {
335		return;
336	}
337	if (ip) {
338		struct sctp_inpcb *inp = NULL;
339		struct sctp_tcb *stcb = NULL;
340		struct sctp_nets *net = NULL;
341		struct sockaddr_in to, from;
342
343		sh = (struct sctphdr *)((caddr_t)ip + (ip->ip_hl << 2));
344		bzero(&to, sizeof(to));
345		bzero(&from, sizeof(from));
346		from.sin_family = to.sin_family = AF_INET;
347		from.sin_len = to.sin_len = sizeof(to);
348		from.sin_port = sh->src_port;
349		from.sin_addr = ip->ip_src;
350		to.sin_port = sh->dest_port;
351		to.sin_addr = ip->ip_dst;
352
353		/*
354		 * 'to' holds the dest of the packet that failed to be sent.
355		 * 'from' holds our local endpoint address. Thus we reverse
356		 * the to and the from in the lookup.
357		 */
358		stcb = sctp_findassociation_addr_sa((struct sockaddr *)&from,
359		    (struct sockaddr *)&to,
360		    &inp, &net, 1, vrf_id);
361		if (stcb != NULL && inp && (inp->sctp_socket != NULL)) {
362			if (cmd != PRC_MSGSIZE) {
363				sctp_notify(inp, ip, sh,
364				    (struct sockaddr *)&to, stcb,
365				    net);
366			} else {
367				/* handle possible ICMP size messages */
368				sctp_notify_mbuf(inp, stcb, net, ip, sh);
369			}
370		} else {
371			if ((stcb == NULL) && (inp != NULL)) {
372				/* reduce ref-count */
373				SCTP_INP_WLOCK(inp);
374				SCTP_INP_DECR_REF(inp);
375				SCTP_INP_WUNLOCK(inp);
376			}
377			if (stcb) {
378				SCTP_TCB_UNLOCK(stcb);
379			}
380		}
381	}
382	return;
383}
384
385#endif
386
387static int
388sctp_getcred(SYSCTL_HANDLER_ARGS)
389{
390	struct xucred xuc;
391	struct sockaddr_in addrs[2];
392	struct sctp_inpcb *inp;
393	struct sctp_nets *net;
394	struct sctp_tcb *stcb;
395	int error;
396	uint32_t vrf_id;
397
398	/* FIX, for non-bsd is this right? */
399	vrf_id = SCTP_DEFAULT_VRFID;
400
401	error = priv_check(req->td, PRIV_NETINET_GETCRED);
402
403	if (error)
404		return (error);
405
406	error = SYSCTL_IN(req, addrs, sizeof(addrs));
407	if (error)
408		return (error);
409
410	stcb = sctp_findassociation_addr_sa(sintosa(&addrs[0]),
411	    sintosa(&addrs[1]),
412	    &inp, &net, 1, vrf_id);
413	if (stcb == NULL || inp == NULL || inp->sctp_socket == NULL) {
414		if ((inp != NULL) && (stcb == NULL)) {
415			/* reduce ref-count */
416			SCTP_INP_WLOCK(inp);
417			SCTP_INP_DECR_REF(inp);
418			goto cred_can_cont;
419		}
420		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
421		error = ENOENT;
422		goto out;
423	}
424	SCTP_TCB_UNLOCK(stcb);
425	/*
426	 * We use the write lock here, only since in the error leg we need
427	 * it. If we used RLOCK, then we would have to
428	 * wlock/decr/unlock/rlock. Which in theory could create a hole.
429	 * Better to use higher wlock.
430	 */
431	SCTP_INP_WLOCK(inp);
432cred_can_cont:
433	error = cr_canseesocket(req->td->td_ucred, inp->sctp_socket);
434	if (error) {
435		SCTP_INP_WUNLOCK(inp);
436		goto out;
437	}
438	cru2x(inp->sctp_socket->so_cred, &xuc);
439	SCTP_INP_WUNLOCK(inp);
440	error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
441out:
442	return (error);
443}
444
445SYSCTL_PROC(_net_inet_sctp, OID_AUTO, getcred, CTLTYPE_OPAQUE | CTLFLAG_RW,
446    0, 0, sctp_getcred, "S,ucred", "Get the ucred of a SCTP connection");
447
448
449#ifdef INET
450static void
451sctp_abort(struct socket *so)
452{
453	struct sctp_inpcb *inp;
454	uint32_t flags;
455
456	inp = (struct sctp_inpcb *)so->so_pcb;
457	if (inp == 0) {
458		return;
459	}
460sctp_must_try_again:
461	flags = inp->sctp_flags;
462#ifdef SCTP_LOG_CLOSING
463	sctp_log_closing(inp, NULL, 17);
464#endif
465	if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
466	    (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
467#ifdef SCTP_LOG_CLOSING
468		sctp_log_closing(inp, NULL, 16);
469#endif
470		sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
471		    SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
472		SOCK_LOCK(so);
473		SCTP_SB_CLEAR(so->so_snd);
474		/*
475		 * same for the rcv ones, they are only here for the
476		 * accounting/select.
477		 */
478		SCTP_SB_CLEAR(so->so_rcv);
479
480		/* Now null out the reference, we are completely detached. */
481		so->so_pcb = NULL;
482		SOCK_UNLOCK(so);
483	} else {
484		flags = inp->sctp_flags;
485		if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
486			goto sctp_must_try_again;
487		}
488	}
489	return;
490}
491
492static int
493sctp_attach(struct socket *so, int proto, struct thread *p)
494{
495	struct sctp_inpcb *inp;
496	struct inpcb *ip_inp;
497	int error;
498	uint32_t vrf_id = SCTP_DEFAULT_VRFID;
499
500#ifdef IPSEC
501	uint32_t flags;
502
503#endif
504
505	inp = (struct sctp_inpcb *)so->so_pcb;
506	if (inp != 0) {
507		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
508		return EINVAL;
509	}
510	if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
511		error = SCTP_SORESERVE(so, SCTP_BASE_SYSCTL(sctp_sendspace), SCTP_BASE_SYSCTL(sctp_recvspace));
512		if (error) {
513			return error;
514		}
515	}
516	error = sctp_inpcb_alloc(so, vrf_id);
517	if (error) {
518		return error;
519	}
520	inp = (struct sctp_inpcb *)so->so_pcb;
521	SCTP_INP_WLOCK(inp);
522	inp->sctp_flags &= ~SCTP_PCB_FLAGS_BOUND_V6;	/* I'm not v6! */
523	ip_inp = &inp->ip_inp.inp;
524	ip_inp->inp_vflag |= INP_IPV4;
525	ip_inp->inp_ip_ttl = MODULE_GLOBAL(ip_defttl);
526#ifdef IPSEC
527	error = ipsec_init_policy(so, &ip_inp->inp_sp);
528#ifdef SCTP_LOG_CLOSING
529	sctp_log_closing(inp, NULL, 17);
530#endif
531	if (error != 0) {
532try_again:
533		flags = inp->sctp_flags;
534		if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
535		    (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
536#ifdef SCTP_LOG_CLOSING
537			sctp_log_closing(inp, NULL, 15);
538#endif
539			SCTP_INP_WUNLOCK(inp);
540			sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
541			    SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
542		} else {
543			flags = inp->sctp_flags;
544			if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
545				goto try_again;
546			} else {
547				SCTP_INP_WUNLOCK(inp);
548			}
549		}
550		return error;
551	}
552#endif				/* IPSEC */
553	SCTP_INP_WUNLOCK(inp);
554	return 0;
555}
556
557static int
558sctp_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
559{
560	struct sctp_inpcb *inp = NULL;
561	int error;
562
563#ifdef INET
564	if (addr && addr->sa_family != AF_INET) {
565		/* must be a v4 address! */
566		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
567		return EINVAL;
568	}
569#endif				/* INET6 */
570	if (addr && (addr->sa_len != sizeof(struct sockaddr_in))) {
571		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
572		return EINVAL;
573	}
574	inp = (struct sctp_inpcb *)so->so_pcb;
575	if (inp == 0) {
576		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
577		return EINVAL;
578	}
579	error = sctp_inpcb_bind(so, addr, NULL, p);
580	return error;
581}
582
583#endif
584void
585sctp_close(struct socket *so)
586{
587	struct sctp_inpcb *inp;
588	uint32_t flags;
589
590	inp = (struct sctp_inpcb *)so->so_pcb;
591	if (inp == 0)
592		return;
593
594	/*
595	 * Inform all the lower layer assoc that we are done.
596	 */
597sctp_must_try_again:
598	flags = inp->sctp_flags;
599#ifdef SCTP_LOG_CLOSING
600	sctp_log_closing(inp, NULL, 17);
601#endif
602	if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
603	    (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
604		if (((so->so_options & SO_LINGER) && (so->so_linger == 0)) ||
605		    (so->so_rcv.sb_cc > 0)) {
606#ifdef SCTP_LOG_CLOSING
607			sctp_log_closing(inp, NULL, 13);
608#endif
609			sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
610			    SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
611		} else {
612#ifdef SCTP_LOG_CLOSING
613			sctp_log_closing(inp, NULL, 14);
614#endif
615			sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_GRACEFUL_CLOSE,
616			    SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
617		}
618		/*
619		 * The socket is now detached, no matter what the state of
620		 * the SCTP association.
621		 */
622		SOCK_LOCK(so);
623		SCTP_SB_CLEAR(so->so_snd);
624		/*
625		 * same for the rcv ones, they are only here for the
626		 * accounting/select.
627		 */
628		SCTP_SB_CLEAR(so->so_rcv);
629
630		/* Now null out the reference, we are completely detached. */
631		so->so_pcb = NULL;
632		SOCK_UNLOCK(so);
633	} else {
634		flags = inp->sctp_flags;
635		if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
636			goto sctp_must_try_again;
637		}
638	}
639	return;
640}
641
642
643int
644sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
645    struct mbuf *control, struct thread *p);
646
647
648int
649sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
650    struct mbuf *control, struct thread *p)
651{
652	struct sctp_inpcb *inp;
653	int error;
654
655	inp = (struct sctp_inpcb *)so->so_pcb;
656	if (inp == 0) {
657		if (control) {
658			sctp_m_freem(control);
659			control = NULL;
660		}
661		SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
662		sctp_m_freem(m);
663		return EINVAL;
664	}
665	/* Got to have an to address if we are NOT a connected socket */
666	if ((addr == NULL) &&
667	    ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) ||
668	    (inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE))
669	    ) {
670		goto connected_type;
671	} else if (addr == NULL) {
672		SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EDESTADDRREQ);
673		error = EDESTADDRREQ;
674		sctp_m_freem(m);
675		if (control) {
676			sctp_m_freem(control);
677			control = NULL;
678		}
679		return (error);
680	}
681#ifdef INET6
682	if (addr->sa_family != AF_INET) {
683		/* must be a v4 address! */
684		SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EDESTADDRREQ);
685		sctp_m_freem(m);
686		if (control) {
687			sctp_m_freem(control);
688			control = NULL;
689		}
690		error = EDESTADDRREQ;
691		return (error);
692	}
693#endif				/* INET6 */
694connected_type:
695	/* now what about control */
696	if (control) {
697		if (inp->control) {
698			SCTP_PRINTF("huh? control set?\n");
699			sctp_m_freem(inp->control);
700			inp->control = NULL;
701		}
702		inp->control = control;
703	}
704	/* Place the data */
705	if (inp->pkt) {
706		SCTP_BUF_NEXT(inp->pkt_last) = m;
707		inp->pkt_last = m;
708	} else {
709		inp->pkt_last = inp->pkt = m;
710	}
711	if (
712	/* FreeBSD uses a flag passed */
713	    ((flags & PRUS_MORETOCOME) == 0)
714	    ) {
715		/*
716		 * note with the current version this code will only be used
717		 * by OpenBSD-- NetBSD, FreeBSD, and MacOS have methods for
718		 * re-defining sosend to use the sctp_sosend. One can
719		 * optionally switch back to this code (by changing back the
720		 * definitions) but this is not advisable. This code is used
721		 * by FreeBSD when sending a file with sendfile() though.
722		 */
723		int ret;
724
725		ret = sctp_output(inp, inp->pkt, addr, inp->control, p, flags);
726		inp->pkt = NULL;
727		inp->control = NULL;
728		return (ret);
729	} else {
730		return (0);
731	}
732}
733
734int
735sctp_disconnect(struct socket *so)
736{
737	struct sctp_inpcb *inp;
738
739	inp = (struct sctp_inpcb *)so->so_pcb;
740	if (inp == NULL) {
741		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
742		return (ENOTCONN);
743	}
744	SCTP_INP_RLOCK(inp);
745	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
746	    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
747		if (LIST_EMPTY(&inp->sctp_asoc_list)) {
748			/* No connection */
749			SCTP_INP_RUNLOCK(inp);
750			return (0);
751		} else {
752			struct sctp_association *asoc;
753			struct sctp_tcb *stcb;
754
755			stcb = LIST_FIRST(&inp->sctp_asoc_list);
756			if (stcb == NULL) {
757				SCTP_INP_RUNLOCK(inp);
758				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
759				return (EINVAL);
760			}
761			SCTP_TCB_LOCK(stcb);
762			asoc = &stcb->asoc;
763			if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
764				/* We are about to be freed, out of here */
765				SCTP_TCB_UNLOCK(stcb);
766				SCTP_INP_RUNLOCK(inp);
767				return (0);
768			}
769			if (((so->so_options & SO_LINGER) &&
770			    (so->so_linger == 0)) ||
771			    (so->so_rcv.sb_cc > 0)) {
772				if (SCTP_GET_STATE(asoc) !=
773				    SCTP_STATE_COOKIE_WAIT) {
774					/* Left with Data unread */
775					struct mbuf *err;
776
777					err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), 0, M_DONTWAIT, 1, MT_DATA);
778					if (err) {
779						/*
780						 * Fill in the user
781						 * initiated abort
782						 */
783						struct sctp_paramhdr *ph;
784
785						ph = mtod(err, struct sctp_paramhdr *);
786						SCTP_BUF_LEN(err) = sizeof(struct sctp_paramhdr);
787						ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
788						ph->param_length = htons(SCTP_BUF_LEN(err));
789					}
790#if defined(SCTP_PANIC_ON_ABORT)
791					panic("disconnect does an abort");
792#endif
793					sctp_send_abort_tcb(stcb, err, SCTP_SO_LOCKED);
794					SCTP_STAT_INCR_COUNTER32(sctps_aborted);
795				}
796				SCTP_INP_RUNLOCK(inp);
797				if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
798				    (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
799					SCTP_STAT_DECR_GAUGE32(sctps_currestab);
800				}
801				(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_3);
802				/* No unlock tcb assoc is gone */
803				return (0);
804			}
805			if (TAILQ_EMPTY(&asoc->send_queue) &&
806			    TAILQ_EMPTY(&asoc->sent_queue) &&
807			    (asoc->stream_queue_cnt == 0)) {
808				/* there is nothing queued to send, so done */
809				if (asoc->locked_on_sending) {
810					goto abort_anyway;
811				}
812				if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) &&
813				    (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
814					/* only send SHUTDOWN 1st time thru */
815					struct sctp_nets *netp;
816
817					if (stcb->asoc.alternate) {
818						netp = stcb->asoc.alternate;
819					} else {
820						netp = stcb->asoc.primary_destination;
821					}
822					sctp_stop_timers_for_shutdown(stcb);
823					sctp_send_shutdown(stcb, netp);
824					sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_LOCKED);
825					if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
826					    (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
827						SCTP_STAT_DECR_GAUGE32(sctps_currestab);
828					}
829					SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
830					SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
831					sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
832					    stcb->sctp_ep, stcb, netp);
833					sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
834					    stcb->sctp_ep, stcb, netp);
835
836				}
837			} else {
838				/*
839				 * we still got (or just got) data to send,
840				 * so set SHUTDOWN_PENDING
841				 */
842				/*
843				 * XXX sockets draft says that SCTP_EOF
844				 * should be sent with no data. currently,
845				 * we will allow user data to be sent first
846				 * and move to SHUTDOWN-PENDING
847				 */
848				struct sctp_nets *netp;
849
850				if (stcb->asoc.alternate) {
851					netp = stcb->asoc.alternate;
852				} else {
853					netp = stcb->asoc.primary_destination;
854				}
855
856				asoc->state |= SCTP_STATE_SHUTDOWN_PENDING;
857				sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb,
858				    netp);
859				if (asoc->locked_on_sending) {
860					/* Locked to send out the data */
861					struct sctp_stream_queue_pending *sp;
862
863					sp = TAILQ_LAST(&asoc->locked_on_sending->outqueue, sctp_streamhead);
864					if (sp == NULL) {
865						SCTP_PRINTF("Error, sp is NULL, locked on sending is non-null strm:%d\n",
866						    asoc->locked_on_sending->stream_no);
867					} else {
868						if ((sp->length == 0) && (sp->msg_is_complete == 0))
869							asoc->state |= SCTP_STATE_PARTIAL_MSG_LEFT;
870					}
871				}
872				if (TAILQ_EMPTY(&asoc->send_queue) &&
873				    TAILQ_EMPTY(&asoc->sent_queue) &&
874				    (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
875					struct mbuf *op_err;
876
877			abort_anyway:
878					op_err = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)),
879					    0, M_DONTWAIT, 1, MT_DATA);
880					if (op_err) {
881						/*
882						 * Fill in the user
883						 * initiated abort
884						 */
885						struct sctp_paramhdr *ph;
886						uint32_t *ippp;
887
888						SCTP_BUF_LEN(op_err) =
889						    (sizeof(struct sctp_paramhdr) + sizeof(uint32_t));
890						ph = mtod(op_err,
891						    struct sctp_paramhdr *);
892						ph->param_type = htons(
893						    SCTP_CAUSE_USER_INITIATED_ABT);
894						ph->param_length = htons(SCTP_BUF_LEN(op_err));
895						ippp = (uint32_t *) (ph + 1);
896						*ippp = htonl(SCTP_FROM_SCTP_USRREQ + SCTP_LOC_4);
897					}
898#if defined(SCTP_PANIC_ON_ABORT)
899					panic("disconnect does an abort");
900#endif
901
902					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_4;
903					sctp_send_abort_tcb(stcb, op_err, SCTP_SO_LOCKED);
904					SCTP_STAT_INCR_COUNTER32(sctps_aborted);
905					if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
906					    (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
907						SCTP_STAT_DECR_GAUGE32(sctps_currestab);
908					}
909					SCTP_INP_RUNLOCK(inp);
910					(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_5);
911					return (0);
912				} else {
913					sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
914				}
915			}
916			soisdisconnecting(so);
917			SCTP_TCB_UNLOCK(stcb);
918			SCTP_INP_RUNLOCK(inp);
919			return (0);
920		}
921		/* not reached */
922	} else {
923		/* UDP model does not support this */
924		SCTP_INP_RUNLOCK(inp);
925		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
926		return EOPNOTSUPP;
927	}
928}
929
930int
931sctp_flush(struct socket *so, int how)
932{
933	/*
934	 * We will just clear out the values and let subsequent close clear
935	 * out the data, if any. Note if the user did a shutdown(SHUT_RD)
936	 * they will not be able to read the data, the socket will block
937	 * that from happening.
938	 */
939	struct sctp_inpcb *inp;
940
941	inp = (struct sctp_inpcb *)so->so_pcb;
942	if (inp == NULL) {
943		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
944		return EINVAL;
945	}
946	SCTP_INP_RLOCK(inp);
947	/* For the 1 to many model this does nothing */
948	if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
949		SCTP_INP_RUNLOCK(inp);
950		return (0);
951	}
952	SCTP_INP_RUNLOCK(inp);
953	if ((how == PRU_FLUSH_RD) || (how == PRU_FLUSH_RDWR)) {
954		/*
955		 * First make sure the sb will be happy, we don't use these
956		 * except maybe the count
957		 */
958		SCTP_INP_WLOCK(inp);
959		SCTP_INP_READ_LOCK(inp);
960		inp->sctp_flags |= SCTP_PCB_FLAGS_SOCKET_CANT_READ;
961		SCTP_INP_READ_UNLOCK(inp);
962		SCTP_INP_WUNLOCK(inp);
963		so->so_rcv.sb_cc = 0;
964		so->so_rcv.sb_mbcnt = 0;
965		so->so_rcv.sb_mb = NULL;
966	}
967	if ((how == PRU_FLUSH_WR) || (how == PRU_FLUSH_RDWR)) {
968		/*
969		 * First make sure the sb will be happy, we don't use these
970		 * except maybe the count
971		 */
972		so->so_snd.sb_cc = 0;
973		so->so_snd.sb_mbcnt = 0;
974		so->so_snd.sb_mb = NULL;
975
976	}
977	return (0);
978}
979
980int
981sctp_shutdown(struct socket *so)
982{
983	struct sctp_inpcb *inp;
984
985	inp = (struct sctp_inpcb *)so->so_pcb;
986	if (inp == 0) {
987		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
988		return EINVAL;
989	}
990	SCTP_INP_RLOCK(inp);
991	/* For UDP model this is a invalid call */
992	if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
993		/* Restore the flags that the soshutdown took away. */
994		SOCKBUF_LOCK(&so->so_rcv);
995		so->so_rcv.sb_state &= ~SBS_CANTRCVMORE;
996		SOCKBUF_UNLOCK(&so->so_rcv);
997		/* This proc will wakeup for read and do nothing (I hope) */
998		SCTP_INP_RUNLOCK(inp);
999		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
1000		return (EOPNOTSUPP);
1001	}
1002	/*
1003	 * Ok if we reach here its the TCP model and it is either a SHUT_WR
1004	 * or SHUT_RDWR. This means we put the shutdown flag against it.
1005	 */
1006	{
1007		struct sctp_tcb *stcb;
1008		struct sctp_association *asoc;
1009
1010		if ((so->so_state &
1011		    (SS_ISCONNECTED | SS_ISCONNECTING | SS_ISDISCONNECTING)) == 0) {
1012			SCTP_INP_RUNLOCK(inp);
1013			return (ENOTCONN);
1014		}
1015		socantsendmore(so);
1016
1017		stcb = LIST_FIRST(&inp->sctp_asoc_list);
1018		if (stcb == NULL) {
1019			/*
1020			 * Ok we hit the case that the shutdown call was
1021			 * made after an abort or something. Nothing to do
1022			 * now.
1023			 */
1024			SCTP_INP_RUNLOCK(inp);
1025			return (0);
1026		}
1027		SCTP_TCB_LOCK(stcb);
1028		asoc = &stcb->asoc;
1029		if (TAILQ_EMPTY(&asoc->send_queue) &&
1030		    TAILQ_EMPTY(&asoc->sent_queue) &&
1031		    (asoc->stream_queue_cnt == 0)) {
1032			if (asoc->locked_on_sending) {
1033				goto abort_anyway;
1034			}
1035			/* there is nothing queued to send, so I'm done... */
1036			if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) {
1037				/* only send SHUTDOWN the first time through */
1038				struct sctp_nets *netp;
1039
1040				if (stcb->asoc.alternate) {
1041					netp = stcb->asoc.alternate;
1042				} else {
1043					netp = stcb->asoc.primary_destination;
1044				}
1045				sctp_stop_timers_for_shutdown(stcb);
1046				sctp_send_shutdown(stcb, netp);
1047				sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_LOCKED);
1048				if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
1049				    (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
1050					SCTP_STAT_DECR_GAUGE32(sctps_currestab);
1051				}
1052				SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
1053				SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
1054				sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
1055				    stcb->sctp_ep, stcb, netp);
1056				sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
1057				    stcb->sctp_ep, stcb, netp);
1058			}
1059		} else {
1060			/*
1061			 * we still got (or just got) data to send, so set
1062			 * SHUTDOWN_PENDING
1063			 */
1064			struct sctp_nets *netp;
1065
1066			if (stcb->asoc.alternate) {
1067				netp = stcb->asoc.alternate;
1068			} else {
1069				netp = stcb->asoc.primary_destination;
1070			}
1071
1072			asoc->state |= SCTP_STATE_SHUTDOWN_PENDING;
1073			sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb,
1074			    netp);
1075
1076			if (asoc->locked_on_sending) {
1077				/* Locked to send out the data */
1078				struct sctp_stream_queue_pending *sp;
1079
1080				sp = TAILQ_LAST(&asoc->locked_on_sending->outqueue, sctp_streamhead);
1081				if (sp == NULL) {
1082					SCTP_PRINTF("Error, sp is NULL, locked on sending is non-null strm:%d\n",
1083					    asoc->locked_on_sending->stream_no);
1084				} else {
1085					if ((sp->length == 0) && (sp->msg_is_complete == 0)) {
1086						asoc->state |= SCTP_STATE_PARTIAL_MSG_LEFT;
1087					}
1088				}
1089			}
1090			if (TAILQ_EMPTY(&asoc->send_queue) &&
1091			    TAILQ_EMPTY(&asoc->sent_queue) &&
1092			    (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
1093				struct mbuf *op_err;
1094
1095		abort_anyway:
1096				op_err = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)),
1097				    0, M_DONTWAIT, 1, MT_DATA);
1098				if (op_err) {
1099					/* Fill in the user initiated abort */
1100					struct sctp_paramhdr *ph;
1101					uint32_t *ippp;
1102
1103					SCTP_BUF_LEN(op_err) =
1104					    sizeof(struct sctp_paramhdr) + sizeof(uint32_t);
1105					ph = mtod(op_err,
1106					    struct sctp_paramhdr *);
1107					ph->param_type = htons(
1108					    SCTP_CAUSE_USER_INITIATED_ABT);
1109					ph->param_length = htons(SCTP_BUF_LEN(op_err));
1110					ippp = (uint32_t *) (ph + 1);
1111					*ippp = htonl(SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6);
1112				}
1113#if defined(SCTP_PANIC_ON_ABORT)
1114				panic("shutdown does an abort");
1115#endif
1116				stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6;
1117				sctp_abort_an_association(stcb->sctp_ep, stcb,
1118				    SCTP_RESPONSE_TO_USER_REQ,
1119				    op_err, SCTP_SO_LOCKED);
1120				goto skip_unlock;
1121			} else {
1122				sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
1123			}
1124		}
1125		SCTP_TCB_UNLOCK(stcb);
1126	}
1127skip_unlock:
1128	SCTP_INP_RUNLOCK(inp);
1129	return 0;
1130}
1131
1132/*
1133 * copies a "user" presentable address and removes embedded scope, etc.
1134 * returns 0 on success, 1 on error
1135 */
1136static uint32_t
1137sctp_fill_user_address(struct sockaddr_storage *ss, struct sockaddr *sa)
1138{
1139#ifdef INET6
1140	struct sockaddr_in6 lsa6;
1141
1142	sa = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)sa,
1143	    &lsa6);
1144#endif
1145	memcpy(ss, sa, sa->sa_len);
1146	return (0);
1147}
1148
1149
1150
1151/*
1152 * NOTE: assumes addr lock is held
1153 */
1154static size_t
1155sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp,
1156    struct sctp_tcb *stcb,
1157    size_t limit,
1158    struct sockaddr_storage *sas,
1159    uint32_t vrf_id)
1160{
1161	struct sctp_ifn *sctp_ifn;
1162	struct sctp_ifa *sctp_ifa;
1163	int loopback_scope, ipv4_local_scope, local_scope, site_scope;
1164	size_t actual;
1165	int ipv4_addr_legal, ipv6_addr_legal;
1166	struct sctp_vrf *vrf;
1167
1168	actual = 0;
1169	if (limit <= 0)
1170		return (actual);
1171
1172	if (stcb) {
1173		/* Turn on all the appropriate scope */
1174		loopback_scope = stcb->asoc.loopback_scope;
1175		ipv4_local_scope = stcb->asoc.ipv4_local_scope;
1176		local_scope = stcb->asoc.local_scope;
1177		site_scope = stcb->asoc.site_scope;
1178	} else {
1179		/* Turn on ALL scope, since we look at the EP */
1180		loopback_scope = ipv4_local_scope = local_scope =
1181		    site_scope = 1;
1182	}
1183	ipv4_addr_legal = ipv6_addr_legal = 0;
1184	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
1185		ipv6_addr_legal = 1;
1186		if (SCTP_IPV6_V6ONLY(inp) == 0) {
1187			ipv4_addr_legal = 1;
1188		}
1189	} else {
1190		ipv4_addr_legal = 1;
1191	}
1192	vrf = sctp_find_vrf(vrf_id);
1193	if (vrf == NULL) {
1194		return (0);
1195	}
1196	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
1197		LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
1198			if ((loopback_scope == 0) &&
1199			    SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
1200				/* Skip loopback if loopback_scope not set */
1201				continue;
1202			}
1203			LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
1204				if (stcb) {
1205					/*
1206					 * For the BOUND-ALL case, the list
1207					 * associated with a TCB is Always
1208					 * considered a reverse list.. i.e.
1209					 * it lists addresses that are NOT
1210					 * part of the association. If this
1211					 * is one of those we must skip it.
1212					 */
1213					if (sctp_is_addr_restricted(stcb,
1214					    sctp_ifa)) {
1215						continue;
1216					}
1217				}
1218				switch (sctp_ifa->address.sa.sa_family) {
1219#ifdef INET
1220				case AF_INET:
1221					if (ipv4_addr_legal) {
1222						struct sockaddr_in *sin;
1223
1224						sin = (struct sockaddr_in *)&sctp_ifa->address.sa;
1225						if (sin->sin_addr.s_addr == 0) {
1226							/*
1227							 * we skip
1228							 * unspecifed
1229							 * addresses
1230							 */
1231							continue;
1232						}
1233						if ((ipv4_local_scope == 0) &&
1234						    (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) {
1235							continue;
1236						}
1237#ifdef INET6
1238						if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
1239							in6_sin_2_v4mapsin6(sin, (struct sockaddr_in6 *)sas);
1240							((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
1241							sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(struct sockaddr_in6));
1242							actual += sizeof(struct sockaddr_in6);
1243						} else {
1244#endif
1245							memcpy(sas, sin, sizeof(*sin));
1246							((struct sockaddr_in *)sas)->sin_port = inp->sctp_lport;
1247							sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(*sin));
1248							actual += sizeof(*sin);
1249#ifdef INET6
1250						}
1251#endif
1252						if (actual >= limit) {
1253							return (actual);
1254						}
1255					} else {
1256						continue;
1257					}
1258					break;
1259#endif
1260#ifdef INET6
1261				case AF_INET6:
1262					if (ipv6_addr_legal) {
1263						struct sockaddr_in6 *sin6;
1264
1265						sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa;
1266						if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
1267							/*
1268							 * we skip
1269							 * unspecifed
1270							 * addresses
1271							 */
1272							continue;
1273						}
1274						if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
1275							if (local_scope == 0)
1276								continue;
1277							if (sin6->sin6_scope_id == 0) {
1278								if (sa6_recoverscope(sin6) != 0)
1279									/*
1280									 *
1281									 * bad
1282									 *
1283									 * li
1284									 * nk
1285									 *
1286									 * loc
1287									 * al
1288									 *
1289									 * add
1290									 * re
1291									 * ss
1292									 * */
1293									continue;
1294							}
1295						}
1296						if ((site_scope == 0) &&
1297						    (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) {
1298							continue;
1299						}
1300						memcpy(sas, sin6, sizeof(*sin6));
1301						((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
1302						sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(*sin6));
1303						actual += sizeof(*sin6);
1304						if (actual >= limit) {
1305							return (actual);
1306						}
1307					} else {
1308						continue;
1309					}
1310					break;
1311#endif
1312				default:
1313					/* TSNH */
1314					break;
1315				}
1316			}
1317		}
1318	} else {
1319		struct sctp_laddr *laddr;
1320
1321		LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
1322			if (stcb) {
1323				if (sctp_is_addr_restricted(stcb, laddr->ifa)) {
1324					continue;
1325				}
1326			}
1327			if (sctp_fill_user_address(sas, &laddr->ifa->address.sa))
1328				continue;
1329
1330			((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
1331			sas = (struct sockaddr_storage *)((caddr_t)sas +
1332			    laddr->ifa->address.sa.sa_len);
1333			actual += laddr->ifa->address.sa.sa_len;
1334			if (actual >= limit) {
1335				return (actual);
1336			}
1337		}
1338	}
1339	return (actual);
1340}
1341
1342static size_t
1343sctp_fill_up_addresses(struct sctp_inpcb *inp,
1344    struct sctp_tcb *stcb,
1345    size_t limit,
1346    struct sockaddr_storage *sas)
1347{
1348	size_t size = 0;
1349
1350	SCTP_IPI_ADDR_RLOCK();
1351	/* fill up addresses for the endpoint's default vrf */
1352	size = sctp_fill_up_addresses_vrf(inp, stcb, limit, sas,
1353	    inp->def_vrf_id);
1354	SCTP_IPI_ADDR_RUNLOCK();
1355	return (size);
1356}
1357
1358/*
1359 * NOTE: assumes addr lock is held
1360 */
1361static int
1362sctp_count_max_addresses_vrf(struct sctp_inpcb *inp, uint32_t vrf_id)
1363{
1364	int cnt = 0;
1365	struct sctp_vrf *vrf = NULL;
1366
1367	/*
1368	 * In both sub-set bound an bound_all cases we return the MAXIMUM
1369	 * number of addresses that you COULD get. In reality the sub-set
1370	 * bound may have an exclusion list for a given TCB OR in the
1371	 * bound-all case a TCB may NOT include the loopback or other
1372	 * addresses as well.
1373	 */
1374	vrf = sctp_find_vrf(vrf_id);
1375	if (vrf == NULL) {
1376		return (0);
1377	}
1378	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
1379		struct sctp_ifn *sctp_ifn;
1380		struct sctp_ifa *sctp_ifa;
1381
1382		LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
1383			LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
1384				/* Count them if they are the right type */
1385				switch (sctp_ifa->address.sa.sa_family) {
1386#ifdef INET
1387				case AF_INET:
1388					if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4))
1389						cnt += sizeof(struct sockaddr_in6);
1390					else
1391						cnt += sizeof(struct sockaddr_in);
1392					break;
1393#endif
1394#ifdef INET6
1395				case AF_INET6:
1396					cnt += sizeof(struct sockaddr_in6);
1397					break;
1398#endif
1399				default:
1400					break;
1401				}
1402			}
1403		}
1404	} else {
1405		struct sctp_laddr *laddr;
1406
1407		LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
1408			switch (laddr->ifa->address.sa.sa_family) {
1409#ifdef INET
1410			case AF_INET:
1411				if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4))
1412					cnt += sizeof(struct sockaddr_in6);
1413				else
1414					cnt += sizeof(struct sockaddr_in);
1415				break;
1416#endif
1417#ifdef INET6
1418			case AF_INET6:
1419				cnt += sizeof(struct sockaddr_in6);
1420				break;
1421#endif
1422			default:
1423				break;
1424			}
1425		}
1426	}
1427	return (cnt);
1428}
1429
1430static int
1431sctp_count_max_addresses(struct sctp_inpcb *inp)
1432{
1433	int cnt = 0;
1434
1435	SCTP_IPI_ADDR_RLOCK();
1436	/* count addresses for the endpoint's default VRF */
1437	cnt = sctp_count_max_addresses_vrf(inp, inp->def_vrf_id);
1438	SCTP_IPI_ADDR_RUNLOCK();
1439	return (cnt);
1440}
1441
1442static int
1443sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
1444    size_t optsize, void *p, int delay)
1445{
1446	int error = 0;
1447	int creat_lock_on = 0;
1448	struct sctp_tcb *stcb = NULL;
1449	struct sockaddr *sa;
1450	int num_v6 = 0, num_v4 = 0, *totaddrp, totaddr;
1451	uint32_t vrf_id;
1452	int bad_addresses = 0;
1453	sctp_assoc_t *a_id;
1454
1455	SCTPDBG(SCTP_DEBUG_PCB1, "Connectx called\n");
1456
1457	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
1458	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
1459		/* We are already connected AND the TCP model */
1460		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
1461		return (EADDRINUSE);
1462	}
1463	if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
1464	    (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
1465		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1466		return (EINVAL);
1467	}
1468	if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
1469		SCTP_INP_RLOCK(inp);
1470		stcb = LIST_FIRST(&inp->sctp_asoc_list);
1471		SCTP_INP_RUNLOCK(inp);
1472	}
1473	if (stcb) {
1474		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
1475		return (EALREADY);
1476	}
1477	SCTP_INP_INCR_REF(inp);
1478	SCTP_ASOC_CREATE_LOCK(inp);
1479	creat_lock_on = 1;
1480	if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
1481	    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
1482		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
1483		error = EFAULT;
1484		goto out_now;
1485	}
1486	totaddrp = (int *)optval;
1487	totaddr = *totaddrp;
1488	sa = (struct sockaddr *)(totaddrp + 1);
1489	stcb = sctp_connectx_helper_find(inp, sa, &totaddr, &num_v4, &num_v6, &error, (optsize - sizeof(int)), &bad_addresses);
1490	if ((stcb != NULL) || bad_addresses) {
1491		/* Already have or am bring up an association */
1492		SCTP_ASOC_CREATE_UNLOCK(inp);
1493		creat_lock_on = 0;
1494		if (stcb)
1495			SCTP_TCB_UNLOCK(stcb);
1496		if (bad_addresses == 0) {
1497			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
1498			error = EALREADY;
1499		}
1500		goto out_now;
1501	}
1502#ifdef INET6
1503	if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
1504	    (num_v6 > 0)) {
1505		error = EINVAL;
1506		goto out_now;
1507	}
1508	if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
1509	    (num_v4 > 0)) {
1510		struct in6pcb *inp6;
1511
1512		inp6 = (struct in6pcb *)inp;
1513		if (SCTP_IPV6_V6ONLY(inp6)) {
1514			/*
1515			 * if IPV6_V6ONLY flag, ignore connections destined
1516			 * to a v4 addr or v4-mapped addr
1517			 */
1518			SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1519			error = EINVAL;
1520			goto out_now;
1521		}
1522	}
1523#endif				/* INET6 */
1524	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
1525	    SCTP_PCB_FLAGS_UNBOUND) {
1526		/* Bind a ephemeral port */
1527		error = sctp_inpcb_bind(so, NULL, NULL, p);
1528		if (error) {
1529			goto out_now;
1530		}
1531	}
1532	/* FIX ME: do we want to pass in a vrf on the connect call? */
1533	vrf_id = inp->def_vrf_id;
1534
1535
1536	/* We are GOOD to go */
1537	stcb = sctp_aloc_assoc(inp, sa, &error, 0, vrf_id,
1538	    (struct thread *)p
1539	    );
1540	if (stcb == NULL) {
1541		/* Gak! no memory */
1542		goto out_now;
1543	}
1544	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
1545		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
1546		/* Set the connected flag so we can queue data */
1547		soisconnecting(so);
1548	}
1549	SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
1550	/* move to second address */
1551	switch (sa->sa_family) {
1552#ifdef INET
1553	case AF_INET:
1554		sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in));
1555		break;
1556#endif
1557#ifdef INET6
1558	case AF_INET6:
1559		sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in6));
1560		break;
1561#endif
1562	default:
1563		break;
1564	}
1565
1566	error = 0;
1567	sctp_connectx_helper_add(stcb, sa, (totaddr - 1), &error);
1568	/* Fill in the return id */
1569	if (error) {
1570		(void)sctp_free_assoc(inp, stcb, SCTP_PCBFREE_FORCE, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6);
1571		goto out_now;
1572	}
1573	a_id = (sctp_assoc_t *) optval;
1574	*a_id = sctp_get_associd(stcb);
1575
1576	/* initialize authentication parameters for the assoc */
1577	sctp_initialize_auth_params(inp, stcb);
1578
1579	if (delay) {
1580		/* doing delayed connection */
1581		stcb->asoc.delayed_connection = 1;
1582		sctp_timer_start(SCTP_TIMER_TYPE_INIT, inp, stcb, stcb->asoc.primary_destination);
1583	} else {
1584		(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
1585		sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
1586	}
1587	SCTP_TCB_UNLOCK(stcb);
1588	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
1589		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
1590		/* Set the connected flag so we can queue data */
1591		soisconnecting(so);
1592	}
1593out_now:
1594	if (creat_lock_on) {
1595		SCTP_ASOC_CREATE_UNLOCK(inp);
1596	}
1597	SCTP_INP_DECR_REF(inp);
1598	return error;
1599}
1600
1601#define SCTP_FIND_STCB(inp, stcb, assoc_id) { \
1602	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||\
1603	    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { \
1604		SCTP_INP_RLOCK(inp); \
1605		stcb = LIST_FIRST(&inp->sctp_asoc_list); \
1606		if (stcb) { \
1607			SCTP_TCB_LOCK(stcb); \
1608                } \
1609		SCTP_INP_RUNLOCK(inp); \
1610	} else if (assoc_id > SCTP_ALL_ASSOC) { \
1611		stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1); \
1612		if (stcb == NULL) { \
1613		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT); \
1614			error = ENOENT; \
1615			break; \
1616		} \
1617	} else { \
1618		stcb = NULL; \
1619        } \
1620  }
1621
1622
1623#define SCTP_CHECK_AND_CAST(destp, srcp, type, size)  {\
1624	if (size < sizeof(type)) { \
1625		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); \
1626		error = EINVAL; \
1627		break; \
1628	} else { \
1629		destp = (type *)srcp; \
1630	} \
1631      }
1632
1633static int
1634sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
1635    void *p)
1636{
1637	struct sctp_inpcb *inp = NULL;
1638	int error, val = 0;
1639	struct sctp_tcb *stcb = NULL;
1640
1641	if (optval == NULL) {
1642		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1643		return (EINVAL);
1644	}
1645	inp = (struct sctp_inpcb *)so->so_pcb;
1646	if (inp == 0) {
1647		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1648		return EINVAL;
1649	}
1650	error = 0;
1651
1652	switch (optname) {
1653	case SCTP_NODELAY:
1654	case SCTP_AUTOCLOSE:
1655	case SCTP_EXPLICIT_EOR:
1656	case SCTP_AUTO_ASCONF:
1657	case SCTP_DISABLE_FRAGMENTS:
1658	case SCTP_I_WANT_MAPPED_V4_ADDR:
1659	case SCTP_USE_EXT_RCVINFO:
1660		SCTP_INP_RLOCK(inp);
1661		switch (optname) {
1662		case SCTP_DISABLE_FRAGMENTS:
1663			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NO_FRAGMENT);
1664			break;
1665		case SCTP_I_WANT_MAPPED_V4_ADDR:
1666			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4);
1667			break;
1668		case SCTP_AUTO_ASCONF:
1669			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
1670				/* only valid for bound all sockets */
1671				val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTO_ASCONF);
1672			} else {
1673				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1674				error = EINVAL;
1675				goto flags_out;
1676			}
1677			break;
1678		case SCTP_EXPLICIT_EOR:
1679			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR);
1680			break;
1681		case SCTP_NODELAY:
1682			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NODELAY);
1683			break;
1684		case SCTP_USE_EXT_RCVINFO:
1685			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO);
1686			break;
1687		case SCTP_AUTOCLOSE:
1688			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE))
1689				val = TICKS_TO_SEC(inp->sctp_ep.auto_close_time);
1690			else
1691				val = 0;
1692			break;
1693
1694		default:
1695			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
1696			error = ENOPROTOOPT;
1697		}		/* end switch (sopt->sopt_name) */
1698		if (*optsize < sizeof(val)) {
1699			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1700			error = EINVAL;
1701		}
1702flags_out:
1703		SCTP_INP_RUNLOCK(inp);
1704		if (error == 0) {
1705			/* return the option value */
1706			*(int *)optval = val;
1707			*optsize = sizeof(val);
1708		}
1709		break;
1710	case SCTP_GET_PACKET_LOG:
1711		{
1712#ifdef  SCTP_PACKET_LOGGING
1713			uint8_t *target;
1714			int ret;
1715
1716			SCTP_CHECK_AND_CAST(target, optval, uint8_t, *optsize);
1717			ret = sctp_copy_out_packet_log(target, (int)*optsize);
1718			*optsize = ret;
1719#else
1720			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
1721			error = EOPNOTSUPP;
1722#endif
1723			break;
1724		}
1725	case SCTP_REUSE_PORT:
1726		{
1727			uint32_t *value;
1728
1729			if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
1730				/* Can't do this for a 1-m socket */
1731				error = EINVAL;
1732				break;
1733			}
1734			SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
1735			*value = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE);
1736			*optsize = sizeof(uint32_t);
1737			break;
1738		}
1739	case SCTP_PARTIAL_DELIVERY_POINT:
1740		{
1741			uint32_t *value;
1742
1743			SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
1744			*value = inp->partial_delivery_point;
1745			*optsize = sizeof(uint32_t);
1746			break;
1747		}
1748	case SCTP_FRAGMENT_INTERLEAVE:
1749		{
1750			uint32_t *value;
1751
1752			SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
1753			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE)) {
1754				if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS)) {
1755					*value = SCTP_FRAG_LEVEL_2;
1756				} else {
1757					*value = SCTP_FRAG_LEVEL_1;
1758				}
1759			} else {
1760				*value = SCTP_FRAG_LEVEL_0;
1761			}
1762			*optsize = sizeof(uint32_t);
1763			break;
1764		}
1765	case SCTP_CMT_ON_OFF:
1766		{
1767			struct sctp_assoc_value *av;
1768
1769			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
1770			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
1771			if (stcb) {
1772				av->assoc_value = stcb->asoc.sctp_cmt_on_off;
1773				SCTP_TCB_UNLOCK(stcb);
1774			} else {
1775				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1776				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
1777				    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
1778					SCTP_INP_RLOCK(inp);
1779					av->assoc_value = inp->sctp_cmt_on_off;
1780					SCTP_INP_RUNLOCK(inp);
1781				} else {
1782					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1783					error = EINVAL;
1784				}
1785			}
1786			if (error == 0) {
1787				*optsize = sizeof(struct sctp_assoc_value);
1788			}
1789			break;
1790		}
1791	case SCTP_PLUGGABLE_CC:
1792		{
1793			struct sctp_assoc_value *av;
1794
1795			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
1796			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
1797			if (stcb) {
1798				av->assoc_value = stcb->asoc.congestion_control_module;
1799				SCTP_TCB_UNLOCK(stcb);
1800			} else {
1801				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1802				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
1803				    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
1804					SCTP_INP_RLOCK(inp);
1805					av->assoc_value = inp->sctp_ep.sctp_default_cc_module;
1806					SCTP_INP_RUNLOCK(inp);
1807				} else {
1808					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1809					error = EINVAL;
1810				}
1811			}
1812			if (error == 0) {
1813				*optsize = sizeof(struct sctp_assoc_value);
1814			}
1815			break;
1816		}
1817	case SCTP_CC_OPTION:
1818		{
1819			struct sctp_cc_option *cc_opt;
1820
1821			SCTP_CHECK_AND_CAST(cc_opt, optval, struct sctp_cc_option, *optsize);
1822			SCTP_FIND_STCB(inp, stcb, cc_opt->aid_value.assoc_id);
1823			if (stcb == NULL) {
1824				error = EINVAL;
1825			} else {
1826				if (stcb->asoc.cc_functions.sctp_cwnd_socket_option == NULL) {
1827					error = ENOTSUP;
1828				} else {
1829					error = (*stcb->asoc.cc_functions.sctp_cwnd_socket_option) (stcb, 0, cc_opt);
1830					*optsize = sizeof(struct sctp_cc_option);
1831				}
1832				SCTP_TCB_UNLOCK(stcb);
1833			}
1834			break;
1835		}
1836	case SCTP_PLUGGABLE_SS:
1837		{
1838			struct sctp_assoc_value *av;
1839
1840			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
1841			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
1842			if (stcb) {
1843				av->assoc_value = stcb->asoc.stream_scheduling_module;
1844				SCTP_TCB_UNLOCK(stcb);
1845			} else {
1846				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1847				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
1848				    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
1849					SCTP_INP_RLOCK(inp);
1850					av->assoc_value = inp->sctp_ep.sctp_default_ss_module;
1851					SCTP_INP_RUNLOCK(inp);
1852				} else {
1853					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1854					error = EINVAL;
1855				}
1856			}
1857			if (error == 0) {
1858				*optsize = sizeof(struct sctp_assoc_value);
1859			}
1860			break;
1861		}
1862	case SCTP_SS_VALUE:
1863		{
1864			struct sctp_stream_value *av;
1865
1866			SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, *optsize);
1867			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
1868			if (stcb) {
1869				if (stcb->asoc.ss_functions.sctp_ss_get_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id],
1870				    &av->stream_value) < 0) {
1871					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1872					error = EINVAL;
1873				} else {
1874					*optsize = sizeof(struct sctp_stream_value);
1875				}
1876				SCTP_TCB_UNLOCK(stcb);
1877			} else {
1878				/*
1879				 * Can't get stream value without
1880				 * association
1881				 */
1882				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1883				error = EINVAL;
1884			}
1885			break;
1886		}
1887	case SCTP_GET_ADDR_LEN:
1888		{
1889			struct sctp_assoc_value *av;
1890
1891			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
1892			error = EINVAL;
1893#ifdef INET
1894			if (av->assoc_value == AF_INET) {
1895				av->assoc_value = sizeof(struct sockaddr_in);
1896				error = 0;
1897			}
1898#endif
1899#ifdef INET6
1900			if (av->assoc_value == AF_INET6) {
1901				av->assoc_value = sizeof(struct sockaddr_in6);
1902				error = 0;
1903			}
1904#endif
1905			if (error) {
1906				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
1907			} else {
1908				*optsize = sizeof(struct sctp_assoc_value);
1909			}
1910			break;
1911		}
1912	case SCTP_GET_ASSOC_NUMBER:
1913		{
1914			uint32_t *value, cnt;
1915
1916			SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
1917			cnt = 0;
1918			SCTP_INP_RLOCK(inp);
1919			LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
1920				cnt++;
1921			}
1922			SCTP_INP_RUNLOCK(inp);
1923			*value = cnt;
1924			*optsize = sizeof(uint32_t);
1925			break;
1926		}
1927	case SCTP_GET_ASSOC_ID_LIST:
1928		{
1929			struct sctp_assoc_ids *ids;
1930			unsigned int at, limit;
1931
1932			SCTP_CHECK_AND_CAST(ids, optval, struct sctp_assoc_ids, *optsize);
1933			at = 0;
1934			limit = (*optsize - sizeof(uint32_t)) / sizeof(sctp_assoc_t);
1935			SCTP_INP_RLOCK(inp);
1936			LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
1937				if (at < limit) {
1938					ids->gaids_assoc_id[at++] = sctp_get_associd(stcb);
1939				} else {
1940					error = EINVAL;
1941					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
1942					break;
1943				}
1944			}
1945			SCTP_INP_RUNLOCK(inp);
1946			if (error == 0) {
1947				ids->gaids_number_of_ids = at;
1948				*optsize = ((at * sizeof(sctp_assoc_t)) + sizeof(uint32_t));
1949			}
1950			break;
1951		}
1952	case SCTP_CONTEXT:
1953		{
1954			struct sctp_assoc_value *av;
1955
1956			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
1957			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
1958
1959			if (stcb) {
1960				av->assoc_value = stcb->asoc.context;
1961				SCTP_TCB_UNLOCK(stcb);
1962			} else {
1963				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1964				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
1965				    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
1966					SCTP_INP_RLOCK(inp);
1967					av->assoc_value = inp->sctp_context;
1968					SCTP_INP_RUNLOCK(inp);
1969				} else {
1970					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1971					error = EINVAL;
1972				}
1973			}
1974			if (error == 0) {
1975				*optsize = sizeof(struct sctp_assoc_value);
1976			}
1977			break;
1978		}
1979	case SCTP_VRF_ID:
1980		{
1981			uint32_t *default_vrfid;
1982
1983			SCTP_CHECK_AND_CAST(default_vrfid, optval, uint32_t, *optsize);
1984			*default_vrfid = inp->def_vrf_id;
1985			*optsize = sizeof(uint32_t);
1986			break;
1987		}
1988	case SCTP_GET_ASOC_VRF:
1989		{
1990			struct sctp_assoc_value *id;
1991
1992			SCTP_CHECK_AND_CAST(id, optval, struct sctp_assoc_value, *optsize);
1993			SCTP_FIND_STCB(inp, stcb, id->assoc_id);
1994			if (stcb == NULL) {
1995				error = EINVAL;
1996				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
1997			} else {
1998				id->assoc_value = stcb->asoc.vrf_id;
1999				*optsize = sizeof(struct sctp_assoc_value);
2000			}
2001			break;
2002		}
2003	case SCTP_GET_VRF_IDS:
2004		{
2005			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
2006			error = EOPNOTSUPP;
2007			break;
2008		}
2009	case SCTP_GET_NONCE_VALUES:
2010		{
2011			struct sctp_get_nonce_values *gnv;
2012
2013			SCTP_CHECK_AND_CAST(gnv, optval, struct sctp_get_nonce_values, *optsize);
2014			SCTP_FIND_STCB(inp, stcb, gnv->gn_assoc_id);
2015
2016			if (stcb) {
2017				gnv->gn_peers_tag = stcb->asoc.peer_vtag;
2018				gnv->gn_local_tag = stcb->asoc.my_vtag;
2019				SCTP_TCB_UNLOCK(stcb);
2020				*optsize = sizeof(struct sctp_get_nonce_values);
2021			} else {
2022				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
2023				error = ENOTCONN;
2024			}
2025			break;
2026		}
2027	case SCTP_DELAYED_SACK:
2028		{
2029			struct sctp_sack_info *sack;
2030
2031			SCTP_CHECK_AND_CAST(sack, optval, struct sctp_sack_info, *optsize);
2032			SCTP_FIND_STCB(inp, stcb, sack->sack_assoc_id);
2033			if (stcb) {
2034				sack->sack_delay = stcb->asoc.delayed_ack;
2035				sack->sack_freq = stcb->asoc.sack_freq;
2036				SCTP_TCB_UNLOCK(stcb);
2037			} else {
2038				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2039				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2040				    (sack->sack_assoc_id == SCTP_FUTURE_ASSOC)) {
2041					SCTP_INP_RLOCK(inp);
2042					sack->sack_delay = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
2043					sack->sack_freq = inp->sctp_ep.sctp_sack_freq;
2044					SCTP_INP_RUNLOCK(inp);
2045				} else {
2046					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2047					error = EINVAL;
2048				}
2049			}
2050			if (error == 0) {
2051				*optsize = sizeof(struct sctp_sack_info);
2052			}
2053			break;
2054		}
2055	case SCTP_GET_SNDBUF_USE:
2056		{
2057			struct sctp_sockstat *ss;
2058
2059			SCTP_CHECK_AND_CAST(ss, optval, struct sctp_sockstat, *optsize);
2060			SCTP_FIND_STCB(inp, stcb, ss->ss_assoc_id);
2061
2062			if (stcb) {
2063				ss->ss_total_sndbuf = stcb->asoc.total_output_queue_size;
2064				ss->ss_total_recv_buf = (stcb->asoc.size_on_reasm_queue +
2065				    stcb->asoc.size_on_all_streams);
2066				SCTP_TCB_UNLOCK(stcb);
2067				*optsize = sizeof(struct sctp_sockstat);
2068			} else {
2069				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
2070				error = ENOTCONN;
2071			}
2072			break;
2073		}
2074	case SCTP_MAX_BURST:
2075		{
2076			struct sctp_assoc_value *av;
2077
2078			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2079			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2080
2081			if (stcb) {
2082				av->assoc_value = stcb->asoc.max_burst;
2083				SCTP_TCB_UNLOCK(stcb);
2084			} else {
2085				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2086				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2087				    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
2088					SCTP_INP_RLOCK(inp);
2089					av->assoc_value = inp->sctp_ep.max_burst;
2090					SCTP_INP_RUNLOCK(inp);
2091				} else {
2092					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2093					error = EINVAL;
2094				}
2095			}
2096			if (error == 0) {
2097				*optsize = sizeof(struct sctp_assoc_value);
2098			}
2099			break;
2100		}
2101	case SCTP_MAXSEG:
2102		{
2103			struct sctp_assoc_value *av;
2104			int ovh;
2105
2106			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2107			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2108
2109			if (stcb) {
2110				av->assoc_value = sctp_get_frag_point(stcb, &stcb->asoc);
2111				SCTP_TCB_UNLOCK(stcb);
2112			} else {
2113				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2114				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2115				    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
2116					SCTP_INP_RLOCK(inp);
2117					if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
2118						ovh = SCTP_MED_OVERHEAD;
2119					} else {
2120						ovh = SCTP_MED_V4_OVERHEAD;
2121					}
2122					if (inp->sctp_frag_point >= SCTP_DEFAULT_MAXSEGMENT)
2123						av->assoc_value = 0;
2124					else
2125						av->assoc_value = inp->sctp_frag_point - ovh;
2126					SCTP_INP_RUNLOCK(inp);
2127				} else {
2128					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2129					error = EINVAL;
2130				}
2131			}
2132			if (error == 0) {
2133				*optsize = sizeof(struct sctp_assoc_value);
2134			}
2135			break;
2136		}
2137	case SCTP_GET_STAT_LOG:
2138		error = sctp_fill_stat_log(optval, optsize);
2139		break;
2140	case SCTP_EVENTS:
2141		{
2142			struct sctp_event_subscribe *events;
2143
2144			SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, *optsize);
2145			memset(events, 0, sizeof(struct sctp_event_subscribe));
2146			SCTP_INP_RLOCK(inp);
2147			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT))
2148				events->sctp_data_io_event = 1;
2149
2150			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT))
2151				events->sctp_association_event = 1;
2152
2153			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVPADDREVNT))
2154				events->sctp_address_event = 1;
2155
2156			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT))
2157				events->sctp_send_failure_event = 1;
2158
2159			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVPEERERR))
2160				events->sctp_peer_error_event = 1;
2161
2162			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT))
2163				events->sctp_shutdown_event = 1;
2164
2165			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT))
2166				events->sctp_partial_delivery_event = 1;
2167
2168			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT))
2169				events->sctp_adaptation_layer_event = 1;
2170
2171			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT))
2172				events->sctp_authentication_event = 1;
2173
2174			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT))
2175				events->sctp_sender_dry_event = 1;
2176
2177			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT))
2178				events->sctp_stream_reset_event = 1;
2179			SCTP_INP_RUNLOCK(inp);
2180			*optsize = sizeof(struct sctp_event_subscribe);
2181			break;
2182		}
2183	case SCTP_ADAPTATION_LAYER:
2184		{
2185			uint32_t *value;
2186
2187			SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2188
2189			SCTP_INP_RLOCK(inp);
2190			*value = inp->sctp_ep.adaptation_layer_indicator;
2191			SCTP_INP_RUNLOCK(inp);
2192			*optsize = sizeof(uint32_t);
2193			break;
2194		}
2195	case SCTP_SET_INITIAL_DBG_SEQ:
2196		{
2197			uint32_t *value;
2198
2199			SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2200			SCTP_INP_RLOCK(inp);
2201			*value = inp->sctp_ep.initial_sequence_debug;
2202			SCTP_INP_RUNLOCK(inp);
2203			*optsize = sizeof(uint32_t);
2204			break;
2205		}
2206	case SCTP_GET_LOCAL_ADDR_SIZE:
2207		{
2208			uint32_t *value;
2209
2210			SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2211			SCTP_INP_RLOCK(inp);
2212			*value = sctp_count_max_addresses(inp);
2213			SCTP_INP_RUNLOCK(inp);
2214			*optsize = sizeof(uint32_t);
2215			break;
2216		}
2217	case SCTP_GET_REMOTE_ADDR_SIZE:
2218		{
2219			uint32_t *value;
2220			size_t size;
2221			struct sctp_nets *net;
2222
2223			SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2224			/* FIXME MT: change to sctp_assoc_value? */
2225			SCTP_FIND_STCB(inp, stcb, (sctp_assoc_t) * value);
2226
2227			if (stcb) {
2228				size = 0;
2229				/* Count the sizes */
2230				TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
2231					if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
2232						size += sizeof(struct sockaddr_in6);
2233					} else {
2234						switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) {
2235#ifdef INET
2236						case AF_INET:
2237							size += sizeof(struct sockaddr_in);
2238							break;
2239#endif
2240#ifdef INET6
2241						case AF_INET6:
2242							size += sizeof(struct sockaddr_in6);
2243							break;
2244#endif
2245						default:
2246							break;
2247						}
2248					}
2249				}
2250				SCTP_TCB_UNLOCK(stcb);
2251				*value = (uint32_t) size;
2252				*optsize = sizeof(uint32_t);
2253			} else {
2254				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
2255				error = ENOTCONN;
2256			}
2257			break;
2258		}
2259	case SCTP_GET_PEER_ADDRESSES:
2260		/*
2261		 * Get the address information, an array is passed in to
2262		 * fill up we pack it.
2263		 */
2264		{
2265			size_t cpsz, left;
2266			struct sockaddr_storage *sas;
2267			struct sctp_nets *net;
2268			struct sctp_getaddresses *saddr;
2269
2270			SCTP_CHECK_AND_CAST(saddr, optval, struct sctp_getaddresses, *optsize);
2271			SCTP_FIND_STCB(inp, stcb, saddr->sget_assoc_id);
2272
2273			if (stcb) {
2274				left = (*optsize) - sizeof(struct sctp_getaddresses);
2275				*optsize = sizeof(struct sctp_getaddresses);
2276				sas = (struct sockaddr_storage *)&saddr->addr[0];
2277
2278				TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
2279					if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
2280						cpsz = sizeof(struct sockaddr_in6);
2281					} else {
2282						switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) {
2283#ifdef INET
2284						case AF_INET:
2285							cpsz = sizeof(struct sockaddr_in);
2286							break;
2287#endif
2288#ifdef INET6
2289						case AF_INET6:
2290							cpsz = sizeof(struct sockaddr_in6);
2291							break;
2292#endif
2293						default:
2294							cpsz = 0;
2295							break;
2296						}
2297					}
2298					if (cpsz == 0) {
2299						break;
2300					}
2301					if (left < cpsz) {
2302						/* not enough room. */
2303						break;
2304					}
2305#if defined(INET) && defined(INET6)
2306					if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) &&
2307					    (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET)) {
2308						/* Must map the address */
2309						in6_sin_2_v4mapsin6((struct sockaddr_in *)&net->ro._l_addr,
2310						    (struct sockaddr_in6 *)sas);
2311					} else {
2312#endif
2313						memcpy(sas, &net->ro._l_addr, cpsz);
2314#if defined(INET) && defined(INET6)
2315					}
2316#endif
2317					((struct sockaddr_in *)sas)->sin_port = stcb->rport;
2318
2319					sas = (struct sockaddr_storage *)((caddr_t)sas + cpsz);
2320					left -= cpsz;
2321					*optsize += cpsz;
2322				}
2323				SCTP_TCB_UNLOCK(stcb);
2324			} else {
2325				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
2326				error = ENOENT;
2327			}
2328			break;
2329		}
2330	case SCTP_GET_LOCAL_ADDRESSES:
2331		{
2332			size_t limit, actual;
2333			struct sockaddr_storage *sas;
2334			struct sctp_getaddresses *saddr;
2335
2336			SCTP_CHECK_AND_CAST(saddr, optval, struct sctp_getaddresses, *optsize);
2337			SCTP_FIND_STCB(inp, stcb, saddr->sget_assoc_id);
2338
2339			sas = (struct sockaddr_storage *)&saddr->addr[0];
2340			limit = *optsize - sizeof(sctp_assoc_t);
2341			actual = sctp_fill_up_addresses(inp, stcb, limit, sas);
2342			if (stcb) {
2343				SCTP_TCB_UNLOCK(stcb);
2344			}
2345			*optsize = sizeof(struct sockaddr_storage) + actual;
2346			break;
2347		}
2348	case SCTP_PEER_ADDR_PARAMS:
2349		{
2350			struct sctp_paddrparams *paddrp;
2351			struct sctp_nets *net;
2352
2353			SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, *optsize);
2354			SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
2355
2356			net = NULL;
2357			if (stcb) {
2358				net = sctp_findnet(stcb, (struct sockaddr *)&paddrp->spp_address);
2359			} else {
2360				/*
2361				 * We increment here since
2362				 * sctp_findassociation_ep_addr() wil do a
2363				 * decrement if it finds the stcb as long as
2364				 * the locked tcb (last argument) is NOT a
2365				 * TCB.. aka NULL.
2366				 */
2367				SCTP_INP_INCR_REF(inp);
2368				stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&paddrp->spp_address, &net, NULL, NULL);
2369				if (stcb == NULL) {
2370					SCTP_INP_DECR_REF(inp);
2371				}
2372			}
2373			if (stcb && (net == NULL)) {
2374				struct sockaddr *sa;
2375
2376				sa = (struct sockaddr *)&paddrp->spp_address;
2377#ifdef INET
2378				if (sa->sa_family == AF_INET) {
2379					struct sockaddr_in *sin;
2380
2381					sin = (struct sockaddr_in *)sa;
2382					if (sin->sin_addr.s_addr) {
2383						error = EINVAL;
2384						SCTP_TCB_UNLOCK(stcb);
2385						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2386						break;
2387					}
2388				} else
2389#endif
2390#ifdef INET6
2391				if (sa->sa_family == AF_INET6) {
2392					struct sockaddr_in6 *sin6;
2393
2394					sin6 = (struct sockaddr_in6 *)sa;
2395					if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
2396						error = EINVAL;
2397						SCTP_TCB_UNLOCK(stcb);
2398						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2399						break;
2400					}
2401				} else
2402#endif
2403				{
2404					error = EAFNOSUPPORT;
2405					SCTP_TCB_UNLOCK(stcb);
2406					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2407					break;
2408				}
2409			}
2410			if (stcb) {
2411				/* Applies to the specific association */
2412				paddrp->spp_flags = 0;
2413				if (net) {
2414					int ovh;
2415
2416					if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
2417						ovh = SCTP_MED_OVERHEAD;
2418					} else {
2419						ovh = SCTP_MED_V4_OVERHEAD;
2420					}
2421
2422					paddrp->spp_hbinterval = net->heart_beat_delay;
2423					paddrp->spp_pathmaxrxt = net->failure_threshold;
2424					paddrp->spp_pathmtu = net->mtu - ovh;
2425					/* get flags for HB */
2426					if (net->dest_state & SCTP_ADDR_NOHB) {
2427						paddrp->spp_flags |= SPP_HB_DISABLE;
2428					} else {
2429						paddrp->spp_flags |= SPP_HB_ENABLE;
2430					}
2431					/* get flags for PMTU */
2432					if (net->dest_state & SCTP_ADDR_NO_PMTUD) {
2433						paddrp->spp_flags |= SPP_PMTUD_ENABLE;
2434					} else {
2435						paddrp->spp_flags |= SPP_PMTUD_DISABLE;
2436					}
2437					if (net->dscp & 0x01) {
2438						paddrp->spp_dscp = net->dscp & 0xfc;
2439						paddrp->spp_flags |= SPP_DSCP;
2440					}
2441#ifdef INET6
2442					if ((net->ro._l_addr.sa.sa_family == AF_INET6) &&
2443					    (net->flowlabel & 0x80000000)) {
2444						paddrp->spp_ipv6_flowlabel = net->flowlabel & 0x000fffff;
2445						paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
2446					}
2447#endif
2448				} else {
2449					/*
2450					 * No destination so return default
2451					 * value
2452					 */
2453					paddrp->spp_pathmaxrxt = stcb->asoc.def_net_failure;
2454					paddrp->spp_pathmtu = sctp_get_frag_point(stcb, &stcb->asoc);
2455					if (stcb->asoc.default_dscp & 0x01) {
2456						paddrp->spp_dscp = stcb->asoc.default_dscp & 0xfc;
2457						paddrp->spp_flags |= SPP_DSCP;
2458					}
2459#ifdef INET6
2460					if (stcb->asoc.default_flowlabel & 0x80000000) {
2461						paddrp->spp_ipv6_flowlabel = stcb->asoc.default_flowlabel & 0x000fffff;
2462						paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
2463					}
2464#endif
2465					/* default settings should be these */
2466					if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
2467						paddrp->spp_flags |= SPP_HB_DISABLE;
2468					} else {
2469						paddrp->spp_flags |= SPP_HB_ENABLE;
2470					}
2471					if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD)) {
2472						paddrp->spp_flags |= SPP_PMTUD_DISABLE;
2473					} else {
2474						paddrp->spp_flags |= SPP_PMTUD_ENABLE;
2475					}
2476					paddrp->spp_hbinterval = stcb->asoc.heart_beat_delay;
2477				}
2478				paddrp->spp_assoc_id = sctp_get_associd(stcb);
2479				SCTP_TCB_UNLOCK(stcb);
2480			} else {
2481				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2482				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2483				    (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC)) {
2484					/* Use endpoint defaults */
2485					SCTP_INP_RLOCK(inp);
2486					paddrp->spp_pathmaxrxt = inp->sctp_ep.def_net_failure;
2487					paddrp->spp_hbinterval = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]);
2488					paddrp->spp_assoc_id = SCTP_FUTURE_ASSOC;
2489					/* get inp's default */
2490					if (inp->sctp_ep.default_dscp & 0x01) {
2491						paddrp->spp_dscp = inp->sctp_ep.default_dscp & 0xfc;
2492						paddrp->spp_flags |= SPP_DSCP;
2493					}
2494#ifdef INET6
2495					if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
2496					    (inp->sctp_ep.default_flowlabel & 0x80000000)) {
2497						paddrp->spp_ipv6_flowlabel = inp->sctp_ep.default_flowlabel & 0x000fffff;
2498						paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
2499					}
2500#endif
2501					/* can't return this */
2502					paddrp->spp_pathmtu = 0;
2503
2504					if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
2505						paddrp->spp_flags |= SPP_HB_ENABLE;
2506					} else {
2507						paddrp->spp_flags |= SPP_HB_DISABLE;
2508					}
2509					if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD)) {
2510						paddrp->spp_flags |= SPP_PMTUD_ENABLE;
2511					} else {
2512						paddrp->spp_flags |= SPP_PMTUD_DISABLE;
2513					}
2514					SCTP_INP_RUNLOCK(inp);
2515				} else {
2516					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2517					error = EINVAL;
2518				}
2519			}
2520			if (error == 0) {
2521				*optsize = sizeof(struct sctp_paddrparams);
2522			}
2523			break;
2524		}
2525	case SCTP_GET_PEER_ADDR_INFO:
2526		{
2527			struct sctp_paddrinfo *paddri;
2528			struct sctp_nets *net;
2529
2530			SCTP_CHECK_AND_CAST(paddri, optval, struct sctp_paddrinfo, *optsize);
2531			SCTP_FIND_STCB(inp, stcb, paddri->spinfo_assoc_id);
2532
2533			net = NULL;
2534			if (stcb) {
2535				net = sctp_findnet(stcb, (struct sockaddr *)&paddri->spinfo_address);
2536			} else {
2537				/*
2538				 * We increment here since
2539				 * sctp_findassociation_ep_addr() wil do a
2540				 * decrement if it finds the stcb as long as
2541				 * the locked tcb (last argument) is NOT a
2542				 * TCB.. aka NULL.
2543				 */
2544				SCTP_INP_INCR_REF(inp);
2545				stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&paddri->spinfo_address, &net, NULL, NULL);
2546				if (stcb == NULL) {
2547					SCTP_INP_DECR_REF(inp);
2548				}
2549			}
2550
2551			if ((stcb) && (net)) {
2552				if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
2553					/* It's unconfirmed */
2554					paddri->spinfo_state = SCTP_UNCONFIRMED;
2555				} else if (net->dest_state & SCTP_ADDR_REACHABLE) {
2556					/* It's active */
2557					paddri->spinfo_state = SCTP_ACTIVE;
2558				} else {
2559					/* It's inactive */
2560					paddri->spinfo_state = SCTP_INACTIVE;
2561				}
2562				paddri->spinfo_cwnd = net->cwnd;
2563				paddri->spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT;
2564				paddri->spinfo_rto = net->RTO;
2565				paddri->spinfo_assoc_id = sctp_get_associd(stcb);
2566				paddri->spinfo_mtu = net->mtu;
2567				SCTP_TCB_UNLOCK(stcb);
2568				*optsize = sizeof(struct sctp_paddrinfo);
2569			} else {
2570				if (stcb) {
2571					SCTP_TCB_UNLOCK(stcb);
2572				}
2573				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
2574				error = ENOENT;
2575			}
2576			break;
2577		}
2578	case SCTP_PCB_STATUS:
2579		{
2580			struct sctp_pcbinfo *spcb;
2581
2582			SCTP_CHECK_AND_CAST(spcb, optval, struct sctp_pcbinfo, *optsize);
2583			sctp_fill_pcbinfo(spcb);
2584			*optsize = sizeof(struct sctp_pcbinfo);
2585			break;
2586		}
2587	case SCTP_STATUS:
2588		{
2589			struct sctp_nets *net;
2590			struct sctp_status *sstat;
2591
2592			SCTP_CHECK_AND_CAST(sstat, optval, struct sctp_status, *optsize);
2593			SCTP_FIND_STCB(inp, stcb, sstat->sstat_assoc_id);
2594
2595			if (stcb == NULL) {
2596				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2597				error = EINVAL;
2598				break;
2599			}
2600			/*
2601			 * I think passing the state is fine since
2602			 * sctp_constants.h will be available to the user
2603			 * land.
2604			 */
2605			sstat->sstat_state = stcb->asoc.state;
2606			sstat->sstat_assoc_id = sctp_get_associd(stcb);
2607			sstat->sstat_rwnd = stcb->asoc.peers_rwnd;
2608			sstat->sstat_unackdata = stcb->asoc.sent_queue_cnt;
2609			/*
2610			 * We can't include chunks that have been passed to
2611			 * the socket layer. Only things in queue.
2612			 */
2613			sstat->sstat_penddata = (stcb->asoc.cnt_on_reasm_queue +
2614			    stcb->asoc.cnt_on_all_streams);
2615
2616
2617			sstat->sstat_instrms = stcb->asoc.streamincnt;
2618			sstat->sstat_outstrms = stcb->asoc.streamoutcnt;
2619			sstat->sstat_fragmentation_point = sctp_get_frag_point(stcb, &stcb->asoc);
2620			memcpy(&sstat->sstat_primary.spinfo_address,
2621			    &stcb->asoc.primary_destination->ro._l_addr,
2622			    ((struct sockaddr *)(&stcb->asoc.primary_destination->ro._l_addr))->sa_len);
2623			net = stcb->asoc.primary_destination;
2624			((struct sockaddr_in *)&sstat->sstat_primary.spinfo_address)->sin_port = stcb->rport;
2625			/*
2626			 * Again the user can get info from sctp_constants.h
2627			 * for what the state of the network is.
2628			 */
2629			if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
2630				/* It's unconfirmed */
2631				sstat->sstat_primary.spinfo_state = SCTP_UNCONFIRMED;
2632			} else if (net->dest_state & SCTP_ADDR_REACHABLE) {
2633				/* It's active */
2634				sstat->sstat_primary.spinfo_state = SCTP_ACTIVE;
2635			} else {
2636				/* It's inactive */
2637				sstat->sstat_primary.spinfo_state = SCTP_INACTIVE;
2638			}
2639			sstat->sstat_primary.spinfo_cwnd = net->cwnd;
2640			sstat->sstat_primary.spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT;
2641			sstat->sstat_primary.spinfo_rto = net->RTO;
2642			sstat->sstat_primary.spinfo_mtu = net->mtu;
2643			sstat->sstat_primary.spinfo_assoc_id = sctp_get_associd(stcb);
2644			SCTP_TCB_UNLOCK(stcb);
2645			*optsize = sizeof(struct sctp_status);
2646			break;
2647		}
2648	case SCTP_RTOINFO:
2649		{
2650			struct sctp_rtoinfo *srto;
2651
2652			SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, *optsize);
2653			SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
2654
2655			if (stcb) {
2656				srto->srto_initial = stcb->asoc.initial_rto;
2657				srto->srto_max = stcb->asoc.maxrto;
2658				srto->srto_min = stcb->asoc.minrto;
2659				SCTP_TCB_UNLOCK(stcb);
2660			} else {
2661				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2662				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2663				    (srto->srto_assoc_id == SCTP_FUTURE_ASSOC)) {
2664					SCTP_INP_RLOCK(inp);
2665					srto->srto_initial = inp->sctp_ep.initial_rto;
2666					srto->srto_max = inp->sctp_ep.sctp_maxrto;
2667					srto->srto_min = inp->sctp_ep.sctp_minrto;
2668					SCTP_INP_RUNLOCK(inp);
2669				} else {
2670					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2671					error = EINVAL;
2672				}
2673			}
2674			if (error == 0) {
2675				*optsize = sizeof(struct sctp_rtoinfo);
2676			}
2677			break;
2678		}
2679	case SCTP_TIMEOUTS:
2680		{
2681			struct sctp_timeouts *stimo;
2682
2683			SCTP_CHECK_AND_CAST(stimo, optval, struct sctp_timeouts, *optsize);
2684			SCTP_FIND_STCB(inp, stcb, stimo->stimo_assoc_id);
2685
2686			if (stcb) {
2687				stimo->stimo_init = stcb->asoc.timoinit;
2688				stimo->stimo_data = stcb->asoc.timodata;
2689				stimo->stimo_sack = stcb->asoc.timosack;
2690				stimo->stimo_shutdown = stcb->asoc.timoshutdown;
2691				stimo->stimo_heartbeat = stcb->asoc.timoheartbeat;
2692				stimo->stimo_cookie = stcb->asoc.timocookie;
2693				stimo->stimo_shutdownack = stcb->asoc.timoshutdownack;
2694				SCTP_TCB_UNLOCK(stcb);
2695				*optsize = sizeof(struct sctp_timeouts);
2696			} else {
2697				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2698				error = EINVAL;
2699			}
2700			break;
2701		}
2702	case SCTP_ASSOCINFO:
2703		{
2704			struct sctp_assocparams *sasoc;
2705
2706			SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, *optsize);
2707			SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
2708
2709			if (stcb) {
2710				sasoc->sasoc_cookie_life = TICKS_TO_MSEC(stcb->asoc.cookie_life);
2711				sasoc->sasoc_asocmaxrxt = stcb->asoc.max_send_times;
2712				sasoc->sasoc_number_peer_destinations = stcb->asoc.numnets;
2713				sasoc->sasoc_peer_rwnd = stcb->asoc.peers_rwnd;
2714				sasoc->sasoc_local_rwnd = stcb->asoc.my_rwnd;
2715				SCTP_TCB_UNLOCK(stcb);
2716			} else {
2717				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2718				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2719				    (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC)) {
2720					SCTP_INP_RLOCK(inp);
2721					sasoc->sasoc_cookie_life = TICKS_TO_MSEC(inp->sctp_ep.def_cookie_life);
2722					sasoc->sasoc_asocmaxrxt = inp->sctp_ep.max_send_times;
2723					sasoc->sasoc_number_peer_destinations = 0;
2724					sasoc->sasoc_peer_rwnd = 0;
2725					sasoc->sasoc_local_rwnd = sbspace(&inp->sctp_socket->so_rcv);
2726					SCTP_INP_RUNLOCK(inp);
2727				} else {
2728					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2729					error = EINVAL;
2730				}
2731			}
2732			if (error == 0) {
2733				*optsize = sizeof(struct sctp_assocparams);
2734			}
2735			break;
2736		}
2737	case SCTP_DEFAULT_SEND_PARAM:
2738		{
2739			struct sctp_sndrcvinfo *s_info;
2740
2741			SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, *optsize);
2742			SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
2743
2744			if (stcb) {
2745				memcpy(s_info, &stcb->asoc.def_send, sizeof(stcb->asoc.def_send));
2746				SCTP_TCB_UNLOCK(stcb);
2747			} else {
2748				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2749				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2750				    (s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC)) {
2751					SCTP_INP_RLOCK(inp);
2752					memcpy(s_info, &inp->def_send, sizeof(inp->def_send));
2753					SCTP_INP_RUNLOCK(inp);
2754				} else {
2755					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2756					error = EINVAL;
2757				}
2758			}
2759			if (error == 0) {
2760				*optsize = sizeof(struct sctp_sndrcvinfo);
2761			}
2762			break;
2763		}
2764	case SCTP_INITMSG:
2765		{
2766			struct sctp_initmsg *sinit;
2767
2768			SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, *optsize);
2769			SCTP_INP_RLOCK(inp);
2770			sinit->sinit_num_ostreams = inp->sctp_ep.pre_open_stream_count;
2771			sinit->sinit_max_instreams = inp->sctp_ep.max_open_streams_intome;
2772			sinit->sinit_max_attempts = inp->sctp_ep.max_init_times;
2773			sinit->sinit_max_init_timeo = inp->sctp_ep.initial_init_rto_max;
2774			SCTP_INP_RUNLOCK(inp);
2775			*optsize = sizeof(struct sctp_initmsg);
2776			break;
2777		}
2778	case SCTP_PRIMARY_ADDR:
2779		/* we allow a "get" operation on this */
2780		{
2781			struct sctp_setprim *ssp;
2782
2783			SCTP_CHECK_AND_CAST(ssp, optval, struct sctp_setprim, *optsize);
2784			SCTP_FIND_STCB(inp, stcb, ssp->ssp_assoc_id);
2785
2786			if (stcb) {
2787				/* simply copy out the sockaddr_storage... */
2788				int len;
2789
2790				len = *optsize;
2791				if (len > stcb->asoc.primary_destination->ro._l_addr.sa.sa_len)
2792					len = stcb->asoc.primary_destination->ro._l_addr.sa.sa_len;
2793
2794				memcpy(&ssp->ssp_addr,
2795				    &stcb->asoc.primary_destination->ro._l_addr,
2796				    len);
2797				SCTP_TCB_UNLOCK(stcb);
2798				*optsize = sizeof(struct sctp_setprim);
2799			} else {
2800				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2801				error = EINVAL;
2802			}
2803			break;
2804		}
2805	case SCTP_HMAC_IDENT:
2806		{
2807			struct sctp_hmacalgo *shmac;
2808			sctp_hmaclist_t *hmaclist;
2809			uint32_t size;
2810			int i;
2811
2812			SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, *optsize);
2813
2814			SCTP_INP_RLOCK(inp);
2815			hmaclist = inp->sctp_ep.local_hmacs;
2816			if (hmaclist == NULL) {
2817				/* no HMACs to return */
2818				*optsize = sizeof(*shmac);
2819				SCTP_INP_RUNLOCK(inp);
2820				break;
2821			}
2822			/* is there room for all of the hmac ids? */
2823			size = sizeof(*shmac) + (hmaclist->num_algo *
2824			    sizeof(shmac->shmac_idents[0]));
2825			if ((size_t)(*optsize) < size) {
2826				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2827				error = EINVAL;
2828				SCTP_INP_RUNLOCK(inp);
2829				break;
2830			}
2831			/* copy in the list */
2832			shmac->shmac_number_of_idents = hmaclist->num_algo;
2833			for (i = 0; i < hmaclist->num_algo; i++) {
2834				shmac->shmac_idents[i] = hmaclist->hmac[i];
2835			}
2836			SCTP_INP_RUNLOCK(inp);
2837			*optsize = size;
2838			break;
2839		}
2840	case SCTP_AUTH_ACTIVE_KEY:
2841		{
2842			struct sctp_authkeyid *scact;
2843
2844			SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, *optsize);
2845			SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id);
2846
2847			if (stcb) {
2848				/* get the active key on the assoc */
2849				scact->scact_keynumber = stcb->asoc.authinfo.active_keyid;
2850				SCTP_TCB_UNLOCK(stcb);
2851			} else {
2852				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2853				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2854				    (scact->scact_assoc_id == SCTP_FUTURE_ASSOC)) {
2855					/* get the endpoint active key */
2856					SCTP_INP_RLOCK(inp);
2857					scact->scact_keynumber = inp->sctp_ep.default_keyid;
2858					SCTP_INP_RUNLOCK(inp);
2859				} else {
2860					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2861					error = EINVAL;
2862				}
2863			}
2864			if (error == 0) {
2865				*optsize = sizeof(struct sctp_authkeyid);
2866			}
2867			break;
2868		}
2869	case SCTP_LOCAL_AUTH_CHUNKS:
2870		{
2871			struct sctp_authchunks *sac;
2872			sctp_auth_chklist_t *chklist = NULL;
2873			size_t size = 0;
2874
2875			SCTP_CHECK_AND_CAST(sac, optval, struct sctp_authchunks, *optsize);
2876			SCTP_FIND_STCB(inp, stcb, sac->gauth_assoc_id);
2877
2878			if (stcb) {
2879				/* get off the assoc */
2880				chklist = stcb->asoc.local_auth_chunks;
2881				/* is there enough space? */
2882				size = sctp_auth_get_chklist_size(chklist);
2883				if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
2884					error = EINVAL;
2885					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2886				} else {
2887					/* copy in the chunks */
2888					(void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
2889					*optsize = sizeof(struct sctp_authchunks) + size;
2890				}
2891				SCTP_TCB_UNLOCK(stcb);
2892			} else {
2893				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2894				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2895				    (sac->gauth_assoc_id == SCTP_FUTURE_ASSOC)) {
2896					/* get off the endpoint */
2897					SCTP_INP_RLOCK(inp);
2898					chklist = inp->sctp_ep.local_auth_chunks;
2899					/* is there enough space? */
2900					size = sctp_auth_get_chklist_size(chklist);
2901					if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
2902						error = EINVAL;
2903						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2904					} else {
2905						/* copy in the chunks */
2906						(void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
2907						*optsize = sizeof(struct sctp_authchunks) + size;
2908					}
2909					SCTP_INP_RUNLOCK(inp);
2910				} else {
2911					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2912					error = EINVAL;
2913				}
2914			}
2915			break;
2916		}
2917	case SCTP_PEER_AUTH_CHUNKS:
2918		{
2919			struct sctp_authchunks *sac;
2920			sctp_auth_chklist_t *chklist = NULL;
2921			size_t size = 0;
2922
2923			SCTP_CHECK_AND_CAST(sac, optval, struct sctp_authchunks, *optsize);
2924			SCTP_FIND_STCB(inp, stcb, sac->gauth_assoc_id);
2925
2926			if (stcb) {
2927				/* get off the assoc */
2928				chklist = stcb->asoc.peer_auth_chunks;
2929				/* is there enough space? */
2930				size = sctp_auth_get_chklist_size(chklist);
2931				if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
2932					error = EINVAL;
2933					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2934				} else {
2935					/* copy in the chunks */
2936					(void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
2937					*optsize = sizeof(struct sctp_authchunks) + size;
2938				}
2939				SCTP_TCB_UNLOCK(stcb);
2940			} else {
2941				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
2942				error = ENOENT;
2943			}
2944			break;
2945		}
2946	case SCTP_EVENT:
2947		{
2948			struct sctp_event *event;
2949			uint32_t event_type;
2950
2951			SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, *optsize);
2952			SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
2953
2954			switch (event->se_type) {
2955			case SCTP_ASSOC_CHANGE:
2956				event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
2957				break;
2958			case SCTP_PEER_ADDR_CHANGE:
2959				event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
2960				break;
2961			case SCTP_REMOTE_ERROR:
2962				event_type = SCTP_PCB_FLAGS_RECVPEERERR;
2963				break;
2964			case SCTP_SEND_FAILED:
2965				event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
2966				break;
2967			case SCTP_SHUTDOWN_EVENT:
2968				event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
2969				break;
2970			case SCTP_ADAPTATION_INDICATION:
2971				event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
2972				break;
2973			case SCTP_PARTIAL_DELIVERY_EVENT:
2974				event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
2975				break;
2976			case SCTP_AUTHENTICATION_EVENT:
2977				event_type = SCTP_PCB_FLAGS_AUTHEVNT;
2978				break;
2979			case SCTP_STREAM_RESET_EVENT:
2980				event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
2981				break;
2982			case SCTP_SENDER_DRY_EVENT:
2983				event_type = SCTP_PCB_FLAGS_DRYEVNT;
2984				break;
2985			case SCTP_NOTIFICATIONS_STOPPED_EVENT:
2986				event_type = 0;
2987				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
2988				error = ENOTSUP;
2989				break;
2990			default:
2991				event_type = 0;
2992				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2993				error = EINVAL;
2994				break;
2995			}
2996			if (event_type > 0) {
2997				if (stcb) {
2998					event->se_on = sctp_stcb_is_feature_on(inp, stcb, event_type);
2999					SCTP_TCB_UNLOCK(stcb);
3000				} else {
3001					if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3002					    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3003					    (event->se_assoc_id == SCTP_FUTURE_ASSOC)) {
3004						SCTP_INP_RLOCK(inp);
3005						event->se_on = sctp_is_feature_on(inp, event_type);
3006						SCTP_INP_RUNLOCK(inp);
3007					} else {
3008						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3009						error = EINVAL;
3010					}
3011				}
3012			}
3013			if (error == 0) {
3014				*optsize = sizeof(struct sctp_event);
3015			}
3016			break;
3017		}
3018	case SCTP_RECVRCVINFO:
3019		{
3020			int onoff;
3021
3022			if (*optsize < sizeof(int)) {
3023				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3024				error = EINVAL;
3025			} else {
3026				SCTP_INP_RUNLOCK(inp);
3027				onoff = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
3028				SCTP_INP_RUNLOCK(inp);
3029			}
3030			if (error == 0) {
3031				/* return the option value */
3032				*(int *)optval = onoff;
3033				*optsize = sizeof(int);
3034			}
3035			break;
3036		}
3037	case SCTP_RECVNXTINFO:
3038		{
3039			int onoff;
3040
3041			if (*optsize < sizeof(int)) {
3042				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3043				error = EINVAL;
3044			} else {
3045				SCTP_INP_RUNLOCK(inp);
3046				onoff = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
3047				SCTP_INP_RUNLOCK(inp);
3048			}
3049			if (error == 0) {
3050				/* return the option value */
3051				*(int *)optval = onoff;
3052				*optsize = sizeof(int);
3053			}
3054			break;
3055		}
3056	case SCTP_DEFAULT_SNDINFO:
3057		{
3058			struct sctp_sndinfo *info;
3059
3060			SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, *optsize);
3061			SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
3062
3063			if (stcb) {
3064				info->snd_sid = stcb->asoc.def_send.sinfo_stream;
3065				info->snd_flags = stcb->asoc.def_send.sinfo_flags;
3066				info->snd_flags &= 0xfff0;
3067				info->snd_ppid = stcb->asoc.def_send.sinfo_ppid;
3068				info->snd_context = stcb->asoc.def_send.sinfo_context;
3069				SCTP_TCB_UNLOCK(stcb);
3070			} else {
3071				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3072				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3073				    (info->snd_assoc_id == SCTP_FUTURE_ASSOC)) {
3074					SCTP_INP_RLOCK(inp);
3075					info->snd_sid = inp->def_send.sinfo_stream;
3076					info->snd_flags = inp->def_send.sinfo_flags;
3077					info->snd_flags &= 0xfff0;
3078					info->snd_ppid = inp->def_send.sinfo_ppid;
3079					info->snd_context = inp->def_send.sinfo_context;
3080					SCTP_INP_RUNLOCK(inp);
3081				} else {
3082					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3083					error = EINVAL;
3084				}
3085			}
3086			if (error == 0) {
3087				*optsize = sizeof(struct sctp_sndinfo);
3088			}
3089			break;
3090		}
3091	case SCTP_DEFAULT_PRINFO:
3092		{
3093			struct sctp_default_prinfo *info;
3094
3095			SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, *optsize);
3096			SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
3097
3098			if (stcb) {
3099				info->pr_policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
3100				info->pr_value = stcb->asoc.def_send.sinfo_timetolive;
3101				SCTP_TCB_UNLOCK(stcb);
3102			} else {
3103				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3104				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3105				    (info->pr_assoc_id == SCTP_FUTURE_ASSOC)) {
3106					SCTP_INP_RLOCK(inp);
3107					info->pr_policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
3108					info->pr_value = inp->def_send.sinfo_timetolive;
3109					SCTP_INP_RUNLOCK(inp);
3110				} else {
3111					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3112					error = EINVAL;
3113				}
3114			}
3115			if (error == 0) {
3116				*optsize = sizeof(struct sctp_default_prinfo);
3117			}
3118			break;
3119		}
3120	case SCTP_PEER_ADDR_THLDS:
3121		{
3122			struct sctp_paddrthlds *thlds;
3123			struct sctp_nets *net;
3124
3125			SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, *optsize);
3126			SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
3127
3128			net = NULL;
3129			if (stcb) {
3130				net = sctp_findnet(stcb, (struct sockaddr *)&thlds->spt_address);
3131			} else {
3132				/*
3133				 * We increment here since
3134				 * sctp_findassociation_ep_addr() wil do a
3135				 * decrement if it finds the stcb as long as
3136				 * the locked tcb (last argument) is NOT a
3137				 * TCB.. aka NULL.
3138				 */
3139				SCTP_INP_INCR_REF(inp);
3140				stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&thlds->spt_address, &net, NULL, NULL);
3141				if (stcb == NULL) {
3142					SCTP_INP_DECR_REF(inp);
3143				}
3144			}
3145			if (stcb && (net == NULL)) {
3146				struct sockaddr *sa;
3147
3148				sa = (struct sockaddr *)&thlds->spt_address;
3149#ifdef INET
3150				if (sa->sa_family == AF_INET) {
3151					struct sockaddr_in *sin;
3152
3153					sin = (struct sockaddr_in *)sa;
3154					if (sin->sin_addr.s_addr) {
3155						error = EINVAL;
3156						SCTP_TCB_UNLOCK(stcb);
3157						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3158						break;
3159					}
3160				} else
3161#endif
3162#ifdef INET6
3163				if (sa->sa_family == AF_INET6) {
3164					struct sockaddr_in6 *sin6;
3165
3166					sin6 = (struct sockaddr_in6 *)sa;
3167					if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
3168						error = EINVAL;
3169						SCTP_TCB_UNLOCK(stcb);
3170						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3171						break;
3172					}
3173				} else
3174#endif
3175				{
3176					error = EAFNOSUPPORT;
3177					SCTP_TCB_UNLOCK(stcb);
3178					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3179					break;
3180				}
3181			}
3182			if (stcb) {
3183				if (net) {
3184					thlds->spt_pathmaxrxt = net->failure_threshold;
3185					thlds->spt_pathpfthld = net->pf_threshold;
3186				} else {
3187					thlds->spt_pathmaxrxt = stcb->asoc.def_net_failure;
3188					thlds->spt_pathpfthld = stcb->asoc.def_net_pf_threshold;
3189				}
3190				thlds->spt_assoc_id = sctp_get_associd(stcb);
3191				SCTP_TCB_UNLOCK(stcb);
3192			} else {
3193				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3194				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3195				    (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC)) {
3196					/* Use endpoint defaults */
3197					SCTP_INP_RLOCK(inp);
3198					thlds->spt_pathmaxrxt = inp->sctp_ep.def_net_failure;
3199					thlds->spt_pathpfthld = inp->sctp_ep.def_net_pf_threshold;
3200					SCTP_INP_RUNLOCK(inp);
3201				} else {
3202					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3203					error = EINVAL;
3204				}
3205			}
3206			if (error == 0) {
3207				*optsize = sizeof(struct sctp_paddrthlds);
3208			}
3209			break;
3210		}
3211	case SCTP_REMOTE_UDP_ENCAPS_PORT:
3212		{
3213			struct sctp_udpencaps *encaps;
3214			struct sctp_nets *net;
3215
3216			SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, *optsize);
3217			SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
3218
3219			if (stcb) {
3220				net = sctp_findnet(stcb, (struct sockaddr *)&encaps->sue_address);
3221			} else {
3222				/*
3223				 * We increment here since
3224				 * sctp_findassociation_ep_addr() wil do a
3225				 * decrement if it finds the stcb as long as
3226				 * the locked tcb (last argument) is NOT a
3227				 * TCB.. aka NULL.
3228				 */
3229				net = NULL;
3230				SCTP_INP_INCR_REF(inp);
3231				stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&encaps->sue_address, &net, NULL, NULL);
3232				if (stcb == NULL) {
3233					SCTP_INP_DECR_REF(inp);
3234				}
3235			}
3236			if (stcb && (net == NULL)) {
3237				struct sockaddr *sa;
3238
3239				sa = (struct sockaddr *)&encaps->sue_address;
3240#ifdef INET
3241				if (sa->sa_family == AF_INET) {
3242					struct sockaddr_in *sin;
3243
3244					sin = (struct sockaddr_in *)sa;
3245					if (sin->sin_addr.s_addr) {
3246						error = EINVAL;
3247						SCTP_TCB_UNLOCK(stcb);
3248						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3249						break;
3250					}
3251				} else
3252#endif
3253#ifdef INET6
3254				if (sa->sa_family == AF_INET6) {
3255					struct sockaddr_in6 *sin6;
3256
3257					sin6 = (struct sockaddr_in6 *)sa;
3258					if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
3259						error = EINVAL;
3260						SCTP_TCB_UNLOCK(stcb);
3261						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3262						break;
3263					}
3264				} else
3265#endif
3266				{
3267					error = EAFNOSUPPORT;
3268					SCTP_TCB_UNLOCK(stcb);
3269					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3270					break;
3271				}
3272			}
3273			if (stcb) {
3274				if (net) {
3275					encaps->sue_port = net->port;
3276				} else {
3277					encaps->sue_port = stcb->asoc.port;
3278				}
3279				SCTP_TCB_UNLOCK(stcb);
3280			} else {
3281				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3282				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3283				    (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC)) {
3284					SCTP_INP_RLOCK(inp);
3285					encaps->sue_port = inp->sctp_ep.port;
3286					SCTP_INP_RUNLOCK(inp);
3287				} else {
3288					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3289					error = EINVAL;
3290				}
3291			}
3292			if (error == 0) {
3293				*optsize = sizeof(struct sctp_paddrparams);
3294			}
3295			break;
3296		}
3297	default:
3298		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
3299		error = ENOPROTOOPT;
3300		break;
3301	}			/* end switch (sopt->sopt_name) */
3302	if (error) {
3303		*optsize = 0;
3304	}
3305	return (error);
3306}
3307
3308static int
3309sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
3310    void *p)
3311{
3312	int error, set_opt;
3313	uint32_t *mopt;
3314	struct sctp_tcb *stcb = NULL;
3315	struct sctp_inpcb *inp = NULL;
3316	uint32_t vrf_id;
3317
3318	if (optval == NULL) {
3319		SCTP_PRINTF("optval is NULL\n");
3320		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3321		return (EINVAL);
3322	}
3323	inp = (struct sctp_inpcb *)so->so_pcb;
3324	if (inp == 0) {
3325		SCTP_PRINTF("inp is NULL?\n");
3326		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3327		return EINVAL;
3328	}
3329	vrf_id = inp->def_vrf_id;
3330
3331	error = 0;
3332	switch (optname) {
3333	case SCTP_NODELAY:
3334	case SCTP_AUTOCLOSE:
3335	case SCTP_AUTO_ASCONF:
3336	case SCTP_EXPLICIT_EOR:
3337	case SCTP_DISABLE_FRAGMENTS:
3338	case SCTP_USE_EXT_RCVINFO:
3339	case SCTP_I_WANT_MAPPED_V4_ADDR:
3340		/* copy in the option value */
3341		SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
3342		set_opt = 0;
3343		if (error)
3344			break;
3345		switch (optname) {
3346		case SCTP_DISABLE_FRAGMENTS:
3347			set_opt = SCTP_PCB_FLAGS_NO_FRAGMENT;
3348			break;
3349		case SCTP_AUTO_ASCONF:
3350			/*
3351			 * NOTE: we don't really support this flag
3352			 */
3353			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
3354				/* only valid for bound all sockets */
3355				if ((SCTP_BASE_SYSCTL(sctp_auto_asconf) == 0) &&
3356				    (*mopt != 0)) {
3357					/* forbidden by admin */
3358					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EPERM);
3359					return (EPERM);
3360				}
3361				set_opt = SCTP_PCB_FLAGS_AUTO_ASCONF;
3362			} else {
3363				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3364				return (EINVAL);
3365			}
3366			break;
3367		case SCTP_EXPLICIT_EOR:
3368			set_opt = SCTP_PCB_FLAGS_EXPLICIT_EOR;
3369			break;
3370		case SCTP_USE_EXT_RCVINFO:
3371			set_opt = SCTP_PCB_FLAGS_EXT_RCVINFO;
3372			break;
3373		case SCTP_I_WANT_MAPPED_V4_ADDR:
3374			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
3375				set_opt = SCTP_PCB_FLAGS_NEEDS_MAPPED_V4;
3376			} else {
3377				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3378				return (EINVAL);
3379			}
3380			break;
3381		case SCTP_NODELAY:
3382			set_opt = SCTP_PCB_FLAGS_NODELAY;
3383			break;
3384		case SCTP_AUTOCLOSE:
3385			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3386			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
3387				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3388				return (EINVAL);
3389			}
3390			set_opt = SCTP_PCB_FLAGS_AUTOCLOSE;
3391			/*
3392			 * The value is in ticks. Note this does not effect
3393			 * old associations, only new ones.
3394			 */
3395			inp->sctp_ep.auto_close_time = SEC_TO_TICKS(*mopt);
3396			break;
3397		}
3398		SCTP_INP_WLOCK(inp);
3399		if (*mopt != 0) {
3400			sctp_feature_on(inp, set_opt);
3401		} else {
3402			sctp_feature_off(inp, set_opt);
3403		}
3404		SCTP_INP_WUNLOCK(inp);
3405		break;
3406	case SCTP_REUSE_PORT:
3407		{
3408			SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
3409			if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) {
3410				/* Can't set it after we are bound */
3411				error = EINVAL;
3412				break;
3413			}
3414			if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
3415				/* Can't do this for a 1-m socket */
3416				error = EINVAL;
3417				break;
3418			}
3419			if (optval)
3420				sctp_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE);
3421			else
3422				sctp_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE);
3423			break;
3424		}
3425	case SCTP_PARTIAL_DELIVERY_POINT:
3426		{
3427			uint32_t *value;
3428
3429			SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
3430			if (*value > SCTP_SB_LIMIT_RCV(so)) {
3431				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3432				error = EINVAL;
3433				break;
3434			}
3435			inp->partial_delivery_point = *value;
3436			break;
3437		}
3438	case SCTP_FRAGMENT_INTERLEAVE:
3439		/* not yet until we re-write sctp_recvmsg() */
3440		{
3441			uint32_t *level;
3442
3443			SCTP_CHECK_AND_CAST(level, optval, uint32_t, optsize);
3444			if (*level == SCTP_FRAG_LEVEL_2) {
3445				sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
3446				sctp_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
3447			} else if (*level == SCTP_FRAG_LEVEL_1) {
3448				sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
3449				sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
3450			} else if (*level == SCTP_FRAG_LEVEL_0) {
3451				sctp_feature_off(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
3452				sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
3453
3454			} else {
3455				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3456				error = EINVAL;
3457			}
3458			break;
3459		}
3460	case SCTP_CMT_ON_OFF:
3461		if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
3462			struct sctp_assoc_value *av;
3463
3464			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
3465			if (av->assoc_value > SCTP_CMT_MAX) {
3466				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3467				error = EINVAL;
3468				break;
3469			}
3470			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3471			if (stcb) {
3472				stcb->asoc.sctp_cmt_on_off = av->assoc_value;
3473				SCTP_TCB_UNLOCK(stcb);
3474			} else {
3475				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3476				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3477				    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
3478				    (av->assoc_id == SCTP_ALL_ASSOC)) {
3479					SCTP_INP_WLOCK(inp);
3480					inp->sctp_cmt_on_off = av->assoc_value;
3481					SCTP_INP_WUNLOCK(inp);
3482				}
3483				if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
3484				    (av->assoc_id == SCTP_ALL_ASSOC)) {
3485					SCTP_INP_RLOCK(inp);
3486					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3487						SCTP_TCB_LOCK(stcb);
3488						stcb->asoc.sctp_cmt_on_off = av->assoc_value;
3489						SCTP_TCB_UNLOCK(stcb);
3490					}
3491					SCTP_INP_RUNLOCK(inp);
3492				}
3493			}
3494		} else {
3495			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
3496			error = ENOPROTOOPT;
3497		}
3498		break;
3499	case SCTP_PLUGGABLE_CC:
3500		{
3501			struct sctp_assoc_value *av;
3502			struct sctp_nets *net;
3503
3504			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
3505			if ((av->assoc_value != SCTP_CC_RFC2581) &&
3506			    (av->assoc_value != SCTP_CC_HSTCP) &&
3507			    (av->assoc_value != SCTP_CC_HTCP) &&
3508			    (av->assoc_value != SCTP_CC_RTCC)) {
3509				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3510				error = EINVAL;
3511				break;
3512			}
3513			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3514			if (stcb) {
3515				stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
3516				stcb->asoc.congestion_control_module = av->assoc_value;
3517				if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
3518					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
3519						stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
3520					}
3521				}
3522				SCTP_TCB_UNLOCK(stcb);
3523			} else {
3524				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3525				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3526				    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
3527				    (av->assoc_id == SCTP_ALL_ASSOC)) {
3528					SCTP_INP_WLOCK(inp);
3529					inp->sctp_ep.sctp_default_cc_module = av->assoc_value;
3530					SCTP_INP_WUNLOCK(inp);
3531				}
3532				if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
3533				    (av->assoc_id == SCTP_ALL_ASSOC)) {
3534					SCTP_INP_RLOCK(inp);
3535					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3536						SCTP_TCB_LOCK(stcb);
3537						stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
3538						stcb->asoc.congestion_control_module = av->assoc_value;
3539						if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
3540							TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
3541								stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
3542							}
3543						}
3544						SCTP_TCB_UNLOCK(stcb);
3545					}
3546					SCTP_INP_RUNLOCK(inp);
3547				}
3548			}
3549			break;
3550		}
3551	case SCTP_CC_OPTION:
3552		{
3553			struct sctp_cc_option *cc_opt;
3554
3555			SCTP_CHECK_AND_CAST(cc_opt, optval, struct sctp_cc_option, optsize);
3556			SCTP_FIND_STCB(inp, stcb, cc_opt->aid_value.assoc_id);
3557			if (stcb == NULL) {
3558				if (cc_opt->aid_value.assoc_id == SCTP_CURRENT_ASSOC) {
3559					SCTP_INP_RLOCK(inp);
3560					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3561						SCTP_TCB_LOCK(stcb);
3562						if (stcb->asoc.cc_functions.sctp_cwnd_socket_option) {
3563							(*stcb->asoc.cc_functions.sctp_cwnd_socket_option) (stcb, 1, cc_opt);
3564						}
3565						SCTP_TCB_UNLOCK(stcb);
3566					}
3567					SCTP_INP_RUNLOCK(inp);
3568				} else {
3569					error = EINVAL;
3570				}
3571			} else {
3572				if (stcb->asoc.cc_functions.sctp_cwnd_socket_option == NULL) {
3573					error = ENOTSUP;
3574				} else {
3575					error = (*stcb->asoc.cc_functions.sctp_cwnd_socket_option) (stcb, 1,
3576					    cc_opt);
3577				}
3578				SCTP_TCB_UNLOCK(stcb);
3579			}
3580			break;
3581		}
3582	case SCTP_PLUGGABLE_SS:
3583		{
3584			struct sctp_assoc_value *av;
3585
3586			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
3587			if ((av->assoc_value != SCTP_SS_DEFAULT) &&
3588			    (av->assoc_value != SCTP_SS_DEFAULT) &&
3589			    (av->assoc_value != SCTP_SS_ROUND_ROBIN) &&
3590			    (av->assoc_value != SCTP_SS_ROUND_ROBIN_PACKET) &&
3591			    (av->assoc_value != SCTP_SS_PRIORITY) &&
3592			    (av->assoc_value != SCTP_SS_FAIR_BANDWITH) &&
3593			    (av->assoc_value != SCTP_SS_FIRST_COME)) {
3594				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3595				error = EINVAL;
3596				break;
3597			}
3598			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3599			if (stcb) {
3600				stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1);
3601				stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
3602				stcb->asoc.stream_scheduling_module = av->assoc_value;
3603				stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
3604				SCTP_TCB_UNLOCK(stcb);
3605			} else {
3606				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3607				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3608				    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
3609				    (av->assoc_id == SCTP_ALL_ASSOC)) {
3610					SCTP_INP_WLOCK(inp);
3611					inp->sctp_ep.sctp_default_ss_module = av->assoc_value;
3612					SCTP_INP_WUNLOCK(inp);
3613				}
3614				if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
3615				    (av->assoc_id == SCTP_ALL_ASSOC)) {
3616					SCTP_INP_RLOCK(inp);
3617					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3618						SCTP_TCB_LOCK(stcb);
3619						stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1);
3620						stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
3621						stcb->asoc.stream_scheduling_module = av->assoc_value;
3622						stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
3623						SCTP_TCB_UNLOCK(stcb);
3624					}
3625					SCTP_INP_RUNLOCK(inp);
3626				}
3627			}
3628			break;
3629		}
3630	case SCTP_SS_VALUE:
3631		{
3632			struct sctp_stream_value *av;
3633
3634			SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, optsize);
3635			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3636			if (stcb) {
3637				if (stcb->asoc.ss_functions.sctp_ss_set_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id],
3638				    av->stream_value) < 0) {
3639					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3640					error = EINVAL;
3641				}
3642				SCTP_TCB_UNLOCK(stcb);
3643			} else {
3644				if (av->assoc_id == SCTP_CURRENT_ASSOC) {
3645					SCTP_INP_RLOCK(inp);
3646					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3647						SCTP_TCB_LOCK(stcb);
3648						stcb->asoc.ss_functions.sctp_ss_set_value(stcb,
3649						    &stcb->asoc,
3650						    &stcb->asoc.strmout[av->stream_id],
3651						    av->stream_value);
3652						SCTP_TCB_UNLOCK(stcb);
3653					}
3654					SCTP_INP_RUNLOCK(inp);
3655
3656				} else {
3657					/*
3658					 * Can't set stream value without
3659					 * association
3660					 */
3661					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3662					error = EINVAL;
3663				}
3664			}
3665			break;
3666		}
3667	case SCTP_CLR_STAT_LOG:
3668		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
3669		error = EOPNOTSUPP;
3670		break;
3671	case SCTP_CONTEXT:
3672		{
3673			struct sctp_assoc_value *av;
3674
3675			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
3676			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3677
3678			if (stcb) {
3679				stcb->asoc.context = av->assoc_value;
3680				SCTP_TCB_UNLOCK(stcb);
3681			} else {
3682				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3683				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3684				    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
3685				    (av->assoc_id == SCTP_ALL_ASSOC)) {
3686					SCTP_INP_WLOCK(inp);
3687					inp->sctp_context = av->assoc_value;
3688					SCTP_INP_WUNLOCK(inp);
3689				}
3690				if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
3691				    (av->assoc_id == SCTP_ALL_ASSOC)) {
3692					SCTP_INP_RLOCK(inp);
3693					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3694						SCTP_TCB_LOCK(stcb);
3695						stcb->asoc.context = av->assoc_value;
3696						SCTP_TCB_UNLOCK(stcb);
3697					}
3698					SCTP_INP_RUNLOCK(inp);
3699				}
3700			}
3701			break;
3702		}
3703	case SCTP_VRF_ID:
3704		{
3705			uint32_t *default_vrfid;
3706
3707			SCTP_CHECK_AND_CAST(default_vrfid, optval, uint32_t, optsize);
3708			if (*default_vrfid > SCTP_MAX_VRF_ID) {
3709				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3710				error = EINVAL;
3711				break;
3712			}
3713			inp->def_vrf_id = *default_vrfid;
3714			break;
3715		}
3716	case SCTP_DEL_VRF_ID:
3717		{
3718			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
3719			error = EOPNOTSUPP;
3720			break;
3721		}
3722	case SCTP_ADD_VRF_ID:
3723		{
3724			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
3725			error = EOPNOTSUPP;
3726			break;
3727		}
3728	case SCTP_DELAYED_SACK:
3729		{
3730			struct sctp_sack_info *sack;
3731
3732			SCTP_CHECK_AND_CAST(sack, optval, struct sctp_sack_info, optsize);
3733			SCTP_FIND_STCB(inp, stcb, sack->sack_assoc_id);
3734			if (sack->sack_delay) {
3735				if (sack->sack_delay > SCTP_MAX_SACK_DELAY)
3736					sack->sack_delay = SCTP_MAX_SACK_DELAY;
3737				if (MSEC_TO_TICKS(sack->sack_delay) < 1) {
3738					sack->sack_delay = TICKS_TO_MSEC(1);
3739				}
3740			}
3741			if (stcb) {
3742				if (sack->sack_delay) {
3743					stcb->asoc.delayed_ack = sack->sack_delay;
3744				}
3745				if (sack->sack_freq) {
3746					stcb->asoc.sack_freq = sack->sack_freq;
3747				}
3748				SCTP_TCB_UNLOCK(stcb);
3749			} else {
3750				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3751				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3752				    (sack->sack_assoc_id == SCTP_FUTURE_ASSOC) ||
3753				    (sack->sack_assoc_id == SCTP_ALL_ASSOC)) {
3754					SCTP_INP_WLOCK(inp);
3755					if (sack->sack_delay) {
3756						inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV] = MSEC_TO_TICKS(sack->sack_delay);
3757					}
3758					if (sack->sack_freq) {
3759						inp->sctp_ep.sctp_sack_freq = sack->sack_freq;
3760					}
3761					SCTP_INP_WUNLOCK(inp);
3762				}
3763				if ((sack->sack_assoc_id == SCTP_CURRENT_ASSOC) ||
3764				    (sack->sack_assoc_id == SCTP_ALL_ASSOC)) {
3765					SCTP_INP_RLOCK(inp);
3766					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3767						SCTP_TCB_LOCK(stcb);
3768						if (sack->sack_delay) {
3769							stcb->asoc.delayed_ack = sack->sack_delay;
3770						}
3771						if (sack->sack_freq) {
3772							stcb->asoc.sack_freq = sack->sack_freq;
3773						}
3774						SCTP_TCB_UNLOCK(stcb);
3775					}
3776					SCTP_INP_RUNLOCK(inp);
3777				}
3778			}
3779			break;
3780		}
3781	case SCTP_AUTH_CHUNK:
3782		{
3783			struct sctp_authchunk *sauth;
3784
3785			SCTP_CHECK_AND_CAST(sauth, optval, struct sctp_authchunk, optsize);
3786
3787			SCTP_INP_WLOCK(inp);
3788			if (sctp_auth_add_chunk(sauth->sauth_chunk, inp->sctp_ep.local_auth_chunks)) {
3789				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3790				error = EINVAL;
3791			}
3792			SCTP_INP_WUNLOCK(inp);
3793			break;
3794		}
3795	case SCTP_AUTH_KEY:
3796		{
3797			struct sctp_authkey *sca;
3798			struct sctp_keyhead *shared_keys;
3799			sctp_sharedkey_t *shared_key;
3800			sctp_key_t *key = NULL;
3801			size_t size;
3802
3803			SCTP_CHECK_AND_CAST(sca, optval, struct sctp_authkey, optsize);
3804			if (sca->sca_keylength == 0) {
3805				size = optsize - sizeof(struct sctp_authkey);
3806			} else {
3807				if (sca->sca_keylength + sizeof(struct sctp_authkey) <= optsize) {
3808					size = sca->sca_keylength;
3809				} else {
3810					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3811					error = EINVAL;
3812					break;
3813				}
3814			}
3815			SCTP_FIND_STCB(inp, stcb, sca->sca_assoc_id);
3816
3817			if (stcb) {
3818				shared_keys = &stcb->asoc.shared_keys;
3819				/* clear the cached keys for this key id */
3820				sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
3821				/*
3822				 * create the new shared key and
3823				 * insert/replace it
3824				 */
3825				if (size > 0) {
3826					key = sctp_set_key(sca->sca_key, (uint32_t) size);
3827					if (key == NULL) {
3828						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
3829						error = ENOMEM;
3830						SCTP_TCB_UNLOCK(stcb);
3831						break;
3832					}
3833				}
3834				shared_key = sctp_alloc_sharedkey();
3835				if (shared_key == NULL) {
3836					sctp_free_key(key);
3837					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
3838					error = ENOMEM;
3839					SCTP_TCB_UNLOCK(stcb);
3840					break;
3841				}
3842				shared_key->key = key;
3843				shared_key->keyid = sca->sca_keynumber;
3844				error = sctp_insert_sharedkey(shared_keys, shared_key);
3845				SCTP_TCB_UNLOCK(stcb);
3846			} else {
3847				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3848				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3849				    (sca->sca_assoc_id == SCTP_FUTURE_ASSOC) ||
3850				    (sca->sca_assoc_id == SCTP_ALL_ASSOC)) {
3851					SCTP_INP_WLOCK(inp);
3852					shared_keys = &inp->sctp_ep.shared_keys;
3853					/*
3854					 * clear the cached keys on all
3855					 * assocs for this key id
3856					 */
3857					sctp_clear_cachedkeys_ep(inp, sca->sca_keynumber);
3858					/*
3859					 * create the new shared key and
3860					 * insert/replace it
3861					 */
3862					if (size > 0) {
3863						key = sctp_set_key(sca->sca_key, (uint32_t) size);
3864						if (key == NULL) {
3865							SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
3866							error = ENOMEM;
3867							SCTP_INP_WUNLOCK(inp);
3868							break;
3869						}
3870					}
3871					shared_key = sctp_alloc_sharedkey();
3872					if (shared_key == NULL) {
3873						sctp_free_key(key);
3874						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
3875						error = ENOMEM;
3876						SCTP_INP_WUNLOCK(inp);
3877						break;
3878					}
3879					shared_key->key = key;
3880					shared_key->keyid = sca->sca_keynumber;
3881					error = sctp_insert_sharedkey(shared_keys, shared_key);
3882					SCTP_INP_WUNLOCK(inp);
3883				}
3884				if ((sca->sca_assoc_id == SCTP_CURRENT_ASSOC) ||
3885				    (sca->sca_assoc_id == SCTP_ALL_ASSOC)) {
3886					SCTP_INP_RLOCK(inp);
3887					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3888						SCTP_TCB_LOCK(stcb);
3889						shared_keys = &stcb->asoc.shared_keys;
3890						/*
3891						 * clear the cached keys for
3892						 * this key id
3893						 */
3894						sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
3895						/*
3896						 * create the new shared key
3897						 * and insert/replace it
3898						 */
3899						if (size > 0) {
3900							key = sctp_set_key(sca->sca_key, (uint32_t) size);
3901							if (key == NULL) {
3902								SCTP_TCB_UNLOCK(stcb);
3903								continue;
3904							}
3905						}
3906						shared_key = sctp_alloc_sharedkey();
3907						if (shared_key == NULL) {
3908							sctp_free_key(key);
3909							SCTP_TCB_UNLOCK(stcb);
3910							continue;
3911						}
3912						shared_key->key = key;
3913						shared_key->keyid = sca->sca_keynumber;
3914						error = sctp_insert_sharedkey(shared_keys, shared_key);
3915						SCTP_TCB_UNLOCK(stcb);
3916					}
3917					SCTP_INP_RUNLOCK(inp);
3918				}
3919			}
3920			break;
3921		}
3922	case SCTP_HMAC_IDENT:
3923		{
3924			struct sctp_hmacalgo *shmac;
3925			sctp_hmaclist_t *hmaclist;
3926			uint16_t hmacid;
3927			uint32_t i;
3928			size_t found;
3929
3930			SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, optsize);
3931			if (optsize < sizeof(struct sctp_hmacalgo) + shmac->shmac_number_of_idents * sizeof(uint16_t)) {
3932				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3933				error = EINVAL;
3934				break;
3935			}
3936			hmaclist = sctp_alloc_hmaclist(shmac->shmac_number_of_idents);
3937			if (hmaclist == NULL) {
3938				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
3939				error = ENOMEM;
3940				break;
3941			}
3942			for (i = 0; i < shmac->shmac_number_of_idents; i++) {
3943				hmacid = shmac->shmac_idents[i];
3944				if (sctp_auth_add_hmacid(hmaclist, hmacid)) {
3945					 /* invalid HMACs were found */ ;
3946					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3947					error = EINVAL;
3948					sctp_free_hmaclist(hmaclist);
3949					goto sctp_set_hmac_done;
3950				}
3951			}
3952			found = 0;
3953			for (i = 0; i < hmaclist->num_algo; i++) {
3954				if (hmaclist->hmac[i] == SCTP_AUTH_HMAC_ID_SHA1) {
3955					/* already in list */
3956					found = 1;
3957				}
3958			}
3959			if (!found) {
3960				sctp_free_hmaclist(hmaclist);
3961				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3962				error = EINVAL;
3963				break;
3964			}
3965			/* set it on the endpoint */
3966			SCTP_INP_WLOCK(inp);
3967			if (inp->sctp_ep.local_hmacs)
3968				sctp_free_hmaclist(inp->sctp_ep.local_hmacs);
3969			inp->sctp_ep.local_hmacs = hmaclist;
3970			SCTP_INP_WUNLOCK(inp);
3971	sctp_set_hmac_done:
3972			break;
3973		}
3974	case SCTP_AUTH_ACTIVE_KEY:
3975		{
3976			struct sctp_authkeyid *scact;
3977
3978			SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, optsize);
3979			SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id);
3980
3981			/* set the active key on the right place */
3982			if (stcb) {
3983				/* set the active key on the assoc */
3984				if (sctp_auth_setactivekey(stcb,
3985				    scact->scact_keynumber)) {
3986					SCTP_LTRACE_ERR_RET(inp, NULL, NULL,
3987					    SCTP_FROM_SCTP_USRREQ,
3988					    EINVAL);
3989					error = EINVAL;
3990				}
3991				SCTP_TCB_UNLOCK(stcb);
3992			} else {
3993				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3994				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3995				    (scact->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
3996				    (scact->scact_assoc_id == SCTP_ALL_ASSOC)) {
3997					SCTP_INP_WLOCK(inp);
3998					if (sctp_auth_setactivekey_ep(inp, scact->scact_keynumber)) {
3999						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4000						error = EINVAL;
4001					}
4002					SCTP_INP_WUNLOCK(inp);
4003				}
4004				if ((scact->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
4005				    (scact->scact_assoc_id == SCTP_ALL_ASSOC)) {
4006					SCTP_INP_RLOCK(inp);
4007					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4008						SCTP_TCB_LOCK(stcb);
4009						sctp_auth_setactivekey(stcb, scact->scact_keynumber);
4010						SCTP_TCB_UNLOCK(stcb);
4011					}
4012					SCTP_INP_RUNLOCK(inp);
4013				}
4014			}
4015			break;
4016		}
4017	case SCTP_AUTH_DELETE_KEY:
4018		{
4019			struct sctp_authkeyid *scdel;
4020
4021			SCTP_CHECK_AND_CAST(scdel, optval, struct sctp_authkeyid, optsize);
4022			SCTP_FIND_STCB(inp, stcb, scdel->scact_assoc_id);
4023
4024			/* delete the key from the right place */
4025			if (stcb) {
4026				if (sctp_delete_sharedkey(stcb, scdel->scact_keynumber)) {
4027					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4028					error = EINVAL;
4029				}
4030				SCTP_TCB_UNLOCK(stcb);
4031			} else {
4032				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4033				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4034				    (scdel->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
4035				    (scdel->scact_assoc_id == SCTP_ALL_ASSOC)) {
4036					SCTP_INP_WLOCK(inp);
4037					if (sctp_delete_sharedkey_ep(inp, scdel->scact_keynumber)) {
4038						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4039						error = EINVAL;
4040					}
4041					SCTP_INP_WUNLOCK(inp);
4042				}
4043				if ((scdel->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
4044				    (scdel->scact_assoc_id == SCTP_ALL_ASSOC)) {
4045					SCTP_INP_RLOCK(inp);
4046					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4047						SCTP_TCB_LOCK(stcb);
4048						sctp_delete_sharedkey(stcb, scdel->scact_keynumber);
4049						SCTP_TCB_UNLOCK(stcb);
4050					}
4051					SCTP_INP_RUNLOCK(inp);
4052				}
4053			}
4054			break;
4055		}
4056	case SCTP_AUTH_DEACTIVATE_KEY:
4057		{
4058			struct sctp_authkeyid *keyid;
4059
4060			SCTP_CHECK_AND_CAST(keyid, optval, struct sctp_authkeyid, optsize);
4061			SCTP_FIND_STCB(inp, stcb, keyid->scact_assoc_id);
4062
4063			/* deactivate the key from the right place */
4064			if (stcb) {
4065				if (sctp_deact_sharedkey(stcb, keyid->scact_keynumber)) {
4066					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4067					error = EINVAL;
4068				}
4069				SCTP_TCB_UNLOCK(stcb);
4070			} else {
4071				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4072				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4073				    (keyid->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
4074				    (keyid->scact_assoc_id == SCTP_ALL_ASSOC)) {
4075					SCTP_INP_WLOCK(inp);
4076					if (sctp_deact_sharedkey_ep(inp, keyid->scact_keynumber)) {
4077						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4078						error = EINVAL;
4079					}
4080					SCTP_INP_WUNLOCK(inp);
4081				}
4082				if ((keyid->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
4083				    (keyid->scact_assoc_id == SCTP_ALL_ASSOC)) {
4084					SCTP_INP_RLOCK(inp);
4085					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4086						SCTP_TCB_LOCK(stcb);
4087						sctp_deact_sharedkey(stcb, keyid->scact_keynumber);
4088						SCTP_TCB_UNLOCK(stcb);
4089					}
4090					SCTP_INP_RUNLOCK(inp);
4091				}
4092			}
4093			break;
4094		}
4095
4096	case SCTP_RESET_STREAMS:
4097		{
4098			struct sctp_stream_reset *strrst;
4099			uint8_t send_in = 0, send_tsn = 0, send_out = 0,
4100			        addstream = 0;
4101			uint16_t addstrmcnt = 0;
4102			int i;
4103
4104			SCTP_CHECK_AND_CAST(strrst, optval, struct sctp_stream_reset, optsize);
4105			SCTP_FIND_STCB(inp, stcb, strrst->strrst_assoc_id);
4106
4107			if (stcb == NULL) {
4108				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4109				error = ENOENT;
4110				break;
4111			}
4112			if (stcb->asoc.peer_supports_strreset == 0) {
4113				/*
4114				 * Peer does not support it, we return
4115				 * protocol not supported since this is true
4116				 * for this feature and this peer, not the
4117				 * socket request in general.
4118				 */
4119				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EPROTONOSUPPORT);
4120				error = EPROTONOSUPPORT;
4121				SCTP_TCB_UNLOCK(stcb);
4122				break;
4123			}
4124			if (stcb->asoc.stream_reset_outstanding) {
4125				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4126				error = EALREADY;
4127				SCTP_TCB_UNLOCK(stcb);
4128				break;
4129			}
4130			if (strrst->strrst_flags == SCTP_RESET_LOCAL_RECV) {
4131				send_in = 1;
4132			} else if (strrst->strrst_flags == SCTP_RESET_LOCAL_SEND) {
4133				send_out = 1;
4134			} else if (strrst->strrst_flags == SCTP_RESET_BOTH) {
4135				send_in = 1;
4136				send_out = 1;
4137			} else if (strrst->strrst_flags == SCTP_RESET_TSN) {
4138				send_tsn = 1;
4139			} else if (strrst->strrst_flags == SCTP_RESET_ADD_STREAMS) {
4140				if (send_tsn ||
4141				    send_in ||
4142				    send_out) {
4143					/* We can't do that and add streams */
4144					error = EINVAL;
4145					goto skip_stuff;
4146				}
4147				if (stcb->asoc.stream_reset_outstanding) {
4148					error = EBUSY;
4149					goto skip_stuff;
4150				}
4151				addstream = 1;
4152				/* We allocate here */
4153				addstrmcnt = strrst->strrst_num_streams;
4154				if ((int)(addstrmcnt + stcb->asoc.streamoutcnt) > 0xffff) {
4155					/* You can't have more than 64k */
4156					error = EINVAL;
4157					goto skip_stuff;
4158				}
4159				if ((stcb->asoc.strm_realoutsize - stcb->asoc.streamoutcnt) < addstrmcnt) {
4160					/* Need to allocate more */
4161					struct sctp_stream_out *oldstream;
4162					struct sctp_stream_queue_pending *sp,
4163					                         *nsp;
4164
4165					oldstream = stcb->asoc.strmout;
4166					/* get some more */
4167					SCTP_MALLOC(stcb->asoc.strmout, struct sctp_stream_out *,
4168					    ((stcb->asoc.streamoutcnt + addstrmcnt) * sizeof(struct sctp_stream_out)),
4169					    SCTP_M_STRMO);
4170					if (stcb->asoc.strmout == NULL) {
4171						stcb->asoc.strmout = oldstream;
4172						error = ENOMEM;
4173						goto skip_stuff;
4174					}
4175					/*
4176					 * Ok now we proceed with copying
4177					 * the old out stuff and
4178					 * initializing the new stuff.
4179					 */
4180					SCTP_TCB_SEND_LOCK(stcb);
4181					stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 0, 1);
4182					for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
4183						TAILQ_INIT(&stcb->asoc.strmout[i].outqueue);
4184						stcb->asoc.strmout[i].next_sequence_sent = oldstream[i].next_sequence_sent;
4185						stcb->asoc.strmout[i].last_msg_incomplete = oldstream[i].last_msg_incomplete;
4186						stcb->asoc.strmout[i].stream_no = i;
4187						stcb->asoc.ss_functions.sctp_ss_init_stream(&stcb->asoc.strmout[i], &oldstream[i]);
4188						/*
4189						 * now anything on those
4190						 * queues?
4191						 */
4192						TAILQ_FOREACH_SAFE(sp, &oldstream[i].outqueue, next, nsp) {
4193							TAILQ_REMOVE(&oldstream[i].outqueue, sp, next);
4194							TAILQ_INSERT_TAIL(&stcb->asoc.strmout[i].outqueue, sp, next);
4195						}
4196						/*
4197						 * Now move assoc pointers
4198						 * too
4199						 */
4200						if (stcb->asoc.last_out_stream == &oldstream[i]) {
4201							stcb->asoc.last_out_stream = &stcb->asoc.strmout[i];
4202						}
4203						if (stcb->asoc.locked_on_sending == &oldstream[i]) {
4204							stcb->asoc.locked_on_sending = &stcb->asoc.strmout[i];
4205						}
4206					}
4207					/* now the new streams */
4208					stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
4209					for (i = stcb->asoc.streamoutcnt; i < (stcb->asoc.streamoutcnt + addstrmcnt); i++) {
4210						stcb->asoc.strmout[i].next_sequence_sent = 0x0;
4211						TAILQ_INIT(&stcb->asoc.strmout[i].outqueue);
4212						stcb->asoc.strmout[i].stream_no = i;
4213						stcb->asoc.strmout[i].last_msg_incomplete = 0;
4214						stcb->asoc.ss_functions.sctp_ss_init_stream(&stcb->asoc.strmout[i], NULL);
4215					}
4216					stcb->asoc.strm_realoutsize = stcb->asoc.streamoutcnt + addstrmcnt;
4217					SCTP_FREE(oldstream, SCTP_M_STRMO);
4218				}
4219				SCTP_TCB_SEND_UNLOCK(stcb);
4220				goto skip_stuff;
4221			} else {
4222				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4223				error = EINVAL;
4224				SCTP_TCB_UNLOCK(stcb);
4225				break;
4226			}
4227			for (i = 0; i < strrst->strrst_num_streams; i++) {
4228				if ((send_in) &&
4229
4230				    (strrst->strrst_list[i] > stcb->asoc.streamincnt)) {
4231					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4232					error = EINVAL;
4233					goto get_out;
4234				}
4235				if ((send_out) &&
4236				    (strrst->strrst_list[i] > stcb->asoc.streamoutcnt)) {
4237					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4238					error = EINVAL;
4239					goto get_out;
4240				}
4241			}
4242	skip_stuff:
4243			if (error) {
4244		get_out:
4245				SCTP_TCB_UNLOCK(stcb);
4246				break;
4247			}
4248			error = sctp_send_str_reset_req(stcb, strrst->strrst_num_streams,
4249			    strrst->strrst_list,
4250			    send_out, (stcb->asoc.str_reset_seq_in - 3),
4251			    send_in, send_tsn, addstream, addstrmcnt);
4252
4253			sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
4254			SCTP_TCB_UNLOCK(stcb);
4255			break;
4256		}
4257	case SCTP_CONNECT_X:
4258		if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
4259			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4260			error = EINVAL;
4261			break;
4262		}
4263		error = sctp_do_connect_x(so, inp, optval, optsize, p, 0);
4264		break;
4265	case SCTP_CONNECT_X_DELAYED:
4266		if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
4267			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4268			error = EINVAL;
4269			break;
4270		}
4271		error = sctp_do_connect_x(so, inp, optval, optsize, p, 1);
4272		break;
4273	case SCTP_CONNECT_X_COMPLETE:
4274		{
4275			struct sockaddr *sa;
4276			struct sctp_nets *net;
4277
4278			/* FIXME MT: check correct? */
4279			SCTP_CHECK_AND_CAST(sa, optval, struct sockaddr, optsize);
4280
4281			/* find tcb */
4282			if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
4283				SCTP_INP_RLOCK(inp);
4284				stcb = LIST_FIRST(&inp->sctp_asoc_list);
4285				if (stcb) {
4286					SCTP_TCB_LOCK(stcb);
4287					net = sctp_findnet(stcb, sa);
4288				}
4289				SCTP_INP_RUNLOCK(inp);
4290			} else {
4291				/*
4292				 * We increment here since
4293				 * sctp_findassociation_ep_addr() wil do a
4294				 * decrement if it finds the stcb as long as
4295				 * the locked tcb (last argument) is NOT a
4296				 * TCB.. aka NULL.
4297				 */
4298				SCTP_INP_INCR_REF(inp);
4299				stcb = sctp_findassociation_ep_addr(&inp, sa, &net, NULL, NULL);
4300				if (stcb == NULL) {
4301					SCTP_INP_DECR_REF(inp);
4302				}
4303			}
4304
4305			if (stcb == NULL) {
4306				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4307				error = ENOENT;
4308				break;
4309			}
4310			if (stcb->asoc.delayed_connection == 1) {
4311				stcb->asoc.delayed_connection = 0;
4312				(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
4313				sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb,
4314				    stcb->asoc.primary_destination,
4315				    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_9);
4316				sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
4317			} else {
4318				/*
4319				 * already expired or did not use delayed
4320				 * connectx
4321				 */
4322				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4323				error = EALREADY;
4324			}
4325			SCTP_TCB_UNLOCK(stcb);
4326			break;
4327		}
4328	case SCTP_MAX_BURST:
4329		{
4330			struct sctp_assoc_value *av;
4331
4332			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4333			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4334
4335			if (stcb) {
4336				stcb->asoc.max_burst = av->assoc_value;
4337				SCTP_TCB_UNLOCK(stcb);
4338			} else {
4339				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4340				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4341				    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
4342				    (av->assoc_id == SCTP_ALL_ASSOC)) {
4343					SCTP_INP_WLOCK(inp);
4344					inp->sctp_ep.max_burst = av->assoc_value;
4345					SCTP_INP_WUNLOCK(inp);
4346				}
4347				if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4348				    (av->assoc_id == SCTP_ALL_ASSOC)) {
4349					SCTP_INP_RLOCK(inp);
4350					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4351						SCTP_TCB_LOCK(stcb);
4352						stcb->asoc.max_burst = av->assoc_value;
4353						SCTP_TCB_UNLOCK(stcb);
4354					}
4355					SCTP_INP_RUNLOCK(inp);
4356				}
4357			}
4358			break;
4359		}
4360	case SCTP_MAXSEG:
4361		{
4362			struct sctp_assoc_value *av;
4363			int ovh;
4364
4365			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4366			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4367
4368			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
4369				ovh = SCTP_MED_OVERHEAD;
4370			} else {
4371				ovh = SCTP_MED_V4_OVERHEAD;
4372			}
4373			if (stcb) {
4374				if (av->assoc_value) {
4375					stcb->asoc.sctp_frag_point = (av->assoc_value + ovh);
4376				} else {
4377					stcb->asoc.sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
4378				}
4379				SCTP_TCB_UNLOCK(stcb);
4380			} else {
4381				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4382				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4383				    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
4384					SCTP_INP_WLOCK(inp);
4385					/*
4386					 * FIXME MT: I think this is not in
4387					 * tune with the API ID
4388					 */
4389					if (av->assoc_value) {
4390						inp->sctp_frag_point = (av->assoc_value + ovh);
4391					} else {
4392						inp->sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
4393					}
4394					SCTP_INP_WUNLOCK(inp);
4395				} else {
4396					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4397					error = EINVAL;
4398				}
4399			}
4400			break;
4401		}
4402	case SCTP_EVENTS:
4403		{
4404			struct sctp_event_subscribe *events;
4405
4406			SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, optsize);
4407
4408			SCTP_INP_WLOCK(inp);
4409			if (events->sctp_data_io_event) {
4410				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
4411			} else {
4412				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
4413			}
4414
4415			if (events->sctp_association_event) {
4416				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
4417			} else {
4418				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
4419			}
4420
4421			if (events->sctp_address_event) {
4422				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
4423			} else {
4424				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
4425			}
4426
4427			if (events->sctp_send_failure_event) {
4428				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
4429			} else {
4430				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
4431			}
4432
4433			if (events->sctp_peer_error_event) {
4434				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPEERERR);
4435			} else {
4436				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPEERERR);
4437			}
4438
4439			if (events->sctp_shutdown_event) {
4440				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
4441			} else {
4442				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
4443			}
4444
4445			if (events->sctp_partial_delivery_event) {
4446				sctp_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
4447			} else {
4448				sctp_feature_off(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
4449			}
4450
4451			if (events->sctp_adaptation_layer_event) {
4452				sctp_feature_on(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
4453			} else {
4454				sctp_feature_off(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
4455			}
4456
4457			if (events->sctp_authentication_event) {
4458				sctp_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT);
4459			} else {
4460				sctp_feature_off(inp, SCTP_PCB_FLAGS_AUTHEVNT);
4461			}
4462
4463			if (events->sctp_sender_dry_event) {
4464				sctp_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT);
4465			} else {
4466				sctp_feature_off(inp, SCTP_PCB_FLAGS_DRYEVNT);
4467			}
4468
4469			if (events->sctp_stream_reset_event) {
4470				sctp_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
4471			} else {
4472				sctp_feature_off(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
4473			}
4474			SCTP_INP_WUNLOCK(inp);
4475
4476			SCTP_INP_RLOCK(inp);
4477			LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4478				SCTP_TCB_LOCK(stcb);
4479				if (events->sctp_association_event) {
4480					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
4481				} else {
4482					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
4483				}
4484				if (events->sctp_address_event) {
4485					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
4486				} else {
4487					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
4488				}
4489				if (events->sctp_send_failure_event) {
4490					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
4491				} else {
4492					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
4493				}
4494				if (events->sctp_peer_error_event) {
4495					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
4496				} else {
4497					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
4498				}
4499				if (events->sctp_shutdown_event) {
4500					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
4501				} else {
4502					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
4503				}
4504				if (events->sctp_partial_delivery_event) {
4505					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
4506				} else {
4507					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
4508				}
4509				if (events->sctp_adaptation_layer_event) {
4510					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
4511				} else {
4512					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
4513				}
4514				if (events->sctp_authentication_event) {
4515					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
4516				} else {
4517					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
4518				}
4519				if (events->sctp_sender_dry_event) {
4520					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
4521				} else {
4522					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
4523				}
4524				if (events->sctp_stream_reset_event) {
4525					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
4526				} else {
4527					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
4528				}
4529				SCTP_TCB_UNLOCK(stcb);
4530			}
4531			/*
4532			 * Send up the sender dry event only for 1-to-1
4533			 * style sockets.
4534			 */
4535			if (events->sctp_sender_dry_event) {
4536				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4537				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
4538					stcb = LIST_FIRST(&inp->sctp_asoc_list);
4539					if (stcb) {
4540						SCTP_TCB_LOCK(stcb);
4541						if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
4542						    TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
4543						    (stcb->asoc.stream_queue_cnt == 0)) {
4544							sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_LOCKED);
4545						}
4546						SCTP_TCB_UNLOCK(stcb);
4547					}
4548				}
4549			}
4550			SCTP_INP_RUNLOCK(inp);
4551			break;
4552		}
4553	case SCTP_ADAPTATION_LAYER:
4554		{
4555			struct sctp_setadaptation *adap_bits;
4556
4557			SCTP_CHECK_AND_CAST(adap_bits, optval, struct sctp_setadaptation, optsize);
4558			SCTP_INP_WLOCK(inp);
4559			inp->sctp_ep.adaptation_layer_indicator = adap_bits->ssb_adaptation_ind;
4560			SCTP_INP_WUNLOCK(inp);
4561			break;
4562		}
4563#ifdef SCTP_DEBUG
4564	case SCTP_SET_INITIAL_DBG_SEQ:
4565		{
4566			uint32_t *vvv;
4567
4568			SCTP_CHECK_AND_CAST(vvv, optval, uint32_t, optsize);
4569			SCTP_INP_WLOCK(inp);
4570			inp->sctp_ep.initial_sequence_debug = *vvv;
4571			SCTP_INP_WUNLOCK(inp);
4572			break;
4573		}
4574#endif
4575	case SCTP_DEFAULT_SEND_PARAM:
4576		{
4577			struct sctp_sndrcvinfo *s_info;
4578
4579			SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, optsize);
4580			SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
4581
4582			if (stcb) {
4583				if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
4584					memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
4585				} else {
4586					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4587					error = EINVAL;
4588				}
4589				SCTP_TCB_UNLOCK(stcb);
4590			} else {
4591				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4592				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4593				    (s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC) ||
4594				    (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)) {
4595					SCTP_INP_WLOCK(inp);
4596					memcpy(&inp->def_send, s_info, min(optsize, sizeof(inp->def_send)));
4597					SCTP_INP_WUNLOCK(inp);
4598				}
4599				if ((s_info->sinfo_assoc_id == SCTP_CURRENT_ASSOC) ||
4600				    (s_info->sinfo_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 (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
4605							memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
4606						}
4607						SCTP_TCB_UNLOCK(stcb);
4608					}
4609					SCTP_INP_RUNLOCK(inp);
4610				}
4611			}
4612			break;
4613		}
4614	case SCTP_PEER_ADDR_PARAMS:
4615		{
4616			struct sctp_paddrparams *paddrp;
4617			struct sctp_nets *net;
4618
4619			SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, optsize);
4620			SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
4621			net = NULL;
4622			if (stcb) {
4623				net = sctp_findnet(stcb, (struct sockaddr *)&paddrp->spp_address);
4624			} else {
4625				/*
4626				 * We increment here since
4627				 * sctp_findassociation_ep_addr() wil do a
4628				 * decrement if it finds the stcb as long as
4629				 * the locked tcb (last argument) is NOT a
4630				 * TCB.. aka NULL.
4631				 */
4632				SCTP_INP_INCR_REF(inp);
4633				stcb = sctp_findassociation_ep_addr(&inp,
4634				    (struct sockaddr *)&paddrp->spp_address,
4635				    &net, NULL, NULL);
4636				if (stcb == NULL) {
4637					SCTP_INP_DECR_REF(inp);
4638				}
4639			}
4640			if (stcb && (net == NULL)) {
4641				struct sockaddr *sa;
4642
4643				sa = (struct sockaddr *)&paddrp->spp_address;
4644#ifdef INET
4645				if (sa->sa_family == AF_INET) {
4646
4647					struct sockaddr_in *sin;
4648
4649					sin = (struct sockaddr_in *)sa;
4650					if (sin->sin_addr.s_addr) {
4651						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4652						SCTP_TCB_UNLOCK(stcb);
4653						error = EINVAL;
4654						break;
4655					}
4656				} else
4657#endif
4658#ifdef INET6
4659				if (sa->sa_family == AF_INET6) {
4660					struct sockaddr_in6 *sin6;
4661
4662					sin6 = (struct sockaddr_in6 *)sa;
4663					if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
4664						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4665						SCTP_TCB_UNLOCK(stcb);
4666						error = EINVAL;
4667						break;
4668					}
4669				} else
4670#endif
4671				{
4672					error = EAFNOSUPPORT;
4673					SCTP_TCB_UNLOCK(stcb);
4674					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
4675					break;
4676				}
4677			}
4678			/* sanity checks */
4679			if ((paddrp->spp_flags & SPP_HB_ENABLE) && (paddrp->spp_flags & SPP_HB_DISABLE)) {
4680				if (stcb)
4681					SCTP_TCB_UNLOCK(stcb);
4682				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4683				return (EINVAL);
4684			}
4685			if ((paddrp->spp_flags & SPP_PMTUD_ENABLE) && (paddrp->spp_flags & SPP_PMTUD_DISABLE)) {
4686				if (stcb)
4687					SCTP_TCB_UNLOCK(stcb);
4688				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4689				return (EINVAL);
4690			}
4691			if (stcb) {
4692				/************************TCB SPECIFIC SET ******************/
4693				/*
4694				 * do we change the timer for HB, we run
4695				 * only one?
4696				 */
4697				int ovh = 0;
4698
4699				if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
4700					ovh = SCTP_MED_OVERHEAD;
4701				} else {
4702					ovh = SCTP_MED_V4_OVERHEAD;
4703				}
4704
4705				/* network sets ? */
4706				if (net) {
4707					/************************NET SPECIFIC SET ******************/
4708					if (paddrp->spp_flags & SPP_HB_DISABLE) {
4709						if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
4710						    !(net->dest_state & SCTP_ADDR_NOHB)) {
4711							sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
4712							    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
4713						}
4714						net->dest_state |= SCTP_ADDR_NOHB;
4715					}
4716					if (paddrp->spp_flags & SPP_HB_ENABLE) {
4717						if (paddrp->spp_hbinterval) {
4718							net->heart_beat_delay = paddrp->spp_hbinterval;
4719						} else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
4720							net->heart_beat_delay = 0;
4721						}
4722						sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
4723						    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
4724						sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
4725						net->dest_state &= ~SCTP_ADDR_NOHB;
4726					}
4727					if (paddrp->spp_flags & SPP_HB_DEMAND) {
4728						/* on demand HB */
4729						sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
4730						sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED);
4731						sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
4732					}
4733					if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
4734						if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
4735							sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
4736							    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
4737						}
4738						net->dest_state |= SCTP_ADDR_NO_PMTUD;
4739						if (paddrp->spp_pathmtu > SCTP_DEFAULT_MINSEGMENT) {
4740							net->mtu = paddrp->spp_pathmtu + ovh;
4741							if (net->mtu < stcb->asoc.smallest_mtu) {
4742								sctp_pathmtu_adjustment(inp, stcb, net, net->mtu);
4743							}
4744						}
4745					}
4746					if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
4747						if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
4748							sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
4749						}
4750						net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
4751					}
4752					if (paddrp->spp_pathmaxrxt) {
4753						if (net->dest_state & SCTP_ADDR_PF) {
4754							if (net->error_count > paddrp->spp_pathmaxrxt) {
4755								net->dest_state &= ~SCTP_ADDR_PF;
4756							}
4757						} else {
4758							if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
4759							    (net->error_count > net->pf_threshold)) {
4760								net->dest_state |= SCTP_ADDR_PF;
4761								sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
4762								sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
4763								sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
4764							}
4765						}
4766						if (net->dest_state & SCTP_ADDR_REACHABLE) {
4767							if (net->error_count > paddrp->spp_pathmaxrxt) {
4768								net->dest_state &= ~SCTP_ADDR_REACHABLE;
4769								sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, SCTP_RESPONSE_TO_USER_REQ, net, SCTP_SO_LOCKED);
4770							}
4771						} else {
4772							if (net->error_count <= paddrp->spp_pathmaxrxt) {
4773								net->dest_state |= SCTP_ADDR_REACHABLE;
4774								sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, SCTP_RESPONSE_TO_USER_REQ, net, SCTP_SO_LOCKED);
4775							}
4776						}
4777						net->failure_threshold = paddrp->spp_pathmaxrxt;
4778					}
4779					if (paddrp->spp_flags & SPP_DSCP) {
4780						net->dscp = paddrp->spp_dscp & 0xfc;
4781						net->dscp |= 0x01;
4782					}
4783#ifdef INET6
4784					if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
4785						if (net->ro._l_addr.sa.sa_family == AF_INET6) {
4786							net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
4787							net->flowlabel |= 0x80000000;
4788						}
4789					}
4790#endif
4791				} else {
4792					/************************ASSOC ONLY -- NO NET SPECIFIC SET ******************/
4793					if (paddrp->spp_pathmaxrxt) {
4794						stcb->asoc.def_net_failure = paddrp->spp_pathmaxrxt;
4795						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4796							if (net->dest_state & SCTP_ADDR_PF) {
4797								if (net->error_count > paddrp->spp_pathmaxrxt) {
4798									net->dest_state &= ~SCTP_ADDR_PF;
4799								}
4800							} else {
4801								if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
4802								    (net->error_count > net->pf_threshold)) {
4803									net->dest_state |= SCTP_ADDR_PF;
4804									sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
4805									sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
4806									sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
4807								}
4808							}
4809							if (net->dest_state & SCTP_ADDR_REACHABLE) {
4810								if (net->error_count > paddrp->spp_pathmaxrxt) {
4811									net->dest_state &= ~SCTP_ADDR_REACHABLE;
4812									sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, SCTP_RESPONSE_TO_USER_REQ, net, SCTP_SO_LOCKED);
4813								}
4814							} else {
4815								if (net->error_count <= paddrp->spp_pathmaxrxt) {
4816									net->dest_state |= SCTP_ADDR_REACHABLE;
4817									sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, SCTP_RESPONSE_TO_USER_REQ, net, SCTP_SO_LOCKED);
4818								}
4819							}
4820							net->failure_threshold = paddrp->spp_pathmaxrxt;
4821						}
4822					}
4823					if (paddrp->spp_flags & SPP_HB_ENABLE) {
4824						if (paddrp->spp_hbinterval) {
4825							stcb->asoc.heart_beat_delay = paddrp->spp_hbinterval;
4826						} else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
4827							stcb->asoc.heart_beat_delay = 0;
4828						}
4829						/* Turn back on the timer */
4830						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4831							if (paddrp->spp_hbinterval) {
4832								net->heart_beat_delay = paddrp->spp_hbinterval;
4833							} else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
4834								net->heart_beat_delay = 0;
4835							}
4836							if (net->dest_state & SCTP_ADDR_NOHB) {
4837								net->dest_state &= ~SCTP_ADDR_NOHB;
4838							}
4839							sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
4840							    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
4841							sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
4842						}
4843						sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
4844					}
4845					if (paddrp->spp_flags & SPP_HB_DISABLE) {
4846						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4847							if (!(net->dest_state & SCTP_ADDR_NOHB)) {
4848								net->dest_state |= SCTP_ADDR_NOHB;
4849								if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED)) {
4850									sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
4851								}
4852							}
4853						}
4854						sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
4855					}
4856					if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
4857						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4858							if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
4859								sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
4860								    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
4861							}
4862							net->dest_state |= SCTP_ADDR_NO_PMTUD;
4863							if (paddrp->spp_pathmtu > SCTP_DEFAULT_MINSEGMENT) {
4864								net->mtu = paddrp->spp_pathmtu + ovh;
4865								if (net->mtu < stcb->asoc.smallest_mtu) {
4866									sctp_pathmtu_adjustment(inp, stcb, net, net->mtu);
4867								}
4868							}
4869						}
4870						sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
4871					}
4872					if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
4873						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4874							if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
4875								sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
4876							}
4877							net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
4878						}
4879						sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
4880					}
4881					if (paddrp->spp_flags & SPP_DSCP) {
4882						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4883							net->dscp = paddrp->spp_dscp & 0xfc;
4884							net->dscp |= 0x01;
4885						}
4886						stcb->asoc.default_dscp = paddrp->spp_dscp & 0xfc;
4887						stcb->asoc.default_dscp |= 0x01;
4888					}
4889#ifdef INET6
4890					if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
4891						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4892							if (net->ro._l_addr.sa.sa_family == AF_INET6) {
4893								net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
4894								net->flowlabel |= 0x80000000;
4895							}
4896						}
4897						stcb->asoc.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
4898						stcb->asoc.default_flowlabel |= 0x80000000;
4899					}
4900#endif
4901				}
4902				SCTP_TCB_UNLOCK(stcb);
4903			} else {
4904				/************************NO TCB, SET TO default stuff ******************/
4905				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4906				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4907				    (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC)) {
4908					SCTP_INP_WLOCK(inp);
4909					/*
4910					 * For the TOS/FLOWLABEL stuff you
4911					 * set it with the options on the
4912					 * socket
4913					 */
4914					if (paddrp->spp_pathmaxrxt) {
4915						inp->sctp_ep.def_net_failure = paddrp->spp_pathmaxrxt;
4916					}
4917					if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO)
4918						inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
4919					else if (paddrp->spp_hbinterval) {
4920						if (paddrp->spp_hbinterval > SCTP_MAX_HB_INTERVAL)
4921							paddrp->spp_hbinterval = SCTP_MAX_HB_INTERVAL;
4922						inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
4923					}
4924					if (paddrp->spp_flags & SPP_HB_ENABLE) {
4925						if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
4926							inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
4927						} else if (paddrp->spp_hbinterval) {
4928							inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
4929						}
4930						sctp_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
4931					} else if (paddrp->spp_flags & SPP_HB_DISABLE) {
4932						sctp_feature_on(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
4933					}
4934					if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
4935						sctp_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
4936					} else if (paddrp->spp_flags & SPP_PMTUD_DISABLE) {
4937						sctp_feature_on(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
4938					}
4939					if (paddrp->spp_flags & SPP_DSCP) {
4940						inp->sctp_ep.default_dscp = paddrp->spp_dscp & 0xfc;
4941						inp->sctp_ep.default_dscp |= 0x01;
4942					}
4943#ifdef INET6
4944					if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
4945						if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
4946							inp->sctp_ep.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
4947							inp->sctp_ep.default_flowlabel |= 0x80000000;
4948						}
4949					}
4950#endif
4951					SCTP_INP_WUNLOCK(inp);
4952				} else {
4953					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4954					error = EINVAL;
4955				}
4956			}
4957			break;
4958		}
4959	case SCTP_RTOINFO:
4960		{
4961			struct sctp_rtoinfo *srto;
4962			uint32_t new_init, new_min, new_max;
4963
4964			SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, optsize);
4965			SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
4966
4967			if (stcb) {
4968				if (srto->srto_initial)
4969					new_init = srto->srto_initial;
4970				else
4971					new_init = stcb->asoc.initial_rto;
4972				if (srto->srto_max)
4973					new_max = srto->srto_max;
4974				else
4975					new_max = stcb->asoc.maxrto;
4976				if (srto->srto_min)
4977					new_min = srto->srto_min;
4978				else
4979					new_min = stcb->asoc.minrto;
4980				if ((new_min <= new_init) && (new_init <= new_max)) {
4981					stcb->asoc.initial_rto = new_init;
4982					stcb->asoc.maxrto = new_max;
4983					stcb->asoc.minrto = new_min;
4984				} else {
4985					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4986					error = EINVAL;
4987				}
4988				SCTP_TCB_UNLOCK(stcb);
4989			} else {
4990				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4991				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4992				    (srto->srto_assoc_id == SCTP_FUTURE_ASSOC)) {
4993					SCTP_INP_WLOCK(inp);
4994					if (srto->srto_initial)
4995						new_init = srto->srto_initial;
4996					else
4997						new_init = inp->sctp_ep.initial_rto;
4998					if (srto->srto_max)
4999						new_max = srto->srto_max;
5000					else
5001						new_max = inp->sctp_ep.sctp_maxrto;
5002					if (srto->srto_min)
5003						new_min = srto->srto_min;
5004					else
5005						new_min = inp->sctp_ep.sctp_minrto;
5006					if ((new_min <= new_init) && (new_init <= new_max)) {
5007						inp->sctp_ep.initial_rto = new_init;
5008						inp->sctp_ep.sctp_maxrto = new_max;
5009						inp->sctp_ep.sctp_minrto = new_min;
5010					} else {
5011						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5012						error = EINVAL;
5013					}
5014					SCTP_INP_WUNLOCK(inp);
5015				} else {
5016					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5017					error = EINVAL;
5018				}
5019			}
5020			break;
5021		}
5022	case SCTP_ASSOCINFO:
5023		{
5024			struct sctp_assocparams *sasoc;
5025
5026			SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, optsize);
5027			SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
5028			if (sasoc->sasoc_cookie_life) {
5029				/* boundary check the cookie life */
5030				if (sasoc->sasoc_cookie_life < 1000)
5031					sasoc->sasoc_cookie_life = 1000;
5032				if (sasoc->sasoc_cookie_life > SCTP_MAX_COOKIE_LIFE) {
5033					sasoc->sasoc_cookie_life = SCTP_MAX_COOKIE_LIFE;
5034				}
5035			}
5036			if (stcb) {
5037				if (sasoc->sasoc_asocmaxrxt)
5038					stcb->asoc.max_send_times = sasoc->sasoc_asocmaxrxt;
5039				if (sasoc->sasoc_cookie_life) {
5040					stcb->asoc.cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
5041				}
5042				SCTP_TCB_UNLOCK(stcb);
5043			} else {
5044				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5045				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5046				    (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC)) {
5047					SCTP_INP_WLOCK(inp);
5048					if (sasoc->sasoc_asocmaxrxt)
5049						inp->sctp_ep.max_send_times = sasoc->sasoc_asocmaxrxt;
5050					if (sasoc->sasoc_cookie_life) {
5051						inp->sctp_ep.def_cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
5052					}
5053					SCTP_INP_WUNLOCK(inp);
5054				} else {
5055					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5056					error = EINVAL;
5057				}
5058			}
5059			break;
5060		}
5061	case SCTP_INITMSG:
5062		{
5063			struct sctp_initmsg *sinit;
5064
5065			SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, optsize);
5066			SCTP_INP_WLOCK(inp);
5067			if (sinit->sinit_num_ostreams)
5068				inp->sctp_ep.pre_open_stream_count = sinit->sinit_num_ostreams;
5069
5070			if (sinit->sinit_max_instreams)
5071				inp->sctp_ep.max_open_streams_intome = sinit->sinit_max_instreams;
5072
5073			if (sinit->sinit_max_attempts)
5074				inp->sctp_ep.max_init_times = sinit->sinit_max_attempts;
5075
5076			if (sinit->sinit_max_init_timeo)
5077				inp->sctp_ep.initial_init_rto_max = sinit->sinit_max_init_timeo;
5078			SCTP_INP_WUNLOCK(inp);
5079			break;
5080		}
5081	case SCTP_PRIMARY_ADDR:
5082		{
5083			struct sctp_setprim *spa;
5084			struct sctp_nets *net;
5085
5086			SCTP_CHECK_AND_CAST(spa, optval, struct sctp_setprim, optsize);
5087			SCTP_FIND_STCB(inp, stcb, spa->ssp_assoc_id);
5088
5089			net = NULL;
5090			if (stcb) {
5091				net = sctp_findnet(stcb, (struct sockaddr *)&spa->ssp_addr);
5092			} else {
5093				/*
5094				 * We increment here since
5095				 * sctp_findassociation_ep_addr() wil do a
5096				 * decrement if it finds the stcb as long as
5097				 * the locked tcb (last argument) is NOT a
5098				 * TCB.. aka NULL.
5099				 */
5100				SCTP_INP_INCR_REF(inp);
5101				stcb = sctp_findassociation_ep_addr(&inp,
5102				    (struct sockaddr *)&spa->ssp_addr,
5103				    &net, NULL, NULL);
5104				if (stcb == NULL) {
5105					SCTP_INP_DECR_REF(inp);
5106				}
5107			}
5108
5109			if ((stcb) && (net)) {
5110				if ((net != stcb->asoc.primary_destination) &&
5111				    (!(net->dest_state & SCTP_ADDR_UNCONFIRMED))) {
5112					/* Ok we need to set it */
5113					if (sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net) == 0) {
5114						if ((stcb->asoc.alternate) &&
5115						    (!(net->dest_state & SCTP_ADDR_PF)) &&
5116						    (net->dest_state & SCTP_ADDR_REACHABLE)) {
5117							sctp_free_remote_addr(stcb->asoc.alternate);
5118							stcb->asoc.alternate = NULL;
5119						}
5120					}
5121				}
5122			} else {
5123				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5124				error = EINVAL;
5125			}
5126			if (stcb) {
5127				SCTP_TCB_UNLOCK(stcb);
5128			}
5129			break;
5130		}
5131	case SCTP_SET_DYNAMIC_PRIMARY:
5132		{
5133			union sctp_sockstore *ss;
5134
5135			error = priv_check(curthread,
5136			    PRIV_NETINET_RESERVEDPORT);
5137			if (error)
5138				break;
5139
5140			SCTP_CHECK_AND_CAST(ss, optval, union sctp_sockstore, optsize);
5141			/* SUPER USER CHECK? */
5142			error = sctp_dynamic_set_primary(&ss->sa, vrf_id);
5143			break;
5144		}
5145	case SCTP_SET_PEER_PRIMARY_ADDR:
5146		{
5147			struct sctp_setpeerprim *sspp;
5148
5149			SCTP_CHECK_AND_CAST(sspp, optval, struct sctp_setpeerprim, optsize);
5150			SCTP_FIND_STCB(inp, stcb, sspp->sspp_assoc_id);
5151			if (stcb != NULL) {
5152				struct sctp_ifa *ifa;
5153
5154				ifa = sctp_find_ifa_by_addr((struct sockaddr *)&sspp->sspp_addr,
5155				    stcb->asoc.vrf_id, SCTP_ADDR_NOT_LOCKED);
5156				if (ifa == NULL) {
5157					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5158					error = EINVAL;
5159					goto out_of_it;
5160				}
5161				if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
5162					/*
5163					 * Must validate the ifa found is in
5164					 * our ep
5165					 */
5166					struct sctp_laddr *laddr;
5167					int found = 0;
5168
5169					LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
5170						if (laddr->ifa == NULL) {
5171							SCTPDBG(SCTP_DEBUG_OUTPUT1, "%s: NULL ifa\n",
5172							    __FUNCTION__);
5173							continue;
5174						}
5175						if (laddr->ifa == ifa) {
5176							found = 1;
5177							break;
5178						}
5179					}
5180					if (!found) {
5181						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5182						error = EINVAL;
5183						goto out_of_it;
5184					}
5185				}
5186				if (sctp_set_primary_ip_address_sa(stcb,
5187				    (struct sockaddr *)&sspp->sspp_addr) != 0) {
5188					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5189					error = EINVAL;
5190				}
5191		out_of_it:
5192				SCTP_TCB_UNLOCK(stcb);
5193			} else {
5194				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5195				error = EINVAL;
5196			}
5197			break;
5198		}
5199	case SCTP_BINDX_ADD_ADDR:
5200		{
5201			struct sctp_getaddresses *addrs;
5202			size_t sz;
5203			struct thread *td;
5204
5205			td = (struct thread *)p;
5206			SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses,
5207			    optsize);
5208#ifdef INET
5209			if (addrs->addr->sa_family == AF_INET) {
5210				sz = sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in);
5211				if (optsize < sz) {
5212					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5213					error = EINVAL;
5214					break;
5215				}
5216				if (td != NULL && (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)(addrs->addr))->sin_addr)))) {
5217					SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
5218					break;
5219				}
5220			} else
5221#endif
5222#ifdef INET6
5223			if (addrs->addr->sa_family == AF_INET6) {
5224				sz = sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6);
5225				if (optsize < sz) {
5226					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5227					error = EINVAL;
5228					break;
5229				}
5230				if (td != NULL && (error = prison_local_ip6(td->td_ucred, &(((struct sockaddr_in6 *)(addrs->addr))->sin6_addr),
5231				    (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
5232					SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
5233					break;
5234				}
5235			} else
5236#endif
5237			{
5238				error = EAFNOSUPPORT;
5239				break;
5240			}
5241			sctp_bindx_add_address(so, inp, addrs->addr,
5242			    addrs->sget_assoc_id, vrf_id,
5243			    &error, p);
5244			break;
5245		}
5246	case SCTP_BINDX_REM_ADDR:
5247		{
5248			struct sctp_getaddresses *addrs;
5249			size_t sz;
5250			struct thread *td;
5251
5252			td = (struct thread *)p;
5253
5254			SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses, optsize);
5255#ifdef INET
5256			if (addrs->addr->sa_family == AF_INET) {
5257				sz = sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in);
5258				if (optsize < sz) {
5259					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5260					error = EINVAL;
5261					break;
5262				}
5263				if (td != NULL && (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)(addrs->addr))->sin_addr)))) {
5264					SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
5265					break;
5266				}
5267			} else
5268#endif
5269#ifdef INET6
5270			if (addrs->addr->sa_family == AF_INET6) {
5271				sz = sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6);
5272				if (optsize < sz) {
5273					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5274					error = EINVAL;
5275					break;
5276				}
5277				if (td != NULL &&
5278				    (error = prison_local_ip6(td->td_ucred,
5279				    &(((struct sockaddr_in6 *)(addrs->addr))->sin6_addr),
5280				    (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
5281					SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
5282					break;
5283				}
5284			} else
5285#endif
5286			{
5287				error = EAFNOSUPPORT;
5288				break;
5289			}
5290			sctp_bindx_delete_address(so, inp, addrs->addr,
5291			    addrs->sget_assoc_id, vrf_id,
5292			    &error);
5293			break;
5294		}
5295	case SCTP_EVENT:
5296		{
5297			struct sctp_event *event;
5298			uint32_t event_type;
5299
5300			SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, optsize);
5301			SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
5302			switch (event->se_type) {
5303			case SCTP_ASSOC_CHANGE:
5304				event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
5305				break;
5306			case SCTP_PEER_ADDR_CHANGE:
5307				event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
5308				break;
5309			case SCTP_REMOTE_ERROR:
5310				event_type = SCTP_PCB_FLAGS_RECVPEERERR;
5311				break;
5312			case SCTP_SEND_FAILED:
5313				event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
5314				break;
5315			case SCTP_SHUTDOWN_EVENT:
5316				event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
5317				break;
5318			case SCTP_ADAPTATION_INDICATION:
5319				event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
5320				break;
5321			case SCTP_PARTIAL_DELIVERY_EVENT:
5322				event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
5323				break;
5324			case SCTP_AUTHENTICATION_EVENT:
5325				event_type = SCTP_PCB_FLAGS_AUTHEVNT;
5326				break;
5327			case SCTP_STREAM_RESET_EVENT:
5328				event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
5329				break;
5330			case SCTP_SENDER_DRY_EVENT:
5331				event_type = SCTP_PCB_FLAGS_DRYEVNT;
5332				break;
5333			case SCTP_NOTIFICATIONS_STOPPED_EVENT:
5334				event_type = 0;
5335				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
5336				error = ENOTSUP;
5337				break;
5338			default:
5339				event_type = 0;
5340				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5341				error = EINVAL;
5342				break;
5343			}
5344			if (event_type > 0) {
5345				if (stcb) {
5346					if (event->se_on) {
5347						sctp_stcb_feature_on(inp, stcb, event_type);
5348						if (event_type == SCTP_PCB_FLAGS_DRYEVNT) {
5349							if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
5350							    TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
5351							    (stcb->asoc.stream_queue_cnt == 0)) {
5352								sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_LOCKED);
5353							}
5354						}
5355					} else {
5356						sctp_stcb_feature_off(inp, stcb, event_type);
5357					}
5358					SCTP_TCB_UNLOCK(stcb);
5359				} else {
5360					/*
5361					 * We don't want to send up a storm
5362					 * of events, so return an error for
5363					 * sender dry events
5364					 */
5365					if ((event_type == SCTP_PCB_FLAGS_DRYEVNT) &&
5366					    ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) == 0) &&
5367					    ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
5368					    ((event->se_assoc_id == SCTP_ALL_ASSOC) ||
5369					    (event->se_assoc_id == SCTP_CURRENT_ASSOC))) {
5370						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
5371						error = ENOTSUP;
5372						break;
5373					}
5374					if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5375					    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5376					    (event->se_assoc_id == SCTP_FUTURE_ASSOC) ||
5377					    (event->se_assoc_id == SCTP_ALL_ASSOC)) {
5378						SCTP_INP_WLOCK(inp);
5379						if (event->se_on) {
5380							sctp_feature_on(inp, event_type);
5381						} else {
5382							sctp_feature_off(inp, event_type);
5383						}
5384						SCTP_INP_WUNLOCK(inp);
5385					}
5386					if ((event->se_assoc_id == SCTP_CURRENT_ASSOC) ||
5387					    (event->se_assoc_id == SCTP_ALL_ASSOC)) {
5388						SCTP_INP_RLOCK(inp);
5389						LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5390							SCTP_TCB_LOCK(stcb);
5391							if (event->se_on) {
5392								sctp_stcb_feature_on(inp, stcb, event_type);
5393							} else {
5394								sctp_stcb_feature_off(inp, stcb, event_type);
5395							}
5396							SCTP_TCB_UNLOCK(stcb);
5397						}
5398						SCTP_INP_RUNLOCK(inp);
5399					}
5400				}
5401			}
5402			break;
5403		}
5404	case SCTP_RECVRCVINFO:
5405		{
5406			int *onoff;
5407
5408			SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
5409			SCTP_INP_WLOCK(inp);
5410			if (*onoff != 0) {
5411				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
5412			} else {
5413				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
5414			}
5415			SCTP_INP_WUNLOCK(inp);
5416			break;
5417		}
5418	case SCTP_RECVNXTINFO:
5419		{
5420			int *onoff;
5421
5422			SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
5423			SCTP_INP_WLOCK(inp);
5424			if (*onoff != 0) {
5425				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
5426			} else {
5427				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
5428			}
5429			SCTP_INP_WUNLOCK(inp);
5430			break;
5431		}
5432	case SCTP_DEFAULT_SNDINFO:
5433		{
5434			struct sctp_sndinfo *info;
5435			uint16_t policy;
5436
5437			SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, optsize);
5438			SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
5439
5440			if (stcb) {
5441				if (info->snd_sid < stcb->asoc.streamoutcnt) {
5442					stcb->asoc.def_send.sinfo_stream = info->snd_sid;
5443					policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
5444					stcb->asoc.def_send.sinfo_flags = info->snd_flags;
5445					stcb->asoc.def_send.sinfo_flags |= policy;
5446					stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
5447					stcb->asoc.def_send.sinfo_context = info->snd_context;
5448				} else {
5449					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5450					error = EINVAL;
5451				}
5452				SCTP_TCB_UNLOCK(stcb);
5453			} else {
5454				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5455				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5456				    (info->snd_assoc_id == SCTP_FUTURE_ASSOC) ||
5457				    (info->snd_assoc_id == SCTP_ALL_ASSOC)) {
5458					SCTP_INP_WLOCK(inp);
5459					inp->def_send.sinfo_stream = info->snd_sid;
5460					policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
5461					inp->def_send.sinfo_flags = info->snd_flags;
5462					inp->def_send.sinfo_flags |= policy;
5463					inp->def_send.sinfo_ppid = info->snd_ppid;
5464					inp->def_send.sinfo_context = info->snd_context;
5465					SCTP_INP_WUNLOCK(inp);
5466				}
5467				if ((info->snd_assoc_id == SCTP_CURRENT_ASSOC) ||
5468				    (info->snd_assoc_id == SCTP_ALL_ASSOC)) {
5469					SCTP_INP_RLOCK(inp);
5470					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5471						SCTP_TCB_LOCK(stcb);
5472						if (info->snd_sid < stcb->asoc.streamoutcnt) {
5473							stcb->asoc.def_send.sinfo_stream = info->snd_sid;
5474							policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
5475							stcb->asoc.def_send.sinfo_flags = info->snd_flags;
5476							stcb->asoc.def_send.sinfo_flags |= policy;
5477							stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
5478							stcb->asoc.def_send.sinfo_context = info->snd_context;
5479						}
5480						SCTP_TCB_UNLOCK(stcb);
5481					}
5482					SCTP_INP_RUNLOCK(inp);
5483				}
5484			}
5485			break;
5486		}
5487	case SCTP_DEFAULT_PRINFO:
5488		{
5489			struct sctp_default_prinfo *info;
5490
5491			SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, optsize);
5492			SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
5493
5494			if (PR_SCTP_INVALID_POLICY(info->pr_policy)) {
5495				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5496				error = EINVAL;
5497				break;
5498			}
5499			if (stcb) {
5500				stcb->asoc.def_send.sinfo_flags &= 0xfff0;
5501				stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
5502				stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
5503				SCTP_TCB_UNLOCK(stcb);
5504			} else {
5505				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5506				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5507				    (info->pr_assoc_id == SCTP_FUTURE_ASSOC) ||
5508				    (info->pr_assoc_id == SCTP_ALL_ASSOC)) {
5509					SCTP_INP_WLOCK(inp);
5510					inp->def_send.sinfo_flags &= 0xfff0;
5511					inp->def_send.sinfo_flags |= info->pr_policy;
5512					inp->def_send.sinfo_timetolive = info->pr_value;
5513					SCTP_INP_WUNLOCK(inp);
5514				}
5515				if ((info->pr_assoc_id == SCTP_CURRENT_ASSOC) ||
5516				    (info->pr_assoc_id == SCTP_ALL_ASSOC)) {
5517					SCTP_INP_RLOCK(inp);
5518					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5519						SCTP_TCB_LOCK(stcb);
5520						stcb->asoc.def_send.sinfo_flags &= 0xfff0;
5521						stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
5522						stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
5523						SCTP_TCB_UNLOCK(stcb);
5524					}
5525					SCTP_INP_RUNLOCK(inp);
5526				}
5527			}
5528			break;
5529		}
5530	case SCTP_PEER_ADDR_THLDS:
5531		/* Applies to the specific association */
5532		{
5533			struct sctp_paddrthlds *thlds;
5534			struct sctp_nets *net;
5535
5536			SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, optsize);
5537			SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
5538			net = NULL;
5539			if (stcb) {
5540				net = sctp_findnet(stcb, (struct sockaddr *)&thlds->spt_assoc_id);
5541			} else {
5542				/*
5543				 * We increment here since
5544				 * sctp_findassociation_ep_addr() wil do a
5545				 * decrement if it finds the stcb as long as
5546				 * the locked tcb (last argument) is NOT a
5547				 * TCB.. aka NULL.
5548				 */
5549				SCTP_INP_INCR_REF(inp);
5550				stcb = sctp_findassociation_ep_addr(&inp,
5551				    (struct sockaddr *)&thlds->spt_assoc_id,
5552				    &net, NULL, NULL);
5553				if (stcb == NULL) {
5554					SCTP_INP_DECR_REF(inp);
5555				}
5556			}
5557			if (stcb && (net == NULL)) {
5558				struct sockaddr *sa;
5559
5560				sa = (struct sockaddr *)&thlds->spt_assoc_id;
5561#ifdef INET
5562				if (sa->sa_family == AF_INET) {
5563
5564					struct sockaddr_in *sin;
5565
5566					sin = (struct sockaddr_in *)sa;
5567					if (sin->sin_addr.s_addr) {
5568						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5569						SCTP_TCB_UNLOCK(stcb);
5570						error = EINVAL;
5571						break;
5572					}
5573				} else
5574#endif
5575#ifdef INET6
5576				if (sa->sa_family == AF_INET6) {
5577					struct sockaddr_in6 *sin6;
5578
5579					sin6 = (struct sockaddr_in6 *)sa;
5580					if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
5581						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5582						SCTP_TCB_UNLOCK(stcb);
5583						error = EINVAL;
5584						break;
5585					}
5586				} else
5587#endif
5588				{
5589					error = EAFNOSUPPORT;
5590					SCTP_TCB_UNLOCK(stcb);
5591					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
5592					break;
5593				}
5594			}
5595			if (stcb) {
5596				if (net) {
5597					if (net->dest_state & SCTP_ADDR_PF) {
5598						if ((net->failure_threshold > thlds->spt_pathmaxrxt) ||
5599						    (net->failure_threshold <= thlds->spt_pathpfthld)) {
5600							net->dest_state &= ~SCTP_ADDR_PF;
5601						}
5602					} else {
5603						if ((net->failure_threshold > thlds->spt_pathpfthld) &&
5604						    (net->failure_threshold <= thlds->spt_pathmaxrxt)) {
5605							net->dest_state |= SCTP_ADDR_PF;
5606							sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5607							sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
5608							sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
5609						}
5610					}
5611					if (net->dest_state & SCTP_ADDR_REACHABLE) {
5612						if (net->failure_threshold > thlds->spt_pathmaxrxt) {
5613							net->dest_state &= ~SCTP_ADDR_REACHABLE;
5614							sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, SCTP_RESPONSE_TO_USER_REQ, net, SCTP_SO_LOCKED);
5615						}
5616					} else {
5617						if (net->failure_threshold <= thlds->spt_pathmaxrxt) {
5618							net->dest_state |= SCTP_ADDR_REACHABLE;
5619							sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, SCTP_RESPONSE_TO_USER_REQ, net, SCTP_SO_LOCKED);
5620						}
5621					}
5622					net->failure_threshold = thlds->spt_pathmaxrxt;
5623					net->pf_threshold = thlds->spt_pathpfthld;
5624				} else {
5625					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5626						if (net->dest_state & SCTP_ADDR_PF) {
5627							if ((net->failure_threshold > thlds->spt_pathmaxrxt) ||
5628							    (net->failure_threshold <= thlds->spt_pathpfthld)) {
5629								net->dest_state &= ~SCTP_ADDR_PF;
5630							}
5631						} else {
5632							if ((net->failure_threshold > thlds->spt_pathpfthld) &&
5633							    (net->failure_threshold <= thlds->spt_pathmaxrxt)) {
5634								net->dest_state |= SCTP_ADDR_PF;
5635								sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5636								sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
5637								sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
5638							}
5639						}
5640						if (net->dest_state & SCTP_ADDR_REACHABLE) {
5641							if (net->failure_threshold > thlds->spt_pathmaxrxt) {
5642								net->dest_state &= ~SCTP_ADDR_REACHABLE;
5643								sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, SCTP_RESPONSE_TO_USER_REQ, net, SCTP_SO_LOCKED);
5644							}
5645						} else {
5646							if (net->failure_threshold <= thlds->spt_pathmaxrxt) {
5647								net->dest_state |= SCTP_ADDR_REACHABLE;
5648								sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, SCTP_RESPONSE_TO_USER_REQ, net, SCTP_SO_LOCKED);
5649							}
5650						}
5651						net->failure_threshold = thlds->spt_pathmaxrxt;
5652						net->pf_threshold = thlds->spt_pathpfthld;
5653					}
5654					stcb->asoc.def_net_failure = thlds->spt_pathmaxrxt;
5655					stcb->asoc.def_net_pf_threshold = thlds->spt_pathpfthld;
5656				}
5657			} else {
5658				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5659				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5660				    (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC)) {
5661					SCTP_INP_WLOCK(inp);
5662					inp->sctp_ep.def_net_failure = thlds->spt_pathmaxrxt;
5663					inp->sctp_ep.def_net_pf_threshold = thlds->spt_pathpfthld;
5664					SCTP_INP_WUNLOCK(inp);
5665				} else {
5666					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5667					error = EINVAL;
5668				}
5669			}
5670			break;
5671		}
5672	case SCTP_REMOTE_UDP_ENCAPS_PORT:
5673		{
5674			struct sctp_udpencaps *encaps;
5675			struct sctp_nets *net;
5676
5677			SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, optsize);
5678			SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
5679			if (stcb) {
5680				net = sctp_findnet(stcb, (struct sockaddr *)&encaps->sue_address);
5681			} else {
5682				/*
5683				 * We increment here since
5684				 * sctp_findassociation_ep_addr() wil do a
5685				 * decrement if it finds the stcb as long as
5686				 * the locked tcb (last argument) is NOT a
5687				 * TCB.. aka NULL.
5688				 */
5689				net = NULL;
5690				SCTP_INP_INCR_REF(inp);
5691				stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&encaps->sue_address, &net, NULL, NULL);
5692				if (stcb == NULL) {
5693					SCTP_INP_DECR_REF(inp);
5694				}
5695			}
5696			if (stcb && (net == NULL)) {
5697				struct sockaddr *sa;
5698
5699				sa = (struct sockaddr *)&encaps->sue_address;
5700#ifdef INET
5701				if (sa->sa_family == AF_INET) {
5702
5703					struct sockaddr_in *sin;
5704
5705					sin = (struct sockaddr_in *)sa;
5706					if (sin->sin_addr.s_addr) {
5707						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5708						SCTP_TCB_UNLOCK(stcb);
5709						error = EINVAL;
5710						break;
5711					}
5712				} else
5713#endif
5714#ifdef INET6
5715				if (sa->sa_family == AF_INET6) {
5716					struct sockaddr_in6 *sin6;
5717
5718					sin6 = (struct sockaddr_in6 *)sa;
5719					if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
5720						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5721						SCTP_TCB_UNLOCK(stcb);
5722						error = EINVAL;
5723						break;
5724					}
5725				} else
5726#endif
5727				{
5728					error = EAFNOSUPPORT;
5729					SCTP_TCB_UNLOCK(stcb);
5730					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
5731					break;
5732				}
5733			}
5734			if (stcb) {
5735				if (net) {
5736					net->port = encaps->sue_port;
5737				} else {
5738					stcb->asoc.port = encaps->sue_port;
5739				}
5740				SCTP_TCB_UNLOCK(stcb);
5741			} else {
5742				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5743				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5744				    (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC)) {
5745					SCTP_INP_WLOCK(inp);
5746					inp->sctp_ep.port = encaps->sue_port;
5747					SCTP_INP_WUNLOCK(inp);
5748				} else {
5749					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5750					error = EINVAL;
5751				}
5752			}
5753			break;
5754		}
5755	default:
5756		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
5757		error = ENOPROTOOPT;
5758		break;
5759	}			/* end switch (opt) */
5760	return (error);
5761}
5762
5763int
5764sctp_ctloutput(struct socket *so, struct sockopt *sopt)
5765{
5766	void *optval = NULL;
5767	size_t optsize = 0;
5768	struct sctp_inpcb *inp;
5769	void *p;
5770	int error = 0;
5771
5772	inp = (struct sctp_inpcb *)so->so_pcb;
5773	if (inp == 0) {
5774		/* I made the same as TCP since we are not setup? */
5775		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5776		return (ECONNRESET);
5777	}
5778	if (sopt->sopt_level != IPPROTO_SCTP) {
5779		/* wrong proto level... send back up to IP */
5780#ifdef INET6
5781		if (INP_CHECK_SOCKAF(so, AF_INET6))
5782			error = ip6_ctloutput(so, sopt);
5783#endif				/* INET6 */
5784#if defined(INET) && defined (INET6)
5785		else
5786#endif
5787#ifdef INET
5788			error = ip_ctloutput(so, sopt);
5789#endif
5790		return (error);
5791	}
5792	optsize = sopt->sopt_valsize;
5793	if (optsize) {
5794		SCTP_MALLOC(optval, void *, optsize, SCTP_M_SOCKOPT);
5795		if (optval == NULL) {
5796			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS);
5797			return (ENOBUFS);
5798		}
5799		error = sooptcopyin(sopt, optval, optsize, optsize);
5800		if (error) {
5801			SCTP_FREE(optval, SCTP_M_SOCKOPT);
5802			goto out;
5803		}
5804	}
5805	p = (void *)sopt->sopt_td;
5806	if (sopt->sopt_dir == SOPT_SET) {
5807		error = sctp_setopt(so, sopt->sopt_name, optval, optsize, p);
5808	} else if (sopt->sopt_dir == SOPT_GET) {
5809		error = sctp_getopt(so, sopt->sopt_name, optval, &optsize, p);
5810	} else {
5811		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5812		error = EINVAL;
5813	}
5814	if ((error == 0) && (optval != NULL)) {
5815		error = sooptcopyout(sopt, optval, optsize);
5816		SCTP_FREE(optval, SCTP_M_SOCKOPT);
5817	} else if (optval != NULL) {
5818		SCTP_FREE(optval, SCTP_M_SOCKOPT);
5819	}
5820out:
5821	return (error);
5822}
5823
5824#ifdef INET
5825static int
5826sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
5827{
5828	int error = 0;
5829	int create_lock_on = 0;
5830	uint32_t vrf_id;
5831	struct sctp_inpcb *inp;
5832	struct sctp_tcb *stcb = NULL;
5833
5834	inp = (struct sctp_inpcb *)so->so_pcb;
5835	if (inp == 0) {
5836		/* I made the same as TCP since we are not setup? */
5837		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5838		return (ECONNRESET);
5839	}
5840	if (addr == NULL) {
5841		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5842		return EINVAL;
5843	}
5844	switch (addr->sa_family) {
5845#ifdef INET6
5846	case AF_INET6:
5847		{
5848			struct sockaddr_in6 *sin6p;
5849
5850			if (addr->sa_len != sizeof(struct sockaddr_in6)) {
5851				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5852				return (EINVAL);
5853			}
5854			sin6p = (struct sockaddr_in6 *)addr;
5855			if (p != NULL && (error = prison_remote_ip6(p->td_ucred, &sin6p->sin6_addr)) != 0) {
5856				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
5857				return (error);
5858			}
5859			break;
5860		}
5861#endif
5862#ifdef INET
5863	case AF_INET:
5864		{
5865			struct sockaddr_in *sinp;
5866
5867			if (addr->sa_len != sizeof(struct sockaddr_in)) {
5868				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5869				return (EINVAL);
5870			}
5871			sinp = (struct sockaddr_in *)addr;
5872			if (p != NULL && (error = prison_remote_ip4(p->td_ucred, &sinp->sin_addr)) != 0) {
5873				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
5874				return (error);
5875			}
5876			break;
5877		}
5878#endif
5879	default:
5880		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
5881		return (EAFNOSUPPORT);
5882	}
5883	SCTP_INP_INCR_REF(inp);
5884	SCTP_ASOC_CREATE_LOCK(inp);
5885	create_lock_on = 1;
5886
5887
5888	if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
5889	    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
5890		/* Should I really unlock ? */
5891		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
5892		error = EFAULT;
5893		goto out_now;
5894	}
5895#ifdef INET6
5896	if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
5897	    (addr->sa_family == AF_INET6)) {
5898		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5899		error = EINVAL;
5900		goto out_now;
5901	}
5902#endif				/* INET6 */
5903	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
5904	    SCTP_PCB_FLAGS_UNBOUND) {
5905		/* Bind a ephemeral port */
5906		error = sctp_inpcb_bind(so, NULL, NULL, p);
5907		if (error) {
5908			goto out_now;
5909		}
5910	}
5911	/* Now do we connect? */
5912	if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
5913	    (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
5914		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5915		error = EINVAL;
5916		goto out_now;
5917	}
5918	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
5919	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
5920		/* We are already connected AND the TCP model */
5921		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
5922		error = EADDRINUSE;
5923		goto out_now;
5924	}
5925	if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
5926		SCTP_INP_RLOCK(inp);
5927		stcb = LIST_FIRST(&inp->sctp_asoc_list);
5928		SCTP_INP_RUNLOCK(inp);
5929	} else {
5930		/*
5931		 * We increment here since sctp_findassociation_ep_addr()
5932		 * will do a decrement if it finds the stcb as long as the
5933		 * locked tcb (last argument) is NOT a TCB.. aka NULL.
5934		 */
5935		SCTP_INP_INCR_REF(inp);
5936		stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
5937		if (stcb == NULL) {
5938			SCTP_INP_DECR_REF(inp);
5939		} else {
5940			SCTP_TCB_UNLOCK(stcb);
5941		}
5942	}
5943	if (stcb != NULL) {
5944		/* Already have or am bring up an association */
5945		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
5946		error = EALREADY;
5947		goto out_now;
5948	}
5949	vrf_id = inp->def_vrf_id;
5950	/* We are GOOD to go */
5951	stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, p);
5952	if (stcb == NULL) {
5953		/* Gak! no memory */
5954		goto out_now;
5955	}
5956	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
5957		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
5958		/* Set the connected flag so we can queue data */
5959		soisconnecting(so);
5960	}
5961	SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
5962	(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
5963
5964	/* initialize authentication parameters for the assoc */
5965	sctp_initialize_auth_params(inp, stcb);
5966
5967	sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
5968	SCTP_TCB_UNLOCK(stcb);
5969out_now:
5970	if (create_lock_on) {
5971		SCTP_ASOC_CREATE_UNLOCK(inp);
5972	}
5973	SCTP_INP_DECR_REF(inp);
5974	return error;
5975}
5976
5977#endif
5978
5979int
5980sctp_listen(struct socket *so, int backlog, struct thread *p)
5981{
5982	/*
5983	 * Note this module depends on the protocol processing being called
5984	 * AFTER any socket level flags and backlog are applied to the
5985	 * socket. The traditional way that the socket flags are applied is
5986	 * AFTER protocol processing. We have made a change to the
5987	 * sys/kern/uipc_socket.c module to reverse this but this MUST be in
5988	 * place if the socket API for SCTP is to work properly.
5989	 */
5990
5991	int error = 0;
5992	struct sctp_inpcb *inp;
5993
5994	inp = (struct sctp_inpcb *)so->so_pcb;
5995	if (inp == 0) {
5996		/* I made the same as TCP since we are not setup? */
5997		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5998		return (ECONNRESET);
5999	}
6000	if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) {
6001		/* See if we have a listener */
6002		struct sctp_inpcb *tinp;
6003		union sctp_sockstore store, *sp;
6004
6005		sp = &store;
6006		if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
6007			/* not bound all */
6008			struct sctp_laddr *laddr;
6009
6010			LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
6011				memcpy(&store, &laddr->ifa->address, sizeof(store));
6012				switch (sp->sa.sa_family) {
6013#ifdef INET
6014				case AF_INET:
6015					sp->sin.sin_port = inp->sctp_lport;
6016					break;
6017#endif
6018#ifdef INET6
6019				case AF_INET6:
6020					sp->sin6.sin6_port = inp->sctp_lport;
6021					break;
6022#endif
6023				default:
6024					break;
6025				}
6026				tinp = sctp_pcb_findep(&sp->sa, 0, 0, inp->def_vrf_id);
6027				if (tinp && (tinp != inp) &&
6028				    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
6029				    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
6030				    (tinp->sctp_socket->so_qlimit)) {
6031					/*
6032					 * we have a listener already and
6033					 * its not this inp.
6034					 */
6035					SCTP_INP_DECR_REF(tinp);
6036					return (EADDRINUSE);
6037				} else if (tinp) {
6038					SCTP_INP_DECR_REF(tinp);
6039				}
6040			}
6041		} else {
6042			/* Setup a local addr bound all */
6043			memset(&store, 0, sizeof(store));
6044			switch (sp->sa.sa_family) {
6045#ifdef INET
6046			case AF_INET:
6047				store.sin.sin_port = inp->sctp_lport;
6048				break;
6049#endif
6050#ifdef INET6
6051			case AF_INET6:
6052				sp->sin6.sin6_port = inp->sctp_lport;
6053				break;
6054#endif
6055			default:
6056				break;
6057			}
6058#ifdef INET6
6059			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
6060				store.sa.sa_family = AF_INET6;
6061				store.sa.sa_len = sizeof(struct sockaddr_in6);
6062			}
6063#endif
6064#ifdef INET
6065			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
6066				store.sa.sa_family = AF_INET;
6067				store.sa.sa_len = sizeof(struct sockaddr_in);
6068			}
6069#endif
6070			tinp = sctp_pcb_findep(&sp->sa, 0, 0, inp->def_vrf_id);
6071			if (tinp && (tinp != inp) &&
6072			    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
6073			    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
6074			    (tinp->sctp_socket->so_qlimit)) {
6075				/*
6076				 * we have a listener already and its not
6077				 * this inp.
6078				 */
6079				SCTP_INP_DECR_REF(tinp);
6080				return (EADDRINUSE);
6081			} else if (tinp) {
6082				SCTP_INP_DECR_REF(inp);
6083			}
6084		}
6085	}
6086	SCTP_INP_RLOCK(inp);
6087#ifdef SCTP_LOCK_LOGGING
6088	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) {
6089		sctp_log_lock(inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_SOCK);
6090	}
6091#endif
6092	SOCK_LOCK(so);
6093	error = solisten_proto_check(so);
6094	if (error) {
6095		SOCK_UNLOCK(so);
6096		SCTP_INP_RUNLOCK(inp);
6097		return (error);
6098	}
6099	if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) &&
6100	    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
6101		/*
6102		 * The unlucky case - We are in the tcp pool with this guy.
6103		 * - Someone else is in the main inp slot. - We must move
6104		 * this guy (the listener) to the main slot - We must then
6105		 * move the guy that was listener to the TCP Pool.
6106		 */
6107		if (sctp_swap_inpcb_for_listen(inp)) {
6108			goto in_use;
6109		}
6110	}
6111	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
6112	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
6113		/* We are already connected AND the TCP model */
6114in_use:
6115		SCTP_INP_RUNLOCK(inp);
6116		SOCK_UNLOCK(so);
6117		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
6118		return (EADDRINUSE);
6119	}
6120	SCTP_INP_RUNLOCK(inp);
6121	if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
6122		/* We must do a bind. */
6123		SOCK_UNLOCK(so);
6124		if ((error = sctp_inpcb_bind(so, NULL, NULL, p))) {
6125			/* bind error, probably perm */
6126			return (error);
6127		}
6128		SOCK_LOCK(so);
6129	}
6130	/* It appears for 7.0 and on, we must always call this. */
6131	solisten_proto(so, backlog);
6132	if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
6133		/* remove the ACCEPTCONN flag for one-to-many sockets */
6134		so->so_options &= ~SO_ACCEPTCONN;
6135	}
6136	if (backlog == 0) {
6137		/* turning off listen */
6138		so->so_options &= ~SO_ACCEPTCONN;
6139	}
6140	SOCK_UNLOCK(so);
6141	return (error);
6142}
6143
6144static int sctp_defered_wakeup_cnt = 0;
6145
6146int
6147sctp_accept(struct socket *so, struct sockaddr **addr)
6148{
6149	struct sctp_tcb *stcb;
6150	struct sctp_inpcb *inp;
6151	union sctp_sockstore store;
6152
6153#ifdef INET6
6154	int error;
6155
6156#endif
6157	inp = (struct sctp_inpcb *)so->so_pcb;
6158
6159	if (inp == 0) {
6160		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6161		return (ECONNRESET);
6162	}
6163	SCTP_INP_RLOCK(inp);
6164	if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
6165		SCTP_INP_RUNLOCK(inp);
6166		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
6167		return (EOPNOTSUPP);
6168	}
6169	if (so->so_state & SS_ISDISCONNECTED) {
6170		SCTP_INP_RUNLOCK(inp);
6171		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ECONNABORTED);
6172		return (ECONNABORTED);
6173	}
6174	stcb = LIST_FIRST(&inp->sctp_asoc_list);
6175	if (stcb == NULL) {
6176		SCTP_INP_RUNLOCK(inp);
6177		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6178		return (ECONNRESET);
6179	}
6180	SCTP_TCB_LOCK(stcb);
6181	SCTP_INP_RUNLOCK(inp);
6182	store = stcb->asoc.primary_destination->ro._l_addr;
6183	stcb->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE;
6184	SCTP_TCB_UNLOCK(stcb);
6185	switch (store.sa.sa_family) {
6186#ifdef INET
6187	case AF_INET:
6188		{
6189			struct sockaddr_in *sin;
6190
6191			SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
6192			if (sin == NULL)
6193				return (ENOMEM);
6194			sin->sin_family = AF_INET;
6195			sin->sin_len = sizeof(*sin);
6196			sin->sin_port = ((struct sockaddr_in *)&store)->sin_port;
6197			sin->sin_addr = ((struct sockaddr_in *)&store)->sin_addr;
6198			*addr = (struct sockaddr *)sin;
6199			break;
6200		}
6201#endif
6202#ifdef INET6
6203	case AF_INET6:
6204		{
6205			struct sockaddr_in6 *sin6;
6206
6207			SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
6208			if (sin6 == NULL)
6209				return (ENOMEM);
6210			sin6->sin6_family = AF_INET6;
6211			sin6->sin6_len = sizeof(*sin6);
6212			sin6->sin6_port = ((struct sockaddr_in6 *)&store)->sin6_port;
6213
6214			sin6->sin6_addr = ((struct sockaddr_in6 *)&store)->sin6_addr;
6215			if ((error = sa6_recoverscope(sin6)) != 0) {
6216				SCTP_FREE_SONAME(sin6);
6217				return (error);
6218			}
6219			*addr = (struct sockaddr *)sin6;
6220			break;
6221		}
6222#endif
6223	default:
6224		/* TSNH */
6225		break;
6226	}
6227	/* Wake any delayed sleep action */
6228	if (inp->sctp_flags & SCTP_PCB_FLAGS_DONT_WAKE) {
6229		SCTP_INP_WLOCK(inp);
6230		inp->sctp_flags &= ~SCTP_PCB_FLAGS_DONT_WAKE;
6231		if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEOUTPUT) {
6232			inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEOUTPUT;
6233			SCTP_INP_WUNLOCK(inp);
6234			SOCKBUF_LOCK(&inp->sctp_socket->so_snd);
6235			if (sowriteable(inp->sctp_socket)) {
6236				sowwakeup_locked(inp->sctp_socket);
6237			} else {
6238				SOCKBUF_UNLOCK(&inp->sctp_socket->so_snd);
6239			}
6240			SCTP_INP_WLOCK(inp);
6241		}
6242		if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEINPUT) {
6243			inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEINPUT;
6244			SCTP_INP_WUNLOCK(inp);
6245			SOCKBUF_LOCK(&inp->sctp_socket->so_rcv);
6246			if (soreadable(inp->sctp_socket)) {
6247				sctp_defered_wakeup_cnt++;
6248				sorwakeup_locked(inp->sctp_socket);
6249			} else {
6250				SOCKBUF_UNLOCK(&inp->sctp_socket->so_rcv);
6251			}
6252			SCTP_INP_WLOCK(inp);
6253		}
6254		SCTP_INP_WUNLOCK(inp);
6255	}
6256	if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
6257		SCTP_TCB_LOCK(stcb);
6258		sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_7);
6259	}
6260	return (0);
6261}
6262
6263#ifdef INET
6264int
6265sctp_ingetaddr(struct socket *so, struct sockaddr **addr)
6266{
6267	struct sockaddr_in *sin;
6268	uint32_t vrf_id;
6269	struct sctp_inpcb *inp;
6270	struct sctp_ifa *sctp_ifa;
6271
6272	/*
6273	 * Do the malloc first in case it blocks.
6274	 */
6275	SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
6276	if (sin == NULL)
6277		return (ENOMEM);
6278	sin->sin_family = AF_INET;
6279	sin->sin_len = sizeof(*sin);
6280	inp = (struct sctp_inpcb *)so->so_pcb;
6281	if (!inp) {
6282		SCTP_FREE_SONAME(sin);
6283		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6284		return ECONNRESET;
6285	}
6286	SCTP_INP_RLOCK(inp);
6287	sin->sin_port = inp->sctp_lport;
6288	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
6289		if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
6290			struct sctp_tcb *stcb;
6291			struct sockaddr_in *sin_a;
6292			struct sctp_nets *net;
6293			int fnd;
6294
6295			stcb = LIST_FIRST(&inp->sctp_asoc_list);
6296			if (stcb == NULL) {
6297				goto notConn;
6298			}
6299			fnd = 0;
6300			sin_a = NULL;
6301			SCTP_TCB_LOCK(stcb);
6302			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6303				sin_a = (struct sockaddr_in *)&net->ro._l_addr;
6304				if (sin_a == NULL)
6305					/* this will make coverity happy */
6306					continue;
6307
6308				if (sin_a->sin_family == AF_INET) {
6309					fnd = 1;
6310					break;
6311				}
6312			}
6313			if ((!fnd) || (sin_a == NULL)) {
6314				/* punt */
6315				SCTP_TCB_UNLOCK(stcb);
6316				goto notConn;
6317			}
6318			vrf_id = inp->def_vrf_id;
6319			sctp_ifa = sctp_source_address_selection(inp,
6320			    stcb,
6321			    (sctp_route_t *) & net->ro,
6322			    net, 0, vrf_id);
6323			if (sctp_ifa) {
6324				sin->sin_addr = sctp_ifa->address.sin.sin_addr;
6325				sctp_free_ifa(sctp_ifa);
6326			}
6327			SCTP_TCB_UNLOCK(stcb);
6328		} else {
6329			/* For the bound all case you get back 0 */
6330	notConn:
6331			sin->sin_addr.s_addr = 0;
6332		}
6333
6334	} else {
6335		/* Take the first IPv4 address in the list */
6336		struct sctp_laddr *laddr;
6337		int fnd = 0;
6338
6339		LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
6340			if (laddr->ifa->address.sa.sa_family == AF_INET) {
6341				struct sockaddr_in *sin_a;
6342
6343				sin_a = (struct sockaddr_in *)&laddr->ifa->address.sa;
6344				sin->sin_addr = sin_a->sin_addr;
6345				fnd = 1;
6346				break;
6347			}
6348		}
6349		if (!fnd) {
6350			SCTP_FREE_SONAME(sin);
6351			SCTP_INP_RUNLOCK(inp);
6352			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
6353			return ENOENT;
6354		}
6355	}
6356	SCTP_INP_RUNLOCK(inp);
6357	(*addr) = (struct sockaddr *)sin;
6358	return (0);
6359}
6360
6361int
6362sctp_peeraddr(struct socket *so, struct sockaddr **addr)
6363{
6364	struct sockaddr_in *sin = (struct sockaddr_in *)*addr;
6365	int fnd;
6366	struct sockaddr_in *sin_a;
6367	struct sctp_inpcb *inp;
6368	struct sctp_tcb *stcb;
6369	struct sctp_nets *net;
6370
6371	/* Do the malloc first in case it blocks. */
6372	inp = (struct sctp_inpcb *)so->so_pcb;
6373	if ((inp == NULL) ||
6374	    ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
6375		/* UDP type and listeners will drop out here */
6376		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
6377		return (ENOTCONN);
6378	}
6379	SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
6380	if (sin == NULL)
6381		return (ENOMEM);
6382	sin->sin_family = AF_INET;
6383	sin->sin_len = sizeof(*sin);
6384
6385	/* We must recapture incase we blocked */
6386	inp = (struct sctp_inpcb *)so->so_pcb;
6387	if (!inp) {
6388		SCTP_FREE_SONAME(sin);
6389		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6390		return ECONNRESET;
6391	}
6392	SCTP_INP_RLOCK(inp);
6393	stcb = LIST_FIRST(&inp->sctp_asoc_list);
6394	if (stcb) {
6395		SCTP_TCB_LOCK(stcb);
6396	}
6397	SCTP_INP_RUNLOCK(inp);
6398	if (stcb == NULL) {
6399		SCTP_FREE_SONAME(sin);
6400		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6401		return ECONNRESET;
6402	}
6403	fnd = 0;
6404	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6405		sin_a = (struct sockaddr_in *)&net->ro._l_addr;
6406		if (sin_a->sin_family == AF_INET) {
6407			fnd = 1;
6408			sin->sin_port = stcb->rport;
6409			sin->sin_addr = sin_a->sin_addr;
6410			break;
6411		}
6412	}
6413	SCTP_TCB_UNLOCK(stcb);
6414	if (!fnd) {
6415		/* No IPv4 address */
6416		SCTP_FREE_SONAME(sin);
6417		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
6418		return ENOENT;
6419	}
6420	(*addr) = (struct sockaddr *)sin;
6421	return (0);
6422}
6423
6424#ifdef INET
6425struct pr_usrreqs sctp_usrreqs = {
6426	.pru_abort = sctp_abort,
6427	.pru_accept = sctp_accept,
6428	.pru_attach = sctp_attach,
6429	.pru_bind = sctp_bind,
6430	.pru_connect = sctp_connect,
6431	.pru_control = in_control,
6432	.pru_close = sctp_close,
6433	.pru_detach = sctp_close,
6434	.pru_sopoll = sopoll_generic,
6435	.pru_flush = sctp_flush,
6436	.pru_disconnect = sctp_disconnect,
6437	.pru_listen = sctp_listen,
6438	.pru_peeraddr = sctp_peeraddr,
6439	.pru_send = sctp_sendm,
6440	.pru_shutdown = sctp_shutdown,
6441	.pru_sockaddr = sctp_ingetaddr,
6442	.pru_sosend = sctp_sosend,
6443	.pru_soreceive = sctp_soreceive
6444};
6445
6446#endif
6447#endif
6448