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