sctp_usrreq.c revision 271746
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 271746 2014-09-18 08:58:22Z 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				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4213				error = EINVAL;
4214				break;
4215			}
4216			hmaclist = sctp_alloc_hmaclist(shmac->shmac_number_of_idents);
4217			if (hmaclist == NULL) {
4218				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4219				error = ENOMEM;
4220				break;
4221			}
4222			for (i = 0; i < shmac->shmac_number_of_idents; i++) {
4223				hmacid = shmac->shmac_idents[i];
4224				if (sctp_auth_add_hmacid(hmaclist, hmacid)) {
4225					 /* invalid HMACs were found */ ;
4226					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4227					error = EINVAL;
4228					sctp_free_hmaclist(hmaclist);
4229					goto sctp_set_hmac_done;
4230				}
4231			}
4232			for (i = 0; i < hmaclist->num_algo; i++) {
4233				if (hmaclist->hmac[i] == SCTP_AUTH_HMAC_ID_SHA1) {
4234					/* already in list */
4235					break;
4236				}
4237			}
4238			if (i == hmaclist->num_algo) {
4239				/* not found in list */
4240				sctp_free_hmaclist(hmaclist);
4241				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4242				error = EINVAL;
4243				break;
4244			}
4245			/* set it on the endpoint */
4246			SCTP_INP_WLOCK(inp);
4247			if (inp->sctp_ep.local_hmacs)
4248				sctp_free_hmaclist(inp->sctp_ep.local_hmacs);
4249			inp->sctp_ep.local_hmacs = hmaclist;
4250			SCTP_INP_WUNLOCK(inp);
4251	sctp_set_hmac_done:
4252			break;
4253		}
4254	case SCTP_AUTH_ACTIVE_KEY:
4255		{
4256			struct sctp_authkeyid *scact;
4257
4258			SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, optsize);
4259			SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id);
4260
4261			/* set the active key on the right place */
4262			if (stcb) {
4263				/* set the active key on the assoc */
4264				if (sctp_auth_setactivekey(stcb,
4265				    scact->scact_keynumber)) {
4266					SCTP_LTRACE_ERR_RET(inp, NULL, NULL,
4267					    SCTP_FROM_SCTP_USRREQ,
4268					    EINVAL);
4269					error = EINVAL;
4270				}
4271				SCTP_TCB_UNLOCK(stcb);
4272			} else {
4273				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4274				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4275				    (scact->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
4276				    (scact->scact_assoc_id == SCTP_ALL_ASSOC)) {
4277					SCTP_INP_WLOCK(inp);
4278					if (sctp_auth_setactivekey_ep(inp, scact->scact_keynumber)) {
4279						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4280						error = EINVAL;
4281					}
4282					SCTP_INP_WUNLOCK(inp);
4283				}
4284				if ((scact->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
4285				    (scact->scact_assoc_id == SCTP_ALL_ASSOC)) {
4286					SCTP_INP_RLOCK(inp);
4287					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4288						SCTP_TCB_LOCK(stcb);
4289						sctp_auth_setactivekey(stcb, scact->scact_keynumber);
4290						SCTP_TCB_UNLOCK(stcb);
4291					}
4292					SCTP_INP_RUNLOCK(inp);
4293				}
4294			}
4295			break;
4296		}
4297	case SCTP_AUTH_DELETE_KEY:
4298		{
4299			struct sctp_authkeyid *scdel;
4300
4301			SCTP_CHECK_AND_CAST(scdel, optval, struct sctp_authkeyid, optsize);
4302			SCTP_FIND_STCB(inp, stcb, scdel->scact_assoc_id);
4303
4304			/* delete the key from the right place */
4305			if (stcb) {
4306				if (sctp_delete_sharedkey(stcb, scdel->scact_keynumber)) {
4307					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4308					error = EINVAL;
4309				}
4310				SCTP_TCB_UNLOCK(stcb);
4311			} else {
4312				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4313				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4314				    (scdel->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
4315				    (scdel->scact_assoc_id == SCTP_ALL_ASSOC)) {
4316					SCTP_INP_WLOCK(inp);
4317					if (sctp_delete_sharedkey_ep(inp, scdel->scact_keynumber)) {
4318						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4319						error = EINVAL;
4320					}
4321					SCTP_INP_WUNLOCK(inp);
4322				}
4323				if ((scdel->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
4324				    (scdel->scact_assoc_id == SCTP_ALL_ASSOC)) {
4325					SCTP_INP_RLOCK(inp);
4326					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4327						SCTP_TCB_LOCK(stcb);
4328						sctp_delete_sharedkey(stcb, scdel->scact_keynumber);
4329						SCTP_TCB_UNLOCK(stcb);
4330					}
4331					SCTP_INP_RUNLOCK(inp);
4332				}
4333			}
4334			break;
4335		}
4336	case SCTP_AUTH_DEACTIVATE_KEY:
4337		{
4338			struct sctp_authkeyid *keyid;
4339
4340			SCTP_CHECK_AND_CAST(keyid, optval, struct sctp_authkeyid, optsize);
4341			SCTP_FIND_STCB(inp, stcb, keyid->scact_assoc_id);
4342
4343			/* deactivate the key from the right place */
4344			if (stcb) {
4345				if (sctp_deact_sharedkey(stcb, keyid->scact_keynumber)) {
4346					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4347					error = EINVAL;
4348				}
4349				SCTP_TCB_UNLOCK(stcb);
4350			} else {
4351				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4352				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4353				    (keyid->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
4354				    (keyid->scact_assoc_id == SCTP_ALL_ASSOC)) {
4355					SCTP_INP_WLOCK(inp);
4356					if (sctp_deact_sharedkey_ep(inp, keyid->scact_keynumber)) {
4357						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4358						error = EINVAL;
4359					}
4360					SCTP_INP_WUNLOCK(inp);
4361				}
4362				if ((keyid->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
4363				    (keyid->scact_assoc_id == SCTP_ALL_ASSOC)) {
4364					SCTP_INP_RLOCK(inp);
4365					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4366						SCTP_TCB_LOCK(stcb);
4367						sctp_deact_sharedkey(stcb, keyid->scact_keynumber);
4368						SCTP_TCB_UNLOCK(stcb);
4369					}
4370					SCTP_INP_RUNLOCK(inp);
4371				}
4372			}
4373			break;
4374		}
4375	case SCTP_ENABLE_STREAM_RESET:
4376		{
4377			struct sctp_assoc_value *av;
4378
4379			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4380			if (av->assoc_value & (~SCTP_ENABLE_VALUE_MASK)) {
4381				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4382				error = EINVAL;
4383				break;
4384			}
4385			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4386			if (stcb) {
4387				stcb->asoc.local_strreset_support = (uint8_t) av->assoc_value;
4388				SCTP_TCB_UNLOCK(stcb);
4389			} else {
4390				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4391				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4392				    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
4393				    (av->assoc_id == SCTP_ALL_ASSOC)) {
4394					SCTP_INP_WLOCK(inp);
4395					inp->local_strreset_support = (uint8_t) av->assoc_value;
4396					SCTP_INP_WUNLOCK(inp);
4397				}
4398				if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4399				    (av->assoc_id == SCTP_ALL_ASSOC)) {
4400					SCTP_INP_RLOCK(inp);
4401					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4402						SCTP_TCB_LOCK(stcb);
4403						stcb->asoc.local_strreset_support = (uint8_t) av->assoc_value;
4404						SCTP_TCB_UNLOCK(stcb);
4405					}
4406					SCTP_INP_RUNLOCK(inp);
4407				}
4408			}
4409			break;
4410		}
4411	case SCTP_RESET_STREAMS:
4412		{
4413			struct sctp_reset_streams *strrst;
4414			int i, send_out = 0;
4415			int send_in = 0;
4416
4417			SCTP_CHECK_AND_CAST(strrst, optval, struct sctp_reset_streams, optsize);
4418			SCTP_FIND_STCB(inp, stcb, strrst->srs_assoc_id);
4419			if (stcb == NULL) {
4420				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4421				error = ENOENT;
4422				break;
4423			}
4424			if (stcb->asoc.reconfig_supported == 0) {
4425				/*
4426				 * Peer does not support the chunk type.
4427				 */
4428				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4429				error = EOPNOTSUPP;
4430				SCTP_TCB_UNLOCK(stcb);
4431				break;
4432			}
4433			if (stcb->asoc.stream_reset_outstanding) {
4434				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4435				error = EALREADY;
4436				SCTP_TCB_UNLOCK(stcb);
4437				break;
4438			}
4439			if (strrst->srs_flags & SCTP_STREAM_RESET_INCOMING) {
4440				send_in = 1;
4441			}
4442			if (strrst->srs_flags & SCTP_STREAM_RESET_OUTGOING) {
4443				send_out = 1;
4444			}
4445			if ((send_in == 0) && (send_out == 0)) {
4446				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4447				error = EINVAL;
4448				SCTP_TCB_UNLOCK(stcb);
4449				break;
4450			}
4451			for (i = 0; i < strrst->srs_number_streams; i++) {
4452				if ((send_in) &&
4453				    (strrst->srs_stream_list[i] > stcb->asoc.streamincnt)) {
4454					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4455					error = EINVAL;
4456					break;
4457				}
4458				if ((send_out) &&
4459				    (strrst->srs_stream_list[i] > stcb->asoc.streamoutcnt)) {
4460					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4461					error = EINVAL;
4462					break;
4463				}
4464			}
4465			if (error) {
4466				SCTP_TCB_UNLOCK(stcb);
4467				break;
4468			}
4469			error = sctp_send_str_reset_req(stcb, strrst->srs_number_streams,
4470			    strrst->srs_stream_list,
4471			    send_out, send_in, 0, 0, 0, 0, 0);
4472
4473			sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
4474			SCTP_TCB_UNLOCK(stcb);
4475			break;
4476		}
4477	case SCTP_ADD_STREAMS:
4478		{
4479			struct sctp_add_streams *stradd;
4480			uint8_t addstream = 0;
4481			uint16_t add_o_strmcnt = 0;
4482			uint16_t add_i_strmcnt = 0;
4483
4484			SCTP_CHECK_AND_CAST(stradd, optval, struct sctp_add_streams, optsize);
4485			SCTP_FIND_STCB(inp, stcb, stradd->sas_assoc_id);
4486			if (stcb == NULL) {
4487				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4488				error = ENOENT;
4489				break;
4490			}
4491			if (stcb->asoc.reconfig_supported == 0) {
4492				/*
4493				 * Peer does not support the chunk type.
4494				 */
4495				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4496				error = EOPNOTSUPP;
4497				SCTP_TCB_UNLOCK(stcb);
4498				break;
4499			}
4500			if (stcb->asoc.stream_reset_outstanding) {
4501				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4502				error = EALREADY;
4503				SCTP_TCB_UNLOCK(stcb);
4504				break;
4505			}
4506			if ((stradd->sas_outstrms == 0) &&
4507			    (stradd->sas_instrms == 0)) {
4508				error = EINVAL;
4509				goto skip_stuff;
4510			}
4511			if (stradd->sas_outstrms) {
4512				addstream = 1;
4513				/* We allocate here */
4514				add_o_strmcnt = stradd->sas_outstrms;
4515				if ((((int)add_o_strmcnt) + ((int)stcb->asoc.streamoutcnt)) > 0x0000ffff) {
4516					/* You can't have more than 64k */
4517					error = EINVAL;
4518					goto skip_stuff;
4519				}
4520			}
4521			if (stradd->sas_instrms) {
4522				int cnt;
4523
4524				addstream |= 2;
4525				/*
4526				 * We allocate inside
4527				 * sctp_send_str_reset_req()
4528				 */
4529				add_i_strmcnt = stradd->sas_instrms;
4530				cnt = add_i_strmcnt;
4531				cnt += stcb->asoc.streamincnt;
4532				if (cnt > 0x0000ffff) {
4533					/* You can't have more than 64k */
4534					error = EINVAL;
4535					goto skip_stuff;
4536				}
4537				if (cnt > (int)stcb->asoc.max_inbound_streams) {
4538					/* More than you are allowed */
4539					error = EINVAL;
4540					goto skip_stuff;
4541				}
4542			}
4543			error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 0, addstream, add_o_strmcnt, add_i_strmcnt, 0);
4544			sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
4545	skip_stuff:
4546			SCTP_TCB_UNLOCK(stcb);
4547			break;
4548		}
4549	case SCTP_RESET_ASSOC:
4550		{
4551			uint32_t *value;
4552
4553			SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
4554			SCTP_FIND_STCB(inp, stcb, (sctp_assoc_t) * value);
4555			if (stcb == NULL) {
4556				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4557				error = ENOENT;
4558				break;
4559			}
4560			if (stcb->asoc.reconfig_supported == 0) {
4561				/*
4562				 * Peer does not support the chunk type.
4563				 */
4564				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4565				error = EOPNOTSUPP;
4566				SCTP_TCB_UNLOCK(stcb);
4567				break;
4568			}
4569			if (stcb->asoc.stream_reset_outstanding) {
4570				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4571				error = EALREADY;
4572				SCTP_TCB_UNLOCK(stcb);
4573				break;
4574			}
4575			error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 1, 0, 0, 0, 0);
4576			sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
4577			SCTP_TCB_UNLOCK(stcb);
4578			break;
4579		}
4580	case SCTP_CONNECT_X:
4581		if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
4582			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4583			error = EINVAL;
4584			break;
4585		}
4586		error = sctp_do_connect_x(so, inp, optval, optsize, p, 0);
4587		break;
4588	case SCTP_CONNECT_X_DELAYED:
4589		if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
4590			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4591			error = EINVAL;
4592			break;
4593		}
4594		error = sctp_do_connect_x(so, inp, optval, optsize, p, 1);
4595		break;
4596	case SCTP_CONNECT_X_COMPLETE:
4597		{
4598			struct sockaddr *sa;
4599			struct sctp_nets *net;
4600
4601			/* FIXME MT: check correct? */
4602			SCTP_CHECK_AND_CAST(sa, optval, struct sockaddr, optsize);
4603
4604			/* find tcb */
4605			if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
4606				SCTP_INP_RLOCK(inp);
4607				stcb = LIST_FIRST(&inp->sctp_asoc_list);
4608				if (stcb) {
4609					SCTP_TCB_LOCK(stcb);
4610					net = sctp_findnet(stcb, sa);
4611				}
4612				SCTP_INP_RUNLOCK(inp);
4613			} else {
4614				/*
4615				 * We increment here since
4616				 * sctp_findassociation_ep_addr() wil do a
4617				 * decrement if it finds the stcb as long as
4618				 * the locked tcb (last argument) is NOT a
4619				 * TCB.. aka NULL.
4620				 */
4621				SCTP_INP_INCR_REF(inp);
4622				stcb = sctp_findassociation_ep_addr(&inp, sa, &net, NULL, NULL);
4623				if (stcb == NULL) {
4624					SCTP_INP_DECR_REF(inp);
4625				}
4626			}
4627
4628			if (stcb == NULL) {
4629				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4630				error = ENOENT;
4631				break;
4632			}
4633			if (stcb->asoc.delayed_connection == 1) {
4634				stcb->asoc.delayed_connection = 0;
4635				(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
4636				sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb,
4637				    stcb->asoc.primary_destination,
4638				    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_9);
4639				sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
4640			} else {
4641				/*
4642				 * already expired or did not use delayed
4643				 * connectx
4644				 */
4645				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4646				error = EALREADY;
4647			}
4648			SCTP_TCB_UNLOCK(stcb);
4649			break;
4650		}
4651	case SCTP_MAX_BURST:
4652		{
4653			struct sctp_assoc_value *av;
4654
4655			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4656			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4657
4658			if (stcb) {
4659				stcb->asoc.max_burst = av->assoc_value;
4660				SCTP_TCB_UNLOCK(stcb);
4661			} else {
4662				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4663				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4664				    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
4665				    (av->assoc_id == SCTP_ALL_ASSOC)) {
4666					SCTP_INP_WLOCK(inp);
4667					inp->sctp_ep.max_burst = av->assoc_value;
4668					SCTP_INP_WUNLOCK(inp);
4669				}
4670				if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4671				    (av->assoc_id == SCTP_ALL_ASSOC)) {
4672					SCTP_INP_RLOCK(inp);
4673					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4674						SCTP_TCB_LOCK(stcb);
4675						stcb->asoc.max_burst = av->assoc_value;
4676						SCTP_TCB_UNLOCK(stcb);
4677					}
4678					SCTP_INP_RUNLOCK(inp);
4679				}
4680			}
4681			break;
4682		}
4683	case SCTP_MAXSEG:
4684		{
4685			struct sctp_assoc_value *av;
4686			int ovh;
4687
4688			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4689			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4690
4691			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
4692				ovh = SCTP_MED_OVERHEAD;
4693			} else {
4694				ovh = SCTP_MED_V4_OVERHEAD;
4695			}
4696			if (stcb) {
4697				if (av->assoc_value) {
4698					stcb->asoc.sctp_frag_point = (av->assoc_value + ovh);
4699				} else {
4700					stcb->asoc.sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
4701				}
4702				SCTP_TCB_UNLOCK(stcb);
4703			} else {
4704				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4705				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4706				    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
4707					SCTP_INP_WLOCK(inp);
4708					/*
4709					 * FIXME MT: I think this is not in
4710					 * tune with the API ID
4711					 */
4712					if (av->assoc_value) {
4713						inp->sctp_frag_point = (av->assoc_value + ovh);
4714					} else {
4715						inp->sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
4716					}
4717					SCTP_INP_WUNLOCK(inp);
4718				} else {
4719					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4720					error = EINVAL;
4721				}
4722			}
4723			break;
4724		}
4725	case SCTP_EVENTS:
4726		{
4727			struct sctp_event_subscribe *events;
4728
4729			SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, optsize);
4730
4731			SCTP_INP_WLOCK(inp);
4732			if (events->sctp_data_io_event) {
4733				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
4734			} else {
4735				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
4736			}
4737
4738			if (events->sctp_association_event) {
4739				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
4740			} else {
4741				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
4742			}
4743
4744			if (events->sctp_address_event) {
4745				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
4746			} else {
4747				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
4748			}
4749
4750			if (events->sctp_send_failure_event) {
4751				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
4752			} else {
4753				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
4754			}
4755
4756			if (events->sctp_peer_error_event) {
4757				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPEERERR);
4758			} else {
4759				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPEERERR);
4760			}
4761
4762			if (events->sctp_shutdown_event) {
4763				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
4764			} else {
4765				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
4766			}
4767
4768			if (events->sctp_partial_delivery_event) {
4769				sctp_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
4770			} else {
4771				sctp_feature_off(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
4772			}
4773
4774			if (events->sctp_adaptation_layer_event) {
4775				sctp_feature_on(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
4776			} else {
4777				sctp_feature_off(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
4778			}
4779
4780			if (events->sctp_authentication_event) {
4781				sctp_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT);
4782			} else {
4783				sctp_feature_off(inp, SCTP_PCB_FLAGS_AUTHEVNT);
4784			}
4785
4786			if (events->sctp_sender_dry_event) {
4787				sctp_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT);
4788			} else {
4789				sctp_feature_off(inp, SCTP_PCB_FLAGS_DRYEVNT);
4790			}
4791
4792			if (events->sctp_stream_reset_event) {
4793				sctp_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
4794			} else {
4795				sctp_feature_off(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
4796			}
4797			SCTP_INP_WUNLOCK(inp);
4798
4799			SCTP_INP_RLOCK(inp);
4800			LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4801				SCTP_TCB_LOCK(stcb);
4802				if (events->sctp_association_event) {
4803					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
4804				} else {
4805					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
4806				}
4807				if (events->sctp_address_event) {
4808					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
4809				} else {
4810					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
4811				}
4812				if (events->sctp_send_failure_event) {
4813					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
4814				} else {
4815					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
4816				}
4817				if (events->sctp_peer_error_event) {
4818					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
4819				} else {
4820					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
4821				}
4822				if (events->sctp_shutdown_event) {
4823					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
4824				} else {
4825					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
4826				}
4827				if (events->sctp_partial_delivery_event) {
4828					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
4829				} else {
4830					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
4831				}
4832				if (events->sctp_adaptation_layer_event) {
4833					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
4834				} else {
4835					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
4836				}
4837				if (events->sctp_authentication_event) {
4838					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
4839				} else {
4840					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
4841				}
4842				if (events->sctp_sender_dry_event) {
4843					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
4844				} else {
4845					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
4846				}
4847				if (events->sctp_stream_reset_event) {
4848					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
4849				} else {
4850					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
4851				}
4852				SCTP_TCB_UNLOCK(stcb);
4853			}
4854			/*
4855			 * Send up the sender dry event only for 1-to-1
4856			 * style sockets.
4857			 */
4858			if (events->sctp_sender_dry_event) {
4859				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4860				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
4861					stcb = LIST_FIRST(&inp->sctp_asoc_list);
4862					if (stcb) {
4863						SCTP_TCB_LOCK(stcb);
4864						if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
4865						    TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
4866						    (stcb->asoc.stream_queue_cnt == 0)) {
4867							sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_LOCKED);
4868						}
4869						SCTP_TCB_UNLOCK(stcb);
4870					}
4871				}
4872			}
4873			SCTP_INP_RUNLOCK(inp);
4874			break;
4875		}
4876	case SCTP_ADAPTATION_LAYER:
4877		{
4878			struct sctp_setadaptation *adap_bits;
4879
4880			SCTP_CHECK_AND_CAST(adap_bits, optval, struct sctp_setadaptation, optsize);
4881			SCTP_INP_WLOCK(inp);
4882			inp->sctp_ep.adaptation_layer_indicator = adap_bits->ssb_adaptation_ind;
4883			inp->sctp_ep.adaptation_layer_indicator_provided = 1;
4884			SCTP_INP_WUNLOCK(inp);
4885			break;
4886		}
4887#ifdef SCTP_DEBUG
4888	case SCTP_SET_INITIAL_DBG_SEQ:
4889		{
4890			uint32_t *vvv;
4891
4892			SCTP_CHECK_AND_CAST(vvv, optval, uint32_t, optsize);
4893			SCTP_INP_WLOCK(inp);
4894			inp->sctp_ep.initial_sequence_debug = *vvv;
4895			SCTP_INP_WUNLOCK(inp);
4896			break;
4897		}
4898#endif
4899	case SCTP_DEFAULT_SEND_PARAM:
4900		{
4901			struct sctp_sndrcvinfo *s_info;
4902
4903			SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, optsize);
4904			SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
4905
4906			if (stcb) {
4907				if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
4908					memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
4909				} else {
4910					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4911					error = EINVAL;
4912				}
4913				SCTP_TCB_UNLOCK(stcb);
4914			} else {
4915				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4916				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4917				    (s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC) ||
4918				    (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)) {
4919					SCTP_INP_WLOCK(inp);
4920					memcpy(&inp->def_send, s_info, min(optsize, sizeof(inp->def_send)));
4921					SCTP_INP_WUNLOCK(inp);
4922				}
4923				if ((s_info->sinfo_assoc_id == SCTP_CURRENT_ASSOC) ||
4924				    (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)) {
4925					SCTP_INP_RLOCK(inp);
4926					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4927						SCTP_TCB_LOCK(stcb);
4928						if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
4929							memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
4930						}
4931						SCTP_TCB_UNLOCK(stcb);
4932					}
4933					SCTP_INP_RUNLOCK(inp);
4934				}
4935			}
4936			break;
4937		}
4938	case SCTP_PEER_ADDR_PARAMS:
4939		{
4940			struct sctp_paddrparams *paddrp;
4941			struct sctp_nets *net;
4942
4943			SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, optsize);
4944			SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
4945			net = NULL;
4946			if (stcb) {
4947				net = sctp_findnet(stcb, (struct sockaddr *)&paddrp->spp_address);
4948			} else {
4949				/*
4950				 * We increment here since
4951				 * sctp_findassociation_ep_addr() wil do a
4952				 * decrement if it finds the stcb as long as
4953				 * the locked tcb (last argument) is NOT a
4954				 * TCB.. aka NULL.
4955				 */
4956				SCTP_INP_INCR_REF(inp);
4957				stcb = sctp_findassociation_ep_addr(&inp,
4958				    (struct sockaddr *)&paddrp->spp_address,
4959				    &net, NULL, NULL);
4960				if (stcb == NULL) {
4961					SCTP_INP_DECR_REF(inp);
4962				}
4963			}
4964			if (stcb && (net == NULL)) {
4965				struct sockaddr *sa;
4966
4967				sa = (struct sockaddr *)&paddrp->spp_address;
4968#ifdef INET
4969				if (sa->sa_family == AF_INET) {
4970
4971					struct sockaddr_in *sin;
4972
4973					sin = (struct sockaddr_in *)sa;
4974					if (sin->sin_addr.s_addr) {
4975						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4976						SCTP_TCB_UNLOCK(stcb);
4977						error = EINVAL;
4978						break;
4979					}
4980				} else
4981#endif
4982#ifdef INET6
4983				if (sa->sa_family == AF_INET6) {
4984					struct sockaddr_in6 *sin6;
4985
4986					sin6 = (struct sockaddr_in6 *)sa;
4987					if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
4988						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4989						SCTP_TCB_UNLOCK(stcb);
4990						error = EINVAL;
4991						break;
4992					}
4993				} else
4994#endif
4995				{
4996					error = EAFNOSUPPORT;
4997					SCTP_TCB_UNLOCK(stcb);
4998					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
4999					break;
5000				}
5001			}
5002			/* sanity checks */
5003			if ((paddrp->spp_flags & SPP_HB_ENABLE) && (paddrp->spp_flags & SPP_HB_DISABLE)) {
5004				if (stcb)
5005					SCTP_TCB_UNLOCK(stcb);
5006				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5007				return (EINVAL);
5008			}
5009			if ((paddrp->spp_flags & SPP_PMTUD_ENABLE) && (paddrp->spp_flags & SPP_PMTUD_DISABLE)) {
5010				if (stcb)
5011					SCTP_TCB_UNLOCK(stcb);
5012				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5013				return (EINVAL);
5014			}
5015			if (stcb) {
5016				/************************TCB SPECIFIC SET ******************/
5017				/*
5018				 * do we change the timer for HB, we run
5019				 * only one?
5020				 */
5021				int ovh = 0;
5022
5023				if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
5024					ovh = SCTP_MED_OVERHEAD;
5025				} else {
5026					ovh = SCTP_MED_V4_OVERHEAD;
5027				}
5028
5029				/* network sets ? */
5030				if (net) {
5031					/************************NET SPECIFIC SET ******************/
5032					if (paddrp->spp_flags & SPP_HB_DISABLE) {
5033						if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
5034						    !(net->dest_state & SCTP_ADDR_NOHB)) {
5035							sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
5036							    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
5037						}
5038						net->dest_state |= SCTP_ADDR_NOHB;
5039					}
5040					if (paddrp->spp_flags & SPP_HB_ENABLE) {
5041						if (paddrp->spp_hbinterval) {
5042							net->heart_beat_delay = paddrp->spp_hbinterval;
5043						} else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
5044							net->heart_beat_delay = 0;
5045						}
5046						sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
5047						    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
5048						sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
5049						net->dest_state &= ~SCTP_ADDR_NOHB;
5050					}
5051					if (paddrp->spp_flags & SPP_HB_DEMAND) {
5052						/* on demand HB */
5053						sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5054						sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED);
5055						sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
5056					}
5057					if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
5058						if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
5059							sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
5060							    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
5061						}
5062						net->dest_state |= SCTP_ADDR_NO_PMTUD;
5063						net->mtu = paddrp->spp_pathmtu + ovh;
5064						if (net->mtu < stcb->asoc.smallest_mtu) {
5065							sctp_pathmtu_adjustment(stcb, net->mtu);
5066						}
5067					}
5068					if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
5069						if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
5070							sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
5071						}
5072						net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
5073					}
5074					if (paddrp->spp_pathmaxrxt) {
5075						if (net->dest_state & SCTP_ADDR_PF) {
5076							if (net->error_count > paddrp->spp_pathmaxrxt) {
5077								net->dest_state &= ~SCTP_ADDR_PF;
5078							}
5079						} else {
5080							if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
5081							    (net->error_count > net->pf_threshold)) {
5082								net->dest_state |= SCTP_ADDR_PF;
5083								sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5084								sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
5085								sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
5086							}
5087						}
5088						if (net->dest_state & SCTP_ADDR_REACHABLE) {
5089							if (net->error_count > paddrp->spp_pathmaxrxt) {
5090								net->dest_state &= ~SCTP_ADDR_REACHABLE;
5091								sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
5092							}
5093						} else {
5094							if (net->error_count <= paddrp->spp_pathmaxrxt) {
5095								net->dest_state |= SCTP_ADDR_REACHABLE;
5096								sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
5097							}
5098						}
5099						net->failure_threshold = paddrp->spp_pathmaxrxt;
5100					}
5101					if (paddrp->spp_flags & SPP_DSCP) {
5102						net->dscp = paddrp->spp_dscp & 0xfc;
5103						net->dscp |= 0x01;
5104					}
5105#ifdef INET6
5106					if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
5107						if (net->ro._l_addr.sa.sa_family == AF_INET6) {
5108							net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5109							net->flowlabel |= 0x80000000;
5110						}
5111					}
5112#endif
5113				} else {
5114					/************************ASSOC ONLY -- NO NET SPECIFIC SET ******************/
5115					if (paddrp->spp_pathmaxrxt) {
5116						stcb->asoc.def_net_failure = paddrp->spp_pathmaxrxt;
5117						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5118							if (net->dest_state & SCTP_ADDR_PF) {
5119								if (net->error_count > paddrp->spp_pathmaxrxt) {
5120									net->dest_state &= ~SCTP_ADDR_PF;
5121								}
5122							} else {
5123								if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
5124								    (net->error_count > net->pf_threshold)) {
5125									net->dest_state |= SCTP_ADDR_PF;
5126									sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5127									sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
5128									sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
5129								}
5130							}
5131							if (net->dest_state & SCTP_ADDR_REACHABLE) {
5132								if (net->error_count > paddrp->spp_pathmaxrxt) {
5133									net->dest_state &= ~SCTP_ADDR_REACHABLE;
5134									sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
5135								}
5136							} else {
5137								if (net->error_count <= paddrp->spp_pathmaxrxt) {
5138									net->dest_state |= SCTP_ADDR_REACHABLE;
5139									sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
5140								}
5141							}
5142							net->failure_threshold = paddrp->spp_pathmaxrxt;
5143						}
5144					}
5145					if (paddrp->spp_flags & SPP_HB_ENABLE) {
5146						if (paddrp->spp_hbinterval) {
5147							stcb->asoc.heart_beat_delay = paddrp->spp_hbinterval;
5148						} else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
5149							stcb->asoc.heart_beat_delay = 0;
5150						}
5151						/* Turn back on the timer */
5152						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5153							if (paddrp->spp_hbinterval) {
5154								net->heart_beat_delay = paddrp->spp_hbinterval;
5155							} else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
5156								net->heart_beat_delay = 0;
5157							}
5158							if (net->dest_state & SCTP_ADDR_NOHB) {
5159								net->dest_state &= ~SCTP_ADDR_NOHB;
5160							}
5161							sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
5162							    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
5163							sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
5164						}
5165						sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5166					}
5167					if (paddrp->spp_flags & SPP_HB_DISABLE) {
5168						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5169							if (!(net->dest_state & SCTP_ADDR_NOHB)) {
5170								net->dest_state |= SCTP_ADDR_NOHB;
5171								if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED)) {
5172									sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
5173								}
5174							}
5175						}
5176						sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5177					}
5178					if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
5179						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5180							if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
5181								sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
5182								    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
5183							}
5184							net->dest_state |= SCTP_ADDR_NO_PMTUD;
5185							net->mtu = paddrp->spp_pathmtu + ovh;
5186							if (net->mtu < stcb->asoc.smallest_mtu) {
5187								sctp_pathmtu_adjustment(stcb, net->mtu);
5188							}
5189						}
5190						sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5191					}
5192					if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
5193						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5194							if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
5195								sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
5196							}
5197							net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
5198						}
5199						sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5200					}
5201					if (paddrp->spp_flags & SPP_DSCP) {
5202						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5203							net->dscp = paddrp->spp_dscp & 0xfc;
5204							net->dscp |= 0x01;
5205						}
5206						stcb->asoc.default_dscp = paddrp->spp_dscp & 0xfc;
5207						stcb->asoc.default_dscp |= 0x01;
5208					}
5209#ifdef INET6
5210					if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
5211						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5212							if (net->ro._l_addr.sa.sa_family == AF_INET6) {
5213								net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5214								net->flowlabel |= 0x80000000;
5215							}
5216						}
5217						stcb->asoc.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5218						stcb->asoc.default_flowlabel |= 0x80000000;
5219					}
5220#endif
5221				}
5222				SCTP_TCB_UNLOCK(stcb);
5223			} else {
5224				/************************NO TCB, SET TO default stuff ******************/
5225				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5226				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5227				    (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC)) {
5228					SCTP_INP_WLOCK(inp);
5229					/*
5230					 * For the TOS/FLOWLABEL stuff you
5231					 * set it with the options on the
5232					 * socket
5233					 */
5234					if (paddrp->spp_pathmaxrxt) {
5235						inp->sctp_ep.def_net_failure = paddrp->spp_pathmaxrxt;
5236					}
5237					if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO)
5238						inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
5239					else if (paddrp->spp_hbinterval) {
5240						if (paddrp->spp_hbinterval > SCTP_MAX_HB_INTERVAL)
5241							paddrp->spp_hbinterval = SCTP_MAX_HB_INTERVAL;
5242						inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
5243					}
5244					if (paddrp->spp_flags & SPP_HB_ENABLE) {
5245						if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
5246							inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
5247						} else if (paddrp->spp_hbinterval) {
5248							inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
5249						}
5250						sctp_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5251					} else if (paddrp->spp_flags & SPP_HB_DISABLE) {
5252						sctp_feature_on(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5253					}
5254					if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
5255						sctp_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5256					} else if (paddrp->spp_flags & SPP_PMTUD_DISABLE) {
5257						sctp_feature_on(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5258					}
5259					if (paddrp->spp_flags & SPP_DSCP) {
5260						inp->sctp_ep.default_dscp = paddrp->spp_dscp & 0xfc;
5261						inp->sctp_ep.default_dscp |= 0x01;
5262					}
5263#ifdef INET6
5264					if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
5265						if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
5266							inp->sctp_ep.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5267							inp->sctp_ep.default_flowlabel |= 0x80000000;
5268						}
5269					}
5270#endif
5271					SCTP_INP_WUNLOCK(inp);
5272				} else {
5273					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5274					error = EINVAL;
5275				}
5276			}
5277			break;
5278		}
5279	case SCTP_RTOINFO:
5280		{
5281			struct sctp_rtoinfo *srto;
5282			uint32_t new_init, new_min, new_max;
5283
5284			SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, optsize);
5285			SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
5286
5287			if (stcb) {
5288				if (srto->srto_initial)
5289					new_init = srto->srto_initial;
5290				else
5291					new_init = stcb->asoc.initial_rto;
5292				if (srto->srto_max)
5293					new_max = srto->srto_max;
5294				else
5295					new_max = stcb->asoc.maxrto;
5296				if (srto->srto_min)
5297					new_min = srto->srto_min;
5298				else
5299					new_min = stcb->asoc.minrto;
5300				if ((new_min <= new_init) && (new_init <= new_max)) {
5301					stcb->asoc.initial_rto = new_init;
5302					stcb->asoc.maxrto = new_max;
5303					stcb->asoc.minrto = new_min;
5304				} else {
5305					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5306					error = EINVAL;
5307				}
5308				SCTP_TCB_UNLOCK(stcb);
5309			} else {
5310				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5311				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5312				    (srto->srto_assoc_id == SCTP_FUTURE_ASSOC)) {
5313					SCTP_INP_WLOCK(inp);
5314					if (srto->srto_initial)
5315						new_init = srto->srto_initial;
5316					else
5317						new_init = inp->sctp_ep.initial_rto;
5318					if (srto->srto_max)
5319						new_max = srto->srto_max;
5320					else
5321						new_max = inp->sctp_ep.sctp_maxrto;
5322					if (srto->srto_min)
5323						new_min = srto->srto_min;
5324					else
5325						new_min = inp->sctp_ep.sctp_minrto;
5326					if ((new_min <= new_init) && (new_init <= new_max)) {
5327						inp->sctp_ep.initial_rto = new_init;
5328						inp->sctp_ep.sctp_maxrto = new_max;
5329						inp->sctp_ep.sctp_minrto = new_min;
5330					} else {
5331						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5332						error = EINVAL;
5333					}
5334					SCTP_INP_WUNLOCK(inp);
5335				} else {
5336					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5337					error = EINVAL;
5338				}
5339			}
5340			break;
5341		}
5342	case SCTP_ASSOCINFO:
5343		{
5344			struct sctp_assocparams *sasoc;
5345
5346			SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, optsize);
5347			SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
5348			if (sasoc->sasoc_cookie_life) {
5349				/* boundary check the cookie life */
5350				if (sasoc->sasoc_cookie_life < 1000)
5351					sasoc->sasoc_cookie_life = 1000;
5352				if (sasoc->sasoc_cookie_life > SCTP_MAX_COOKIE_LIFE) {
5353					sasoc->sasoc_cookie_life = SCTP_MAX_COOKIE_LIFE;
5354				}
5355			}
5356			if (stcb) {
5357				if (sasoc->sasoc_asocmaxrxt)
5358					stcb->asoc.max_send_times = sasoc->sasoc_asocmaxrxt;
5359				if (sasoc->sasoc_cookie_life) {
5360					stcb->asoc.cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
5361				}
5362				SCTP_TCB_UNLOCK(stcb);
5363			} else {
5364				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5365				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5366				    (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC)) {
5367					SCTP_INP_WLOCK(inp);
5368					if (sasoc->sasoc_asocmaxrxt)
5369						inp->sctp_ep.max_send_times = sasoc->sasoc_asocmaxrxt;
5370					if (sasoc->sasoc_cookie_life) {
5371						inp->sctp_ep.def_cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
5372					}
5373					SCTP_INP_WUNLOCK(inp);
5374				} else {
5375					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5376					error = EINVAL;
5377				}
5378			}
5379			break;
5380		}
5381	case SCTP_INITMSG:
5382		{
5383			struct sctp_initmsg *sinit;
5384
5385			SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, optsize);
5386			SCTP_INP_WLOCK(inp);
5387			if (sinit->sinit_num_ostreams)
5388				inp->sctp_ep.pre_open_stream_count = sinit->sinit_num_ostreams;
5389
5390			if (sinit->sinit_max_instreams)
5391				inp->sctp_ep.max_open_streams_intome = sinit->sinit_max_instreams;
5392
5393			if (sinit->sinit_max_attempts)
5394				inp->sctp_ep.max_init_times = sinit->sinit_max_attempts;
5395
5396			if (sinit->sinit_max_init_timeo)
5397				inp->sctp_ep.initial_init_rto_max = sinit->sinit_max_init_timeo;
5398			SCTP_INP_WUNLOCK(inp);
5399			break;
5400		}
5401	case SCTP_PRIMARY_ADDR:
5402		{
5403			struct sctp_setprim *spa;
5404			struct sctp_nets *net;
5405
5406			SCTP_CHECK_AND_CAST(spa, optval, struct sctp_setprim, optsize);
5407			SCTP_FIND_STCB(inp, stcb, spa->ssp_assoc_id);
5408
5409			net = NULL;
5410			if (stcb) {
5411				net = sctp_findnet(stcb, (struct sockaddr *)&spa->ssp_addr);
5412			} else {
5413				/*
5414				 * We increment here since
5415				 * sctp_findassociation_ep_addr() wil do a
5416				 * decrement if it finds the stcb as long as
5417				 * the locked tcb (last argument) is NOT a
5418				 * TCB.. aka NULL.
5419				 */
5420				SCTP_INP_INCR_REF(inp);
5421				stcb = sctp_findassociation_ep_addr(&inp,
5422				    (struct sockaddr *)&spa->ssp_addr,
5423				    &net, NULL, NULL);
5424				if (stcb == NULL) {
5425					SCTP_INP_DECR_REF(inp);
5426				}
5427			}
5428
5429			if ((stcb) && (net)) {
5430				if ((net != stcb->asoc.primary_destination) &&
5431				    (!(net->dest_state & SCTP_ADDR_UNCONFIRMED))) {
5432					/* Ok we need to set it */
5433					if (sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net) == 0) {
5434						if ((stcb->asoc.alternate) &&
5435						    (!(net->dest_state & SCTP_ADDR_PF)) &&
5436						    (net->dest_state & SCTP_ADDR_REACHABLE)) {
5437							sctp_free_remote_addr(stcb->asoc.alternate);
5438							stcb->asoc.alternate = NULL;
5439						}
5440					}
5441				}
5442			} else {
5443				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5444				error = EINVAL;
5445			}
5446			if (stcb) {
5447				SCTP_TCB_UNLOCK(stcb);
5448			}
5449			break;
5450		}
5451	case SCTP_SET_DYNAMIC_PRIMARY:
5452		{
5453			union sctp_sockstore *ss;
5454
5455			error = priv_check(curthread,
5456			    PRIV_NETINET_RESERVEDPORT);
5457			if (error)
5458				break;
5459
5460			SCTP_CHECK_AND_CAST(ss, optval, union sctp_sockstore, optsize);
5461			/* SUPER USER CHECK? */
5462			error = sctp_dynamic_set_primary(&ss->sa, vrf_id);
5463			break;
5464		}
5465	case SCTP_SET_PEER_PRIMARY_ADDR:
5466		{
5467			struct sctp_setpeerprim *sspp;
5468
5469			SCTP_CHECK_AND_CAST(sspp, optval, struct sctp_setpeerprim, optsize);
5470			SCTP_FIND_STCB(inp, stcb, sspp->sspp_assoc_id);
5471			if (stcb != NULL) {
5472				struct sctp_ifa *ifa;
5473
5474				ifa = sctp_find_ifa_by_addr((struct sockaddr *)&sspp->sspp_addr,
5475				    stcb->asoc.vrf_id, SCTP_ADDR_NOT_LOCKED);
5476				if (ifa == NULL) {
5477					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5478					error = EINVAL;
5479					goto out_of_it;
5480				}
5481				if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
5482					/*
5483					 * Must validate the ifa found is in
5484					 * our ep
5485					 */
5486					struct sctp_laddr *laddr;
5487					int found = 0;
5488
5489					LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
5490						if (laddr->ifa == NULL) {
5491							SCTPDBG(SCTP_DEBUG_OUTPUT1, "%s: NULL ifa\n",
5492							    __FUNCTION__);
5493							continue;
5494						}
5495						if (laddr->ifa == ifa) {
5496							found = 1;
5497							break;
5498						}
5499					}
5500					if (!found) {
5501						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5502						error = EINVAL;
5503						goto out_of_it;
5504					}
5505				} else {
5506					switch (sspp->sspp_addr.ss_family) {
5507#ifdef INET
5508					case AF_INET:
5509						{
5510							struct sockaddr_in *sin;
5511
5512							sin = (struct sockaddr_in *)&sspp->sspp_addr;
5513							if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
5514							    &sin->sin_addr) != 0) {
5515								SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5516								error = EINVAL;
5517								goto out_of_it;
5518							}
5519							break;
5520						}
5521#endif
5522#ifdef INET6
5523					case AF_INET6:
5524						{
5525							struct sockaddr_in6 *sin6;
5526
5527							sin6 = (struct sockaddr_in6 *)&sspp->sspp_addr;
5528							if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
5529							    &sin6->sin6_addr) != 0) {
5530								SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5531								error = EINVAL;
5532								goto out_of_it;
5533							}
5534							break;
5535						}
5536#endif
5537					default:
5538						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5539						error = EINVAL;
5540						goto out_of_it;
5541					}
5542				}
5543				if (sctp_set_primary_ip_address_sa(stcb,
5544				    (struct sockaddr *)&sspp->sspp_addr) != 0) {
5545					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5546					error = EINVAL;
5547				}
5548		out_of_it:
5549				SCTP_TCB_UNLOCK(stcb);
5550			} else {
5551				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5552				error = EINVAL;
5553			}
5554			break;
5555		}
5556	case SCTP_BINDX_ADD_ADDR:
5557		{
5558			struct sctp_getaddresses *addrs;
5559			struct thread *td;
5560
5561			td = (struct thread *)p;
5562			SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses,
5563			    optsize);
5564#ifdef INET
5565			if (addrs->addr->sa_family == AF_INET) {
5566				if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in)) {
5567					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5568					error = EINVAL;
5569					break;
5570				}
5571				if (td != NULL && (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)(addrs->addr))->sin_addr)))) {
5572					SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
5573					break;
5574				}
5575			} else
5576#endif
5577#ifdef INET6
5578			if (addrs->addr->sa_family == AF_INET6) {
5579				if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6)) {
5580					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5581					error = EINVAL;
5582					break;
5583				}
5584				if (td != NULL && (error = prison_local_ip6(td->td_ucred, &(((struct sockaddr_in6 *)(addrs->addr))->sin6_addr),
5585				    (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
5586					SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
5587					break;
5588				}
5589			} else
5590#endif
5591			{
5592				error = EAFNOSUPPORT;
5593				break;
5594			}
5595			sctp_bindx_add_address(so, inp, addrs->addr,
5596			    addrs->sget_assoc_id, vrf_id,
5597			    &error, p);
5598			break;
5599		}
5600	case SCTP_BINDX_REM_ADDR:
5601		{
5602			struct sctp_getaddresses *addrs;
5603			struct thread *td;
5604
5605			td = (struct thread *)p;
5606
5607			SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses, optsize);
5608#ifdef INET
5609			if (addrs->addr->sa_family == AF_INET) {
5610				if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in)) {
5611					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5612					error = EINVAL;
5613					break;
5614				}
5615				if (td != NULL && (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)(addrs->addr))->sin_addr)))) {
5616					SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
5617					break;
5618				}
5619			} else
5620#endif
5621#ifdef INET6
5622			if (addrs->addr->sa_family == AF_INET6) {
5623				if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6)) {
5624					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5625					error = EINVAL;
5626					break;
5627				}
5628				if (td != NULL &&
5629				    (error = prison_local_ip6(td->td_ucred,
5630				    &(((struct sockaddr_in6 *)(addrs->addr))->sin6_addr),
5631				    (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
5632					SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
5633					break;
5634				}
5635			} else
5636#endif
5637			{
5638				error = EAFNOSUPPORT;
5639				break;
5640			}
5641			sctp_bindx_delete_address(inp, addrs->addr,
5642			    addrs->sget_assoc_id, vrf_id,
5643			    &error);
5644			break;
5645		}
5646	case SCTP_EVENT:
5647		{
5648			struct sctp_event *event;
5649			uint32_t event_type;
5650
5651			SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, optsize);
5652			SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
5653			switch (event->se_type) {
5654			case SCTP_ASSOC_CHANGE:
5655				event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
5656				break;
5657			case SCTP_PEER_ADDR_CHANGE:
5658				event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
5659				break;
5660			case SCTP_REMOTE_ERROR:
5661				event_type = SCTP_PCB_FLAGS_RECVPEERERR;
5662				break;
5663			case SCTP_SEND_FAILED:
5664				event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
5665				break;
5666			case SCTP_SHUTDOWN_EVENT:
5667				event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
5668				break;
5669			case SCTP_ADAPTATION_INDICATION:
5670				event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
5671				break;
5672			case SCTP_PARTIAL_DELIVERY_EVENT:
5673				event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
5674				break;
5675			case SCTP_AUTHENTICATION_EVENT:
5676				event_type = SCTP_PCB_FLAGS_AUTHEVNT;
5677				break;
5678			case SCTP_STREAM_RESET_EVENT:
5679				event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
5680				break;
5681			case SCTP_SENDER_DRY_EVENT:
5682				event_type = SCTP_PCB_FLAGS_DRYEVNT;
5683				break;
5684			case SCTP_NOTIFICATIONS_STOPPED_EVENT:
5685				event_type = 0;
5686				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
5687				error = ENOTSUP;
5688				break;
5689			case SCTP_ASSOC_RESET_EVENT:
5690				event_type = SCTP_PCB_FLAGS_ASSOC_RESETEVNT;
5691				break;
5692			case SCTP_STREAM_CHANGE_EVENT:
5693				event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT;
5694				break;
5695			case SCTP_SEND_FAILED_EVENT:
5696				event_type = SCTP_PCB_FLAGS_RECVNSENDFAILEVNT;
5697				break;
5698			default:
5699				event_type = 0;
5700				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5701				error = EINVAL;
5702				break;
5703			}
5704			if (event_type > 0) {
5705				if (stcb) {
5706					if (event->se_on) {
5707						sctp_stcb_feature_on(inp, stcb, event_type);
5708						if (event_type == SCTP_PCB_FLAGS_DRYEVNT) {
5709							if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
5710							    TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
5711							    (stcb->asoc.stream_queue_cnt == 0)) {
5712								sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_LOCKED);
5713							}
5714						}
5715					} else {
5716						sctp_stcb_feature_off(inp, stcb, event_type);
5717					}
5718					SCTP_TCB_UNLOCK(stcb);
5719				} else {
5720					/*
5721					 * We don't want to send up a storm
5722					 * of events, so return an error for
5723					 * sender dry events
5724					 */
5725					if ((event_type == SCTP_PCB_FLAGS_DRYEVNT) &&
5726					    ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) == 0) &&
5727					    ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
5728					    ((event->se_assoc_id == SCTP_ALL_ASSOC) ||
5729					    (event->se_assoc_id == SCTP_CURRENT_ASSOC))) {
5730						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
5731						error = ENOTSUP;
5732						break;
5733					}
5734					if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5735					    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5736					    (event->se_assoc_id == SCTP_FUTURE_ASSOC) ||
5737					    (event->se_assoc_id == SCTP_ALL_ASSOC)) {
5738						SCTP_INP_WLOCK(inp);
5739						if (event->se_on) {
5740							sctp_feature_on(inp, event_type);
5741						} else {
5742							sctp_feature_off(inp, event_type);
5743						}
5744						SCTP_INP_WUNLOCK(inp);
5745					}
5746					if ((event->se_assoc_id == SCTP_CURRENT_ASSOC) ||
5747					    (event->se_assoc_id == SCTP_ALL_ASSOC)) {
5748						SCTP_INP_RLOCK(inp);
5749						LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5750							SCTP_TCB_LOCK(stcb);
5751							if (event->se_on) {
5752								sctp_stcb_feature_on(inp, stcb, event_type);
5753							} else {
5754								sctp_stcb_feature_off(inp, stcb, event_type);
5755							}
5756							SCTP_TCB_UNLOCK(stcb);
5757						}
5758						SCTP_INP_RUNLOCK(inp);
5759					}
5760				}
5761			}
5762			break;
5763		}
5764	case SCTP_RECVRCVINFO:
5765		{
5766			int *onoff;
5767
5768			SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
5769			SCTP_INP_WLOCK(inp);
5770			if (*onoff != 0) {
5771				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
5772			} else {
5773				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
5774			}
5775			SCTP_INP_WUNLOCK(inp);
5776			break;
5777		}
5778	case SCTP_RECVNXTINFO:
5779		{
5780			int *onoff;
5781
5782			SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
5783			SCTP_INP_WLOCK(inp);
5784			if (*onoff != 0) {
5785				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
5786			} else {
5787				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
5788			}
5789			SCTP_INP_WUNLOCK(inp);
5790			break;
5791		}
5792	case SCTP_DEFAULT_SNDINFO:
5793		{
5794			struct sctp_sndinfo *info;
5795			uint16_t policy;
5796
5797			SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, optsize);
5798			SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
5799
5800			if (stcb) {
5801				if (info->snd_sid < stcb->asoc.streamoutcnt) {
5802					stcb->asoc.def_send.sinfo_stream = info->snd_sid;
5803					policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
5804					stcb->asoc.def_send.sinfo_flags = info->snd_flags;
5805					stcb->asoc.def_send.sinfo_flags |= policy;
5806					stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
5807					stcb->asoc.def_send.sinfo_context = info->snd_context;
5808				} else {
5809					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5810					error = EINVAL;
5811				}
5812				SCTP_TCB_UNLOCK(stcb);
5813			} else {
5814				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5815				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5816				    (info->snd_assoc_id == SCTP_FUTURE_ASSOC) ||
5817				    (info->snd_assoc_id == SCTP_ALL_ASSOC)) {
5818					SCTP_INP_WLOCK(inp);
5819					inp->def_send.sinfo_stream = info->snd_sid;
5820					policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
5821					inp->def_send.sinfo_flags = info->snd_flags;
5822					inp->def_send.sinfo_flags |= policy;
5823					inp->def_send.sinfo_ppid = info->snd_ppid;
5824					inp->def_send.sinfo_context = info->snd_context;
5825					SCTP_INP_WUNLOCK(inp);
5826				}
5827				if ((info->snd_assoc_id == SCTP_CURRENT_ASSOC) ||
5828				    (info->snd_assoc_id == SCTP_ALL_ASSOC)) {
5829					SCTP_INP_RLOCK(inp);
5830					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5831						SCTP_TCB_LOCK(stcb);
5832						if (info->snd_sid < stcb->asoc.streamoutcnt) {
5833							stcb->asoc.def_send.sinfo_stream = info->snd_sid;
5834							policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
5835							stcb->asoc.def_send.sinfo_flags = info->snd_flags;
5836							stcb->asoc.def_send.sinfo_flags |= policy;
5837							stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
5838							stcb->asoc.def_send.sinfo_context = info->snd_context;
5839						}
5840						SCTP_TCB_UNLOCK(stcb);
5841					}
5842					SCTP_INP_RUNLOCK(inp);
5843				}
5844			}
5845			break;
5846		}
5847	case SCTP_DEFAULT_PRINFO:
5848		{
5849			struct sctp_default_prinfo *info;
5850
5851			SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, optsize);
5852			SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
5853
5854			if (PR_SCTP_INVALID_POLICY(info->pr_policy)) {
5855				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5856				error = EINVAL;
5857				break;
5858			}
5859			if (stcb) {
5860				stcb->asoc.def_send.sinfo_flags &= 0xfff0;
5861				stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
5862				stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
5863				SCTP_TCB_UNLOCK(stcb);
5864			} else {
5865				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5866				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5867				    (info->pr_assoc_id == SCTP_FUTURE_ASSOC) ||
5868				    (info->pr_assoc_id == SCTP_ALL_ASSOC)) {
5869					SCTP_INP_WLOCK(inp);
5870					inp->def_send.sinfo_flags &= 0xfff0;
5871					inp->def_send.sinfo_flags |= info->pr_policy;
5872					inp->def_send.sinfo_timetolive = info->pr_value;
5873					SCTP_INP_WUNLOCK(inp);
5874				}
5875				if ((info->pr_assoc_id == SCTP_CURRENT_ASSOC) ||
5876				    (info->pr_assoc_id == SCTP_ALL_ASSOC)) {
5877					SCTP_INP_RLOCK(inp);
5878					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5879						SCTP_TCB_LOCK(stcb);
5880						stcb->asoc.def_send.sinfo_flags &= 0xfff0;
5881						stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
5882						stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
5883						SCTP_TCB_UNLOCK(stcb);
5884					}
5885					SCTP_INP_RUNLOCK(inp);
5886				}
5887			}
5888			break;
5889		}
5890	case SCTP_PEER_ADDR_THLDS:
5891		/* Applies to the specific association */
5892		{
5893			struct sctp_paddrthlds *thlds;
5894			struct sctp_nets *net;
5895
5896			SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, optsize);
5897			SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
5898			net = NULL;
5899			if (stcb) {
5900				net = sctp_findnet(stcb, (struct sockaddr *)&thlds->spt_address);
5901			} else {
5902				/*
5903				 * We increment here since
5904				 * sctp_findassociation_ep_addr() wil do a
5905				 * decrement if it finds the stcb as long as
5906				 * the locked tcb (last argument) is NOT a
5907				 * TCB.. aka NULL.
5908				 */
5909				SCTP_INP_INCR_REF(inp);
5910				stcb = sctp_findassociation_ep_addr(&inp,
5911				    (struct sockaddr *)&thlds->spt_address,
5912				    &net, NULL, NULL);
5913				if (stcb == NULL) {
5914					SCTP_INP_DECR_REF(inp);
5915				}
5916			}
5917			if (stcb && (net == NULL)) {
5918				struct sockaddr *sa;
5919
5920				sa = (struct sockaddr *)&thlds->spt_address;
5921#ifdef INET
5922				if (sa->sa_family == AF_INET) {
5923
5924					struct sockaddr_in *sin;
5925
5926					sin = (struct sockaddr_in *)sa;
5927					if (sin->sin_addr.s_addr) {
5928						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5929						SCTP_TCB_UNLOCK(stcb);
5930						error = EINVAL;
5931						break;
5932					}
5933				} else
5934#endif
5935#ifdef INET6
5936				if (sa->sa_family == AF_INET6) {
5937					struct sockaddr_in6 *sin6;
5938
5939					sin6 = (struct sockaddr_in6 *)sa;
5940					if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
5941						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5942						SCTP_TCB_UNLOCK(stcb);
5943						error = EINVAL;
5944						break;
5945					}
5946				} else
5947#endif
5948				{
5949					error = EAFNOSUPPORT;
5950					SCTP_TCB_UNLOCK(stcb);
5951					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
5952					break;
5953				}
5954			}
5955			if (stcb) {
5956				if (net) {
5957					if (net->dest_state & SCTP_ADDR_PF) {
5958						if ((net->failure_threshold > thlds->spt_pathmaxrxt) ||
5959						    (net->failure_threshold <= thlds->spt_pathpfthld)) {
5960							net->dest_state &= ~SCTP_ADDR_PF;
5961						}
5962					} else {
5963						if ((net->failure_threshold > thlds->spt_pathpfthld) &&
5964						    (net->failure_threshold <= thlds->spt_pathmaxrxt)) {
5965							net->dest_state |= SCTP_ADDR_PF;
5966							sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5967							sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
5968							sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
5969						}
5970					}
5971					if (net->dest_state & SCTP_ADDR_REACHABLE) {
5972						if (net->failure_threshold > thlds->spt_pathmaxrxt) {
5973							net->dest_state &= ~SCTP_ADDR_REACHABLE;
5974							sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
5975						}
5976					} else {
5977						if (net->failure_threshold <= thlds->spt_pathmaxrxt) {
5978							net->dest_state |= SCTP_ADDR_REACHABLE;
5979							sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
5980						}
5981					}
5982					net->failure_threshold = thlds->spt_pathmaxrxt;
5983					net->pf_threshold = thlds->spt_pathpfthld;
5984				} else {
5985					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5986						if (net->dest_state & SCTP_ADDR_PF) {
5987							if ((net->failure_threshold > thlds->spt_pathmaxrxt) ||
5988							    (net->failure_threshold <= thlds->spt_pathpfthld)) {
5989								net->dest_state &= ~SCTP_ADDR_PF;
5990							}
5991						} else {
5992							if ((net->failure_threshold > thlds->spt_pathpfthld) &&
5993							    (net->failure_threshold <= thlds->spt_pathmaxrxt)) {
5994								net->dest_state |= SCTP_ADDR_PF;
5995								sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5996								sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
5997								sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
5998							}
5999						}
6000						if (net->dest_state & SCTP_ADDR_REACHABLE) {
6001							if (net->failure_threshold > thlds->spt_pathmaxrxt) {
6002								net->dest_state &= ~SCTP_ADDR_REACHABLE;
6003								sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
6004							}
6005						} else {
6006							if (net->failure_threshold <= thlds->spt_pathmaxrxt) {
6007								net->dest_state |= SCTP_ADDR_REACHABLE;
6008								sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
6009							}
6010						}
6011						net->failure_threshold = thlds->spt_pathmaxrxt;
6012						net->pf_threshold = thlds->spt_pathpfthld;
6013					}
6014					stcb->asoc.def_net_failure = thlds->spt_pathmaxrxt;
6015					stcb->asoc.def_net_pf_threshold = thlds->spt_pathpfthld;
6016				}
6017			} else {
6018				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6019				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6020				    (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC)) {
6021					SCTP_INP_WLOCK(inp);
6022					inp->sctp_ep.def_net_failure = thlds->spt_pathmaxrxt;
6023					inp->sctp_ep.def_net_pf_threshold = thlds->spt_pathpfthld;
6024					SCTP_INP_WUNLOCK(inp);
6025				} else {
6026					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6027					error = EINVAL;
6028				}
6029			}
6030			break;
6031		}
6032	case SCTP_REMOTE_UDP_ENCAPS_PORT:
6033		{
6034			struct sctp_udpencaps *encaps;
6035			struct sctp_nets *net;
6036
6037			SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, optsize);
6038			SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
6039			if (stcb) {
6040				net = sctp_findnet(stcb, (struct sockaddr *)&encaps->sue_address);
6041			} else {
6042				/*
6043				 * We increment here since
6044				 * sctp_findassociation_ep_addr() wil do a
6045				 * decrement if it finds the stcb as long as
6046				 * the locked tcb (last argument) is NOT a
6047				 * TCB.. aka NULL.
6048				 */
6049				net = NULL;
6050				SCTP_INP_INCR_REF(inp);
6051				stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&encaps->sue_address, &net, NULL, NULL);
6052				if (stcb == NULL) {
6053					SCTP_INP_DECR_REF(inp);
6054				}
6055			}
6056			if (stcb && (net == NULL)) {
6057				struct sockaddr *sa;
6058
6059				sa = (struct sockaddr *)&encaps->sue_address;
6060#ifdef INET
6061				if (sa->sa_family == AF_INET) {
6062
6063					struct sockaddr_in *sin;
6064
6065					sin = (struct sockaddr_in *)sa;
6066					if (sin->sin_addr.s_addr) {
6067						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6068						SCTP_TCB_UNLOCK(stcb);
6069						error = EINVAL;
6070						break;
6071					}
6072				} else
6073#endif
6074#ifdef INET6
6075				if (sa->sa_family == AF_INET6) {
6076					struct sockaddr_in6 *sin6;
6077
6078					sin6 = (struct sockaddr_in6 *)sa;
6079					if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
6080						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6081						SCTP_TCB_UNLOCK(stcb);
6082						error = EINVAL;
6083						break;
6084					}
6085				} else
6086#endif
6087				{
6088					error = EAFNOSUPPORT;
6089					SCTP_TCB_UNLOCK(stcb);
6090					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6091					break;
6092				}
6093			}
6094			if (stcb) {
6095				if (net) {
6096					net->port = encaps->sue_port;
6097				} else {
6098					stcb->asoc.port = encaps->sue_port;
6099				}
6100				SCTP_TCB_UNLOCK(stcb);
6101			} else {
6102				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6103				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6104				    (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC)) {
6105					SCTP_INP_WLOCK(inp);
6106					inp->sctp_ep.port = encaps->sue_port;
6107					SCTP_INP_WUNLOCK(inp);
6108				} else {
6109					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6110					error = EINVAL;
6111				}
6112			}
6113			break;
6114		}
6115	case SCTP_ECN_SUPPORTED:
6116		{
6117			struct sctp_assoc_value *av;
6118
6119			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6120			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6121
6122			if (stcb) {
6123				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6124				error = EINVAL;
6125				SCTP_TCB_UNLOCK(stcb);
6126			} else {
6127				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6128				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6129				    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
6130					SCTP_INP_WLOCK(inp);
6131					if (av->assoc_value == 0) {
6132						inp->ecn_supported = 0;
6133					} else {
6134						inp->ecn_supported = 1;
6135					}
6136					SCTP_INP_WUNLOCK(inp);
6137				} else {
6138					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6139					error = EINVAL;
6140				}
6141			}
6142			break;
6143		}
6144	case SCTP_PR_SUPPORTED:
6145		{
6146			struct sctp_assoc_value *av;
6147
6148			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6149			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6150
6151			if (stcb) {
6152				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6153				error = EINVAL;
6154				SCTP_TCB_UNLOCK(stcb);
6155			} else {
6156				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6157				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6158				    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
6159					SCTP_INP_WLOCK(inp);
6160					if (av->assoc_value == 0) {
6161						inp->prsctp_supported = 0;
6162					} else {
6163						inp->prsctp_supported = 1;
6164					}
6165					SCTP_INP_WUNLOCK(inp);
6166				} else {
6167					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6168					error = EINVAL;
6169				}
6170			}
6171			break;
6172		}
6173	case SCTP_AUTH_SUPPORTED:
6174		{
6175			struct sctp_assoc_value *av;
6176
6177			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6178			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6179
6180			if (stcb) {
6181				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6182				error = EINVAL;
6183				SCTP_TCB_UNLOCK(stcb);
6184			} else {
6185				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6186				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6187				    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
6188					if ((av->assoc_value == 0) &&
6189					    (inp->asconf_supported == 1)) {
6190						/*
6191						 * AUTH is required for
6192						 * ASCONF
6193						 */
6194						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6195						error = EINVAL;
6196					} else {
6197						SCTP_INP_WLOCK(inp);
6198						if (av->assoc_value == 0) {
6199							inp->auth_supported = 0;
6200						} else {
6201							inp->auth_supported = 1;
6202						}
6203						SCTP_INP_WUNLOCK(inp);
6204					}
6205				} else {
6206					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6207					error = EINVAL;
6208				}
6209			}
6210			break;
6211		}
6212	case SCTP_ASCONF_SUPPORTED:
6213		{
6214			struct sctp_assoc_value *av;
6215
6216			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6217			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6218
6219			if (stcb) {
6220				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6221				error = EINVAL;
6222				SCTP_TCB_UNLOCK(stcb);
6223			} else {
6224				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6225				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6226				    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
6227					if ((av->assoc_value != 0) &&
6228					    (inp->auth_supported == 0)) {
6229						/*
6230						 * AUTH is required for
6231						 * ASCONF
6232						 */
6233						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6234						error = EINVAL;
6235					} else {
6236						SCTP_INP_WLOCK(inp);
6237						if (av->assoc_value == 0) {
6238							inp->asconf_supported = 0;
6239							sctp_auth_delete_chunk(SCTP_ASCONF,
6240							    inp->sctp_ep.local_auth_chunks);
6241							sctp_auth_delete_chunk(SCTP_ASCONF_ACK,
6242							    inp->sctp_ep.local_auth_chunks);
6243						} else {
6244							inp->asconf_supported = 1;
6245							sctp_auth_add_chunk(SCTP_ASCONF,
6246							    inp->sctp_ep.local_auth_chunks);
6247							sctp_auth_add_chunk(SCTP_ASCONF_ACK,
6248							    inp->sctp_ep.local_auth_chunks);
6249						}
6250						SCTP_INP_WUNLOCK(inp);
6251					}
6252				} else {
6253					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6254					error = EINVAL;
6255				}
6256			}
6257			break;
6258		}
6259	case SCTP_RECONFIG_SUPPORTED:
6260		{
6261			struct sctp_assoc_value *av;
6262
6263			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6264			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6265
6266			if (stcb) {
6267				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6268				error = EINVAL;
6269				SCTP_TCB_UNLOCK(stcb);
6270			} else {
6271				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6272				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6273				    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
6274					SCTP_INP_WLOCK(inp);
6275					if (av->assoc_value == 0) {
6276						inp->reconfig_supported = 0;
6277					} else {
6278						inp->reconfig_supported = 1;
6279					}
6280					SCTP_INP_WUNLOCK(inp);
6281				} else {
6282					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6283					error = EINVAL;
6284				}
6285			}
6286			break;
6287		}
6288	case SCTP_NRSACK_SUPPORTED:
6289		{
6290			struct sctp_assoc_value *av;
6291
6292			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6293			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6294
6295			if (stcb) {
6296				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6297				error = EINVAL;
6298				SCTP_TCB_UNLOCK(stcb);
6299			} else {
6300				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6301				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6302				    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
6303					SCTP_INP_WLOCK(inp);
6304					if (av->assoc_value == 0) {
6305						inp->nrsack_supported = 0;
6306					} else {
6307						inp->nrsack_supported = 1;
6308					}
6309					SCTP_INP_WUNLOCK(inp);
6310				} else {
6311					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6312					error = EINVAL;
6313				}
6314			}
6315			break;
6316		}
6317	case SCTP_PKTDROP_SUPPORTED:
6318		{
6319			struct sctp_assoc_value *av;
6320
6321			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6322			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6323
6324			if (stcb) {
6325				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6326				error = EINVAL;
6327				SCTP_TCB_UNLOCK(stcb);
6328			} else {
6329				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6330				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6331				    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
6332					SCTP_INP_WLOCK(inp);
6333					if (av->assoc_value == 0) {
6334						inp->pktdrop_supported = 0;
6335					} else {
6336						inp->pktdrop_supported = 1;
6337					}
6338					SCTP_INP_WUNLOCK(inp);
6339				} else {
6340					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6341					error = EINVAL;
6342				}
6343			}
6344			break;
6345		}
6346	default:
6347		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
6348		error = ENOPROTOOPT;
6349		break;
6350	}			/* end switch (opt) */
6351	return (error);
6352}
6353
6354int
6355sctp_ctloutput(struct socket *so, struct sockopt *sopt)
6356{
6357	void *optval = NULL;
6358	size_t optsize = 0;
6359	void *p;
6360	int error = 0;
6361
6362	if (sopt->sopt_level != IPPROTO_SCTP) {
6363		/* wrong proto level... send back up to IP */
6364#ifdef INET6
6365		if (INP_CHECK_SOCKAF(so, AF_INET6))
6366			error = ip6_ctloutput(so, sopt);
6367#endif				/* INET6 */
6368#if defined(INET) && defined(INET6)
6369		else
6370#endif
6371#ifdef INET
6372			error = ip_ctloutput(so, sopt);
6373#endif
6374		return (error);
6375	}
6376	optsize = sopt->sopt_valsize;
6377	if (optsize) {
6378		SCTP_MALLOC(optval, void *, optsize, SCTP_M_SOCKOPT);
6379		if (optval == NULL) {
6380			SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS);
6381			return (ENOBUFS);
6382		}
6383		error = sooptcopyin(sopt, optval, optsize, optsize);
6384		if (error) {
6385			SCTP_FREE(optval, SCTP_M_SOCKOPT);
6386			goto out;
6387		}
6388	}
6389	p = (void *)sopt->sopt_td;
6390	if (sopt->sopt_dir == SOPT_SET) {
6391		error = sctp_setopt(so, sopt->sopt_name, optval, optsize, p);
6392	} else if (sopt->sopt_dir == SOPT_GET) {
6393		error = sctp_getopt(so, sopt->sopt_name, optval, &optsize, p);
6394	} else {
6395		SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6396		error = EINVAL;
6397	}
6398	if ((error == 0) && (optval != NULL)) {
6399		error = sooptcopyout(sopt, optval, optsize);
6400		SCTP_FREE(optval, SCTP_M_SOCKOPT);
6401	} else if (optval != NULL) {
6402		SCTP_FREE(optval, SCTP_M_SOCKOPT);
6403	}
6404out:
6405	return (error);
6406}
6407
6408#ifdef INET
6409static int
6410sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
6411{
6412	int error = 0;
6413	int create_lock_on = 0;
6414	uint32_t vrf_id;
6415	struct sctp_inpcb *inp;
6416	struct sctp_tcb *stcb = NULL;
6417
6418	inp = (struct sctp_inpcb *)so->so_pcb;
6419	if (inp == NULL) {
6420		/* I made the same as TCP since we are not setup? */
6421		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6422		return (ECONNRESET);
6423	}
6424	if (addr == NULL) {
6425		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6426		return EINVAL;
6427	}
6428	switch (addr->sa_family) {
6429#ifdef INET6
6430	case AF_INET6:
6431		{
6432			struct sockaddr_in6 *sin6p;
6433
6434			if (addr->sa_len != sizeof(struct sockaddr_in6)) {
6435				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6436				return (EINVAL);
6437			}
6438			sin6p = (struct sockaddr_in6 *)addr;
6439			if (p != NULL && (error = prison_remote_ip6(p->td_ucred, &sin6p->sin6_addr)) != 0) {
6440				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6441				return (error);
6442			}
6443			break;
6444		}
6445#endif
6446#ifdef INET
6447	case AF_INET:
6448		{
6449			struct sockaddr_in *sinp;
6450
6451			if (addr->sa_len != sizeof(struct sockaddr_in)) {
6452				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6453				return (EINVAL);
6454			}
6455			sinp = (struct sockaddr_in *)addr;
6456			if (p != NULL && (error = prison_remote_ip4(p->td_ucred, &sinp->sin_addr)) != 0) {
6457				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6458				return (error);
6459			}
6460			break;
6461		}
6462#endif
6463	default:
6464		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
6465		return (EAFNOSUPPORT);
6466	}
6467	SCTP_INP_INCR_REF(inp);
6468	SCTP_ASOC_CREATE_LOCK(inp);
6469	create_lock_on = 1;
6470
6471
6472	if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
6473	    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
6474		/* Should I really unlock ? */
6475		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
6476		error = EFAULT;
6477		goto out_now;
6478	}
6479#ifdef INET6
6480	if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
6481	    (addr->sa_family == AF_INET6)) {
6482		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6483		error = EINVAL;
6484		goto out_now;
6485	}
6486#endif
6487	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
6488	    SCTP_PCB_FLAGS_UNBOUND) {
6489		/* Bind a ephemeral port */
6490		error = sctp_inpcb_bind(so, NULL, NULL, p);
6491		if (error) {
6492			goto out_now;
6493		}
6494	}
6495	/* Now do we connect? */
6496	if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
6497	    (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
6498		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6499		error = EINVAL;
6500		goto out_now;
6501	}
6502	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
6503	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
6504		/* We are already connected AND the TCP model */
6505		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
6506		error = EADDRINUSE;
6507		goto out_now;
6508	}
6509	if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
6510		SCTP_INP_RLOCK(inp);
6511		stcb = LIST_FIRST(&inp->sctp_asoc_list);
6512		SCTP_INP_RUNLOCK(inp);
6513	} else {
6514		/*
6515		 * We increment here since sctp_findassociation_ep_addr()
6516		 * will do a decrement if it finds the stcb as long as the
6517		 * locked tcb (last argument) is NOT a TCB.. aka NULL.
6518		 */
6519		SCTP_INP_INCR_REF(inp);
6520		stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
6521		if (stcb == NULL) {
6522			SCTP_INP_DECR_REF(inp);
6523		} else {
6524			SCTP_TCB_UNLOCK(stcb);
6525		}
6526	}
6527	if (stcb != NULL) {
6528		/* Already have or am bring up an association */
6529		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
6530		error = EALREADY;
6531		goto out_now;
6532	}
6533	vrf_id = inp->def_vrf_id;
6534	/* We are GOOD to go */
6535	stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, p);
6536	if (stcb == NULL) {
6537		/* Gak! no memory */
6538		goto out_now;
6539	}
6540	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
6541		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
6542		/* Set the connected flag so we can queue data */
6543		soisconnecting(so);
6544	}
6545	SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
6546	(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
6547
6548	/* initialize authentication parameters for the assoc */
6549	sctp_initialize_auth_params(inp, stcb);
6550
6551	sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
6552	SCTP_TCB_UNLOCK(stcb);
6553out_now:
6554	if (create_lock_on) {
6555		SCTP_ASOC_CREATE_UNLOCK(inp);
6556	}
6557	SCTP_INP_DECR_REF(inp);
6558	return (error);
6559}
6560
6561#endif
6562
6563int
6564sctp_listen(struct socket *so, int backlog, struct thread *p)
6565{
6566	/*
6567	 * Note this module depends on the protocol processing being called
6568	 * AFTER any socket level flags and backlog are applied to the
6569	 * socket. The traditional way that the socket flags are applied is
6570	 * AFTER protocol processing. We have made a change to the
6571	 * sys/kern/uipc_socket.c module to reverse this but this MUST be in
6572	 * place if the socket API for SCTP is to work properly.
6573	 */
6574
6575	int error = 0;
6576	struct sctp_inpcb *inp;
6577
6578	inp = (struct sctp_inpcb *)so->so_pcb;
6579	if (inp == NULL) {
6580		/* I made the same as TCP since we are not setup? */
6581		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6582		return (ECONNRESET);
6583	}
6584	if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) {
6585		/* See if we have a listener */
6586		struct sctp_inpcb *tinp;
6587		union sctp_sockstore store;
6588
6589		if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
6590			/* not bound all */
6591			struct sctp_laddr *laddr;
6592
6593			LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
6594				memcpy(&store, &laddr->ifa->address, sizeof(store));
6595				switch (store.sa.sa_family) {
6596#ifdef INET
6597				case AF_INET:
6598					store.sin.sin_port = inp->sctp_lport;
6599					break;
6600#endif
6601#ifdef INET6
6602				case AF_INET6:
6603					store.sin6.sin6_port = inp->sctp_lport;
6604					break;
6605#endif
6606				default:
6607					break;
6608				}
6609				tinp = sctp_pcb_findep(&store.sa, 0, 0, inp->def_vrf_id);
6610				if (tinp && (tinp != inp) &&
6611				    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
6612				    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
6613				    (tinp->sctp_socket->so_qlimit)) {
6614					/*
6615					 * we have a listener already and
6616					 * its not this inp.
6617					 */
6618					SCTP_INP_DECR_REF(tinp);
6619					return (EADDRINUSE);
6620				} else if (tinp) {
6621					SCTP_INP_DECR_REF(tinp);
6622				}
6623			}
6624		} else {
6625			/* Setup a local addr bound all */
6626			memset(&store, 0, sizeof(store));
6627#ifdef INET6
6628			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
6629				store.sa.sa_family = AF_INET6;
6630				store.sa.sa_len = sizeof(struct sockaddr_in6);
6631			}
6632#endif
6633#ifdef INET
6634			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
6635				store.sa.sa_family = AF_INET;
6636				store.sa.sa_len = sizeof(struct sockaddr_in);
6637			}
6638#endif
6639			switch (store.sa.sa_family) {
6640#ifdef INET
6641			case AF_INET:
6642				store.sin.sin_port = inp->sctp_lport;
6643				break;
6644#endif
6645#ifdef INET6
6646			case AF_INET6:
6647				store.sin6.sin6_port = inp->sctp_lport;
6648				break;
6649#endif
6650			default:
6651				break;
6652			}
6653			tinp = sctp_pcb_findep(&store.sa, 0, 0, inp->def_vrf_id);
6654			if (tinp && (tinp != inp) &&
6655			    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
6656			    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
6657			    (tinp->sctp_socket->so_qlimit)) {
6658				/*
6659				 * we have a listener already and its not
6660				 * this inp.
6661				 */
6662				SCTP_INP_DECR_REF(tinp);
6663				return (EADDRINUSE);
6664			} else if (tinp) {
6665				SCTP_INP_DECR_REF(inp);
6666			}
6667		}
6668	}
6669	SCTP_INP_RLOCK(inp);
6670#ifdef SCTP_LOCK_LOGGING
6671	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) {
6672		sctp_log_lock(inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_SOCK);
6673	}
6674#endif
6675	SOCK_LOCK(so);
6676	error = solisten_proto_check(so);
6677	if (error) {
6678		SOCK_UNLOCK(so);
6679		SCTP_INP_RUNLOCK(inp);
6680		return (error);
6681	}
6682	if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) &&
6683	    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
6684		/*
6685		 * The unlucky case - We are in the tcp pool with this guy.
6686		 * - Someone else is in the main inp slot. - We must move
6687		 * this guy (the listener) to the main slot - We must then
6688		 * move the guy that was listener to the TCP Pool.
6689		 */
6690		if (sctp_swap_inpcb_for_listen(inp)) {
6691			goto in_use;
6692		}
6693	}
6694	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
6695	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
6696		/* We are already connected AND the TCP model */
6697in_use:
6698		SCTP_INP_RUNLOCK(inp);
6699		SOCK_UNLOCK(so);
6700		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
6701		return (EADDRINUSE);
6702	}
6703	SCTP_INP_RUNLOCK(inp);
6704	if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
6705		/* We must do a bind. */
6706		SOCK_UNLOCK(so);
6707		if ((error = sctp_inpcb_bind(so, NULL, NULL, p))) {
6708			/* bind error, probably perm */
6709			return (error);
6710		}
6711		SOCK_LOCK(so);
6712	}
6713	/* It appears for 7.0 and on, we must always call this. */
6714	solisten_proto(so, backlog);
6715	if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
6716		/* remove the ACCEPTCONN flag for one-to-many sockets */
6717		so->so_options &= ~SO_ACCEPTCONN;
6718	}
6719	if (backlog == 0) {
6720		/* turning off listen */
6721		so->so_options &= ~SO_ACCEPTCONN;
6722	}
6723	SOCK_UNLOCK(so);
6724	return (error);
6725}
6726
6727static int sctp_defered_wakeup_cnt = 0;
6728
6729int
6730sctp_accept(struct socket *so, struct sockaddr **addr)
6731{
6732	struct sctp_tcb *stcb;
6733	struct sctp_inpcb *inp;
6734	union sctp_sockstore store;
6735
6736#ifdef INET6
6737	int error;
6738
6739#endif
6740	inp = (struct sctp_inpcb *)so->so_pcb;
6741
6742	if (inp == NULL) {
6743		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6744		return (ECONNRESET);
6745	}
6746	SCTP_INP_RLOCK(inp);
6747	if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
6748		SCTP_INP_RUNLOCK(inp);
6749		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
6750		return (EOPNOTSUPP);
6751	}
6752	if (so->so_state & SS_ISDISCONNECTED) {
6753		SCTP_INP_RUNLOCK(inp);
6754		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ECONNABORTED);
6755		return (ECONNABORTED);
6756	}
6757	stcb = LIST_FIRST(&inp->sctp_asoc_list);
6758	if (stcb == NULL) {
6759		SCTP_INP_RUNLOCK(inp);
6760		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6761		return (ECONNRESET);
6762	}
6763	SCTP_TCB_LOCK(stcb);
6764	SCTP_INP_RUNLOCK(inp);
6765	store = stcb->asoc.primary_destination->ro._l_addr;
6766	stcb->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE;
6767	SCTP_TCB_UNLOCK(stcb);
6768	switch (store.sa.sa_family) {
6769#ifdef INET
6770	case AF_INET:
6771		{
6772			struct sockaddr_in *sin;
6773
6774			SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
6775			if (sin == NULL)
6776				return (ENOMEM);
6777			sin->sin_family = AF_INET;
6778			sin->sin_len = sizeof(*sin);
6779			sin->sin_port = store.sin.sin_port;
6780			sin->sin_addr = store.sin.sin_addr;
6781			*addr = (struct sockaddr *)sin;
6782			break;
6783		}
6784#endif
6785#ifdef INET6
6786	case AF_INET6:
6787		{
6788			struct sockaddr_in6 *sin6;
6789
6790			SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
6791			if (sin6 == NULL)
6792				return (ENOMEM);
6793			sin6->sin6_family = AF_INET6;
6794			sin6->sin6_len = sizeof(*sin6);
6795			sin6->sin6_port = store.sin6.sin6_port;
6796			sin6->sin6_addr = store.sin6.sin6_addr;
6797			if ((error = sa6_recoverscope(sin6)) != 0) {
6798				SCTP_FREE_SONAME(sin6);
6799				return (error);
6800			}
6801			*addr = (struct sockaddr *)sin6;
6802			break;
6803		}
6804#endif
6805	default:
6806		/* TSNH */
6807		break;
6808	}
6809	/* Wake any delayed sleep action */
6810	if (inp->sctp_flags & SCTP_PCB_FLAGS_DONT_WAKE) {
6811		SCTP_INP_WLOCK(inp);
6812		inp->sctp_flags &= ~SCTP_PCB_FLAGS_DONT_WAKE;
6813		if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEOUTPUT) {
6814			inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEOUTPUT;
6815			SCTP_INP_WUNLOCK(inp);
6816			SOCKBUF_LOCK(&inp->sctp_socket->so_snd);
6817			if (sowriteable(inp->sctp_socket)) {
6818				sowwakeup_locked(inp->sctp_socket);
6819			} else {
6820				SOCKBUF_UNLOCK(&inp->sctp_socket->so_snd);
6821			}
6822			SCTP_INP_WLOCK(inp);
6823		}
6824		if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEINPUT) {
6825			inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEINPUT;
6826			SCTP_INP_WUNLOCK(inp);
6827			SOCKBUF_LOCK(&inp->sctp_socket->so_rcv);
6828			if (soreadable(inp->sctp_socket)) {
6829				sctp_defered_wakeup_cnt++;
6830				sorwakeup_locked(inp->sctp_socket);
6831			} else {
6832				SOCKBUF_UNLOCK(&inp->sctp_socket->so_rcv);
6833			}
6834			SCTP_INP_WLOCK(inp);
6835		}
6836		SCTP_INP_WUNLOCK(inp);
6837	}
6838	if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
6839		SCTP_TCB_LOCK(stcb);
6840		sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_7);
6841	}
6842	return (0);
6843}
6844
6845#ifdef INET
6846int
6847sctp_ingetaddr(struct socket *so, struct sockaddr **addr)
6848{
6849	struct sockaddr_in *sin;
6850	uint32_t vrf_id;
6851	struct sctp_inpcb *inp;
6852	struct sctp_ifa *sctp_ifa;
6853
6854	/*
6855	 * Do the malloc first in case it blocks.
6856	 */
6857	SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
6858	if (sin == NULL)
6859		return (ENOMEM);
6860	sin->sin_family = AF_INET;
6861	sin->sin_len = sizeof(*sin);
6862	inp = (struct sctp_inpcb *)so->so_pcb;
6863	if (!inp) {
6864		SCTP_FREE_SONAME(sin);
6865		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6866		return (ECONNRESET);
6867	}
6868	SCTP_INP_RLOCK(inp);
6869	sin->sin_port = inp->sctp_lport;
6870	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
6871		if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
6872			struct sctp_tcb *stcb;
6873			struct sockaddr_in *sin_a;
6874			struct sctp_nets *net;
6875			int fnd;
6876
6877			stcb = LIST_FIRST(&inp->sctp_asoc_list);
6878			if (stcb == NULL) {
6879				goto notConn;
6880			}
6881			fnd = 0;
6882			sin_a = NULL;
6883			SCTP_TCB_LOCK(stcb);
6884			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6885				sin_a = (struct sockaddr_in *)&net->ro._l_addr;
6886				if (sin_a == NULL)
6887					/* this will make coverity happy */
6888					continue;
6889
6890				if (sin_a->sin_family == AF_INET) {
6891					fnd = 1;
6892					break;
6893				}
6894			}
6895			if ((!fnd) || (sin_a == NULL)) {
6896				/* punt */
6897				SCTP_TCB_UNLOCK(stcb);
6898				goto notConn;
6899			}
6900			vrf_id = inp->def_vrf_id;
6901			sctp_ifa = sctp_source_address_selection(inp,
6902			    stcb,
6903			    (sctp_route_t *) & net->ro,
6904			    net, 0, vrf_id);
6905			if (sctp_ifa) {
6906				sin->sin_addr = sctp_ifa->address.sin.sin_addr;
6907				sctp_free_ifa(sctp_ifa);
6908			}
6909			SCTP_TCB_UNLOCK(stcb);
6910		} else {
6911			/* For the bound all case you get back 0 */
6912	notConn:
6913			sin->sin_addr.s_addr = 0;
6914		}
6915
6916	} else {
6917		/* Take the first IPv4 address in the list */
6918		struct sctp_laddr *laddr;
6919		int fnd = 0;
6920
6921		LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
6922			if (laddr->ifa->address.sa.sa_family == AF_INET) {
6923				struct sockaddr_in *sin_a;
6924
6925				sin_a = &laddr->ifa->address.sin;
6926				sin->sin_addr = sin_a->sin_addr;
6927				fnd = 1;
6928				break;
6929			}
6930		}
6931		if (!fnd) {
6932			SCTP_FREE_SONAME(sin);
6933			SCTP_INP_RUNLOCK(inp);
6934			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
6935			return (ENOENT);
6936		}
6937	}
6938	SCTP_INP_RUNLOCK(inp);
6939	(*addr) = (struct sockaddr *)sin;
6940	return (0);
6941}
6942
6943int
6944sctp_peeraddr(struct socket *so, struct sockaddr **addr)
6945{
6946	struct sockaddr_in *sin;
6947	int fnd;
6948	struct sockaddr_in *sin_a;
6949	struct sctp_inpcb *inp;
6950	struct sctp_tcb *stcb;
6951	struct sctp_nets *net;
6952
6953	/* Do the malloc first in case it blocks. */
6954	SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
6955	if (sin == NULL)
6956		return (ENOMEM);
6957	sin->sin_family = AF_INET;
6958	sin->sin_len = sizeof(*sin);
6959
6960	inp = (struct sctp_inpcb *)so->so_pcb;
6961	if ((inp == NULL) ||
6962	    ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
6963		/* UDP type and listeners will drop out here */
6964		SCTP_FREE_SONAME(sin);
6965		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
6966		return (ENOTCONN);
6967	}
6968	SCTP_INP_RLOCK(inp);
6969	stcb = LIST_FIRST(&inp->sctp_asoc_list);
6970	if (stcb) {
6971		SCTP_TCB_LOCK(stcb);
6972	}
6973	SCTP_INP_RUNLOCK(inp);
6974	if (stcb == NULL) {
6975		SCTP_FREE_SONAME(sin);
6976		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6977		return (ECONNRESET);
6978	}
6979	fnd = 0;
6980	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6981		sin_a = (struct sockaddr_in *)&net->ro._l_addr;
6982		if (sin_a->sin_family == AF_INET) {
6983			fnd = 1;
6984			sin->sin_port = stcb->rport;
6985			sin->sin_addr = sin_a->sin_addr;
6986			break;
6987		}
6988	}
6989	SCTP_TCB_UNLOCK(stcb);
6990	if (!fnd) {
6991		/* No IPv4 address */
6992		SCTP_FREE_SONAME(sin);
6993		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
6994		return (ENOENT);
6995	}
6996	(*addr) = (struct sockaddr *)sin;
6997	return (0);
6998}
6999
7000struct pr_usrreqs sctp_usrreqs = {
7001	.pru_abort = sctp_abort,
7002	.pru_accept = sctp_accept,
7003	.pru_attach = sctp_attach,
7004	.pru_bind = sctp_bind,
7005	.pru_connect = sctp_connect,
7006	.pru_control = in_control,
7007	.pru_close = sctp_close,
7008	.pru_detach = sctp_close,
7009	.pru_sopoll = sopoll_generic,
7010	.pru_flush = sctp_flush,
7011	.pru_disconnect = sctp_disconnect,
7012	.pru_listen = sctp_listen,
7013	.pru_peeraddr = sctp_peeraddr,
7014	.pru_send = sctp_sendm,
7015	.pru_shutdown = sctp_shutdown,
7016	.pru_sockaddr = sctp_ingetaddr,
7017	.pru_sosend = sctp_sosend,
7018	.pru_soreceive = sctp_soreceive
7019};
7020
7021#endif
7022