sctp_usrreq.c revision 270362
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 270362 2014-08-22 20:22:12Z 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 = (struct sockaddr_in *)&sctp_ifa->address.sa;
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 = (struct sockaddr_in6 *)&sctp_ifa->address.sa;
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	default:
3514		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
3515		error = ENOPROTOOPT;
3516		break;
3517	}			/* end switch (sopt->sopt_name) */
3518	if (error) {
3519		*optsize = 0;
3520	}
3521	return (error);
3522}
3523
3524static int
3525sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
3526    void *p)
3527{
3528	int error, set_opt;
3529	uint32_t *mopt;
3530	struct sctp_tcb *stcb = NULL;
3531	struct sctp_inpcb *inp = NULL;
3532	uint32_t vrf_id;
3533
3534	if (optval == NULL) {
3535		SCTP_PRINTF("optval is NULL\n");
3536		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3537		return (EINVAL);
3538	}
3539	inp = (struct sctp_inpcb *)so->so_pcb;
3540	if (inp == NULL) {
3541		SCTP_PRINTF("inp is NULL?\n");
3542		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3543		return (EINVAL);
3544	}
3545	vrf_id = inp->def_vrf_id;
3546
3547	error = 0;
3548	switch (optname) {
3549	case SCTP_NODELAY:
3550	case SCTP_AUTOCLOSE:
3551	case SCTP_AUTO_ASCONF:
3552	case SCTP_EXPLICIT_EOR:
3553	case SCTP_DISABLE_FRAGMENTS:
3554	case SCTP_USE_EXT_RCVINFO:
3555	case SCTP_I_WANT_MAPPED_V4_ADDR:
3556		/* copy in the option value */
3557		SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
3558		set_opt = 0;
3559		if (error)
3560			break;
3561		switch (optname) {
3562		case SCTP_DISABLE_FRAGMENTS:
3563			set_opt = SCTP_PCB_FLAGS_NO_FRAGMENT;
3564			break;
3565		case SCTP_AUTO_ASCONF:
3566			/*
3567			 * NOTE: we don't really support this flag
3568			 */
3569			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
3570				/* only valid for bound all sockets */
3571				if ((SCTP_BASE_SYSCTL(sctp_auto_asconf) == 0) &&
3572				    (*mopt != 0)) {
3573					/* forbidden by admin */
3574					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EPERM);
3575					return (EPERM);
3576				}
3577				set_opt = SCTP_PCB_FLAGS_AUTO_ASCONF;
3578			} else {
3579				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3580				return (EINVAL);
3581			}
3582			break;
3583		case SCTP_EXPLICIT_EOR:
3584			set_opt = SCTP_PCB_FLAGS_EXPLICIT_EOR;
3585			break;
3586		case SCTP_USE_EXT_RCVINFO:
3587			set_opt = SCTP_PCB_FLAGS_EXT_RCVINFO;
3588			break;
3589		case SCTP_I_WANT_MAPPED_V4_ADDR:
3590			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
3591				set_opt = SCTP_PCB_FLAGS_NEEDS_MAPPED_V4;
3592			} else {
3593				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3594				return (EINVAL);
3595			}
3596			break;
3597		case SCTP_NODELAY:
3598			set_opt = SCTP_PCB_FLAGS_NODELAY;
3599			break;
3600		case SCTP_AUTOCLOSE:
3601			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3602			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
3603				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3604				return (EINVAL);
3605			}
3606			set_opt = SCTP_PCB_FLAGS_AUTOCLOSE;
3607			/*
3608			 * The value is in ticks. Note this does not effect
3609			 * old associations, only new ones.
3610			 */
3611			inp->sctp_ep.auto_close_time = SEC_TO_TICKS(*mopt);
3612			break;
3613		}
3614		SCTP_INP_WLOCK(inp);
3615		if (*mopt != 0) {
3616			sctp_feature_on(inp, set_opt);
3617		} else {
3618			sctp_feature_off(inp, set_opt);
3619		}
3620		SCTP_INP_WUNLOCK(inp);
3621		break;
3622	case SCTP_REUSE_PORT:
3623		{
3624			SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
3625			if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) {
3626				/* Can't set it after we are bound */
3627				error = EINVAL;
3628				break;
3629			}
3630			if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
3631				/* Can't do this for a 1-m socket */
3632				error = EINVAL;
3633				break;
3634			}
3635			if (optval)
3636				sctp_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE);
3637			else
3638				sctp_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE);
3639			break;
3640		}
3641	case SCTP_PARTIAL_DELIVERY_POINT:
3642		{
3643			uint32_t *value;
3644
3645			SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
3646			if (*value > SCTP_SB_LIMIT_RCV(so)) {
3647				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3648				error = EINVAL;
3649				break;
3650			}
3651			inp->partial_delivery_point = *value;
3652			break;
3653		}
3654	case SCTP_FRAGMENT_INTERLEAVE:
3655		/* not yet until we re-write sctp_recvmsg() */
3656		{
3657			uint32_t *level;
3658
3659			SCTP_CHECK_AND_CAST(level, optval, uint32_t, optsize);
3660			if (*level == SCTP_FRAG_LEVEL_2) {
3661				sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
3662				sctp_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
3663			} else if (*level == SCTP_FRAG_LEVEL_1) {
3664				sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
3665				sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
3666			} else if (*level == SCTP_FRAG_LEVEL_0) {
3667				sctp_feature_off(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
3668				sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
3669
3670			} else {
3671				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3672				error = EINVAL;
3673			}
3674			break;
3675		}
3676	case SCTP_CMT_ON_OFF:
3677		if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
3678			struct sctp_assoc_value *av;
3679
3680			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
3681			if (av->assoc_value > SCTP_CMT_MAX) {
3682				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3683				error = EINVAL;
3684				break;
3685			}
3686			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3687			if (stcb) {
3688				stcb->asoc.sctp_cmt_on_off = av->assoc_value;
3689				SCTP_TCB_UNLOCK(stcb);
3690			} else {
3691				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3692				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3693				    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
3694				    (av->assoc_id == SCTP_ALL_ASSOC)) {
3695					SCTP_INP_WLOCK(inp);
3696					inp->sctp_cmt_on_off = av->assoc_value;
3697					SCTP_INP_WUNLOCK(inp);
3698				}
3699				if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
3700				    (av->assoc_id == SCTP_ALL_ASSOC)) {
3701					SCTP_INP_RLOCK(inp);
3702					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3703						SCTP_TCB_LOCK(stcb);
3704						stcb->asoc.sctp_cmt_on_off = av->assoc_value;
3705						SCTP_TCB_UNLOCK(stcb);
3706					}
3707					SCTP_INP_RUNLOCK(inp);
3708				}
3709			}
3710		} else {
3711			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
3712			error = ENOPROTOOPT;
3713		}
3714		break;
3715	case SCTP_PLUGGABLE_CC:
3716		{
3717			struct sctp_assoc_value *av;
3718			struct sctp_nets *net;
3719
3720			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
3721			if ((av->assoc_value != SCTP_CC_RFC2581) &&
3722			    (av->assoc_value != SCTP_CC_HSTCP) &&
3723			    (av->assoc_value != SCTP_CC_HTCP) &&
3724			    (av->assoc_value != SCTP_CC_RTCC)) {
3725				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3726				error = EINVAL;
3727				break;
3728			}
3729			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3730			if (stcb) {
3731				stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
3732				stcb->asoc.congestion_control_module = av->assoc_value;
3733				if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
3734					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
3735						stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
3736					}
3737				}
3738				SCTP_TCB_UNLOCK(stcb);
3739			} else {
3740				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3741				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3742				    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
3743				    (av->assoc_id == SCTP_ALL_ASSOC)) {
3744					SCTP_INP_WLOCK(inp);
3745					inp->sctp_ep.sctp_default_cc_module = av->assoc_value;
3746					SCTP_INP_WUNLOCK(inp);
3747				}
3748				if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
3749				    (av->assoc_id == SCTP_ALL_ASSOC)) {
3750					SCTP_INP_RLOCK(inp);
3751					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3752						SCTP_TCB_LOCK(stcb);
3753						stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
3754						stcb->asoc.congestion_control_module = av->assoc_value;
3755						if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
3756							TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
3757								stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
3758							}
3759						}
3760						SCTP_TCB_UNLOCK(stcb);
3761					}
3762					SCTP_INP_RUNLOCK(inp);
3763				}
3764			}
3765			break;
3766		}
3767	case SCTP_CC_OPTION:
3768		{
3769			struct sctp_cc_option *cc_opt;
3770
3771			SCTP_CHECK_AND_CAST(cc_opt, optval, struct sctp_cc_option, optsize);
3772			SCTP_FIND_STCB(inp, stcb, cc_opt->aid_value.assoc_id);
3773			if (stcb == NULL) {
3774				if (cc_opt->aid_value.assoc_id == SCTP_CURRENT_ASSOC) {
3775					SCTP_INP_RLOCK(inp);
3776					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3777						SCTP_TCB_LOCK(stcb);
3778						if (stcb->asoc.cc_functions.sctp_cwnd_socket_option) {
3779							(*stcb->asoc.cc_functions.sctp_cwnd_socket_option) (stcb, 1, cc_opt);
3780						}
3781						SCTP_TCB_UNLOCK(stcb);
3782					}
3783					SCTP_INP_RUNLOCK(inp);
3784				} else {
3785					error = EINVAL;
3786				}
3787			} else {
3788				if (stcb->asoc.cc_functions.sctp_cwnd_socket_option == NULL) {
3789					error = ENOTSUP;
3790				} else {
3791					error = (*stcb->asoc.cc_functions.sctp_cwnd_socket_option) (stcb, 1,
3792					    cc_opt);
3793				}
3794				SCTP_TCB_UNLOCK(stcb);
3795			}
3796			break;
3797		}
3798	case SCTP_PLUGGABLE_SS:
3799		{
3800			struct sctp_assoc_value *av;
3801
3802			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
3803			if ((av->assoc_value != SCTP_SS_DEFAULT) &&
3804			    (av->assoc_value != SCTP_SS_ROUND_ROBIN) &&
3805			    (av->assoc_value != SCTP_SS_ROUND_ROBIN_PACKET) &&
3806			    (av->assoc_value != SCTP_SS_PRIORITY) &&
3807			    (av->assoc_value != SCTP_SS_FAIR_BANDWITH) &&
3808			    (av->assoc_value != SCTP_SS_FIRST_COME)) {
3809				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3810				error = EINVAL;
3811				break;
3812			}
3813			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3814			if (stcb) {
3815				stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1);
3816				stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
3817				stcb->asoc.stream_scheduling_module = av->assoc_value;
3818				stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
3819				SCTP_TCB_UNLOCK(stcb);
3820			} else {
3821				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3822				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3823				    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
3824				    (av->assoc_id == SCTP_ALL_ASSOC)) {
3825					SCTP_INP_WLOCK(inp);
3826					inp->sctp_ep.sctp_default_ss_module = av->assoc_value;
3827					SCTP_INP_WUNLOCK(inp);
3828				}
3829				if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
3830				    (av->assoc_id == SCTP_ALL_ASSOC)) {
3831					SCTP_INP_RLOCK(inp);
3832					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3833						SCTP_TCB_LOCK(stcb);
3834						stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1);
3835						stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
3836						stcb->asoc.stream_scheduling_module = av->assoc_value;
3837						stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
3838						SCTP_TCB_UNLOCK(stcb);
3839					}
3840					SCTP_INP_RUNLOCK(inp);
3841				}
3842			}
3843			break;
3844		}
3845	case SCTP_SS_VALUE:
3846		{
3847			struct sctp_stream_value *av;
3848
3849			SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, optsize);
3850			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3851			if (stcb) {
3852				if (stcb->asoc.ss_functions.sctp_ss_set_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id],
3853				    av->stream_value) < 0) {
3854					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3855					error = EINVAL;
3856				}
3857				SCTP_TCB_UNLOCK(stcb);
3858			} else {
3859				if (av->assoc_id == SCTP_CURRENT_ASSOC) {
3860					SCTP_INP_RLOCK(inp);
3861					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3862						SCTP_TCB_LOCK(stcb);
3863						stcb->asoc.ss_functions.sctp_ss_set_value(stcb,
3864						    &stcb->asoc,
3865						    &stcb->asoc.strmout[av->stream_id],
3866						    av->stream_value);
3867						SCTP_TCB_UNLOCK(stcb);
3868					}
3869					SCTP_INP_RUNLOCK(inp);
3870
3871				} else {
3872					/*
3873					 * Can't set stream value without
3874					 * association
3875					 */
3876					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3877					error = EINVAL;
3878				}
3879			}
3880			break;
3881		}
3882	case SCTP_CLR_STAT_LOG:
3883		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
3884		error = EOPNOTSUPP;
3885		break;
3886	case SCTP_CONTEXT:
3887		{
3888			struct sctp_assoc_value *av;
3889
3890			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
3891			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3892
3893			if (stcb) {
3894				stcb->asoc.context = av->assoc_value;
3895				SCTP_TCB_UNLOCK(stcb);
3896			} else {
3897				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3898				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3899				    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
3900				    (av->assoc_id == SCTP_ALL_ASSOC)) {
3901					SCTP_INP_WLOCK(inp);
3902					inp->sctp_context = av->assoc_value;
3903					SCTP_INP_WUNLOCK(inp);
3904				}
3905				if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
3906				    (av->assoc_id == SCTP_ALL_ASSOC)) {
3907					SCTP_INP_RLOCK(inp);
3908					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3909						SCTP_TCB_LOCK(stcb);
3910						stcb->asoc.context = av->assoc_value;
3911						SCTP_TCB_UNLOCK(stcb);
3912					}
3913					SCTP_INP_RUNLOCK(inp);
3914				}
3915			}
3916			break;
3917		}
3918	case SCTP_VRF_ID:
3919		{
3920			uint32_t *default_vrfid;
3921
3922			SCTP_CHECK_AND_CAST(default_vrfid, optval, uint32_t, optsize);
3923			if (*default_vrfid > SCTP_MAX_VRF_ID) {
3924				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3925				error = EINVAL;
3926				break;
3927			}
3928			inp->def_vrf_id = *default_vrfid;
3929			break;
3930		}
3931	case SCTP_DEL_VRF_ID:
3932		{
3933			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
3934			error = EOPNOTSUPP;
3935			break;
3936		}
3937	case SCTP_ADD_VRF_ID:
3938		{
3939			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
3940			error = EOPNOTSUPP;
3941			break;
3942		}
3943	case SCTP_DELAYED_SACK:
3944		{
3945			struct sctp_sack_info *sack;
3946
3947			SCTP_CHECK_AND_CAST(sack, optval, struct sctp_sack_info, optsize);
3948			SCTP_FIND_STCB(inp, stcb, sack->sack_assoc_id);
3949			if (sack->sack_delay) {
3950				if (sack->sack_delay > SCTP_MAX_SACK_DELAY)
3951					sack->sack_delay = SCTP_MAX_SACK_DELAY;
3952				if (MSEC_TO_TICKS(sack->sack_delay) < 1) {
3953					sack->sack_delay = TICKS_TO_MSEC(1);
3954				}
3955			}
3956			if (stcb) {
3957				if (sack->sack_delay) {
3958					stcb->asoc.delayed_ack = sack->sack_delay;
3959				}
3960				if (sack->sack_freq) {
3961					stcb->asoc.sack_freq = sack->sack_freq;
3962				}
3963				SCTP_TCB_UNLOCK(stcb);
3964			} else {
3965				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3966				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3967				    (sack->sack_assoc_id == SCTP_FUTURE_ASSOC) ||
3968				    (sack->sack_assoc_id == SCTP_ALL_ASSOC)) {
3969					SCTP_INP_WLOCK(inp);
3970					if (sack->sack_delay) {
3971						inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV] = MSEC_TO_TICKS(sack->sack_delay);
3972					}
3973					if (sack->sack_freq) {
3974						inp->sctp_ep.sctp_sack_freq = sack->sack_freq;
3975					}
3976					SCTP_INP_WUNLOCK(inp);
3977				}
3978				if ((sack->sack_assoc_id == SCTP_CURRENT_ASSOC) ||
3979				    (sack->sack_assoc_id == SCTP_ALL_ASSOC)) {
3980					SCTP_INP_RLOCK(inp);
3981					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3982						SCTP_TCB_LOCK(stcb);
3983						if (sack->sack_delay) {
3984							stcb->asoc.delayed_ack = sack->sack_delay;
3985						}
3986						if (sack->sack_freq) {
3987							stcb->asoc.sack_freq = sack->sack_freq;
3988						}
3989						SCTP_TCB_UNLOCK(stcb);
3990					}
3991					SCTP_INP_RUNLOCK(inp);
3992				}
3993			}
3994			break;
3995		}
3996	case SCTP_AUTH_CHUNK:
3997		{
3998			struct sctp_authchunk *sauth;
3999
4000			SCTP_CHECK_AND_CAST(sauth, optval, struct sctp_authchunk, optsize);
4001
4002			SCTP_INP_WLOCK(inp);
4003			if (sctp_auth_add_chunk(sauth->sauth_chunk, inp->sctp_ep.local_auth_chunks)) {
4004				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4005				error = EINVAL;
4006			}
4007			SCTP_INP_WUNLOCK(inp);
4008			break;
4009		}
4010	case SCTP_AUTH_KEY:
4011		{
4012			struct sctp_authkey *sca;
4013			struct sctp_keyhead *shared_keys;
4014			sctp_sharedkey_t *shared_key;
4015			sctp_key_t *key = NULL;
4016			size_t size;
4017
4018			SCTP_CHECK_AND_CAST(sca, optval, struct sctp_authkey, optsize);
4019			if (sca->sca_keylength == 0) {
4020				size = optsize - sizeof(struct sctp_authkey);
4021			} else {
4022				if (sca->sca_keylength + sizeof(struct sctp_authkey) <= optsize) {
4023					size = sca->sca_keylength;
4024				} else {
4025					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4026					error = EINVAL;
4027					break;
4028				}
4029			}
4030			SCTP_FIND_STCB(inp, stcb, sca->sca_assoc_id);
4031
4032			if (stcb) {
4033				shared_keys = &stcb->asoc.shared_keys;
4034				/* clear the cached keys for this key id */
4035				sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
4036				/*
4037				 * create the new shared key and
4038				 * insert/replace it
4039				 */
4040				if (size > 0) {
4041					key = sctp_set_key(sca->sca_key, (uint32_t) size);
4042					if (key == NULL) {
4043						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4044						error = ENOMEM;
4045						SCTP_TCB_UNLOCK(stcb);
4046						break;
4047					}
4048				}
4049				shared_key = sctp_alloc_sharedkey();
4050				if (shared_key == NULL) {
4051					sctp_free_key(key);
4052					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4053					error = ENOMEM;
4054					SCTP_TCB_UNLOCK(stcb);
4055					break;
4056				}
4057				shared_key->key = key;
4058				shared_key->keyid = sca->sca_keynumber;
4059				error = sctp_insert_sharedkey(shared_keys, shared_key);
4060				SCTP_TCB_UNLOCK(stcb);
4061			} else {
4062				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4063				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4064				    (sca->sca_assoc_id == SCTP_FUTURE_ASSOC) ||
4065				    (sca->sca_assoc_id == SCTP_ALL_ASSOC)) {
4066					SCTP_INP_WLOCK(inp);
4067					shared_keys = &inp->sctp_ep.shared_keys;
4068					/*
4069					 * clear the cached keys on all
4070					 * assocs for this key id
4071					 */
4072					sctp_clear_cachedkeys_ep(inp, sca->sca_keynumber);
4073					/*
4074					 * create the new shared key and
4075					 * insert/replace it
4076					 */
4077					if (size > 0) {
4078						key = sctp_set_key(sca->sca_key, (uint32_t) size);
4079						if (key == NULL) {
4080							SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4081							error = ENOMEM;
4082							SCTP_INP_WUNLOCK(inp);
4083							break;
4084						}
4085					}
4086					shared_key = sctp_alloc_sharedkey();
4087					if (shared_key == NULL) {
4088						sctp_free_key(key);
4089						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4090						error = ENOMEM;
4091						SCTP_INP_WUNLOCK(inp);
4092						break;
4093					}
4094					shared_key->key = key;
4095					shared_key->keyid = sca->sca_keynumber;
4096					error = sctp_insert_sharedkey(shared_keys, shared_key);
4097					SCTP_INP_WUNLOCK(inp);
4098				}
4099				if ((sca->sca_assoc_id == SCTP_CURRENT_ASSOC) ||
4100				    (sca->sca_assoc_id == SCTP_ALL_ASSOC)) {
4101					SCTP_INP_RLOCK(inp);
4102					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4103						SCTP_TCB_LOCK(stcb);
4104						shared_keys = &stcb->asoc.shared_keys;
4105						/*
4106						 * clear the cached keys for
4107						 * this key id
4108						 */
4109						sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
4110						/*
4111						 * create the new shared key
4112						 * and insert/replace it
4113						 */
4114						if (size > 0) {
4115							key = sctp_set_key(sca->sca_key, (uint32_t) size);
4116							if (key == NULL) {
4117								SCTP_TCB_UNLOCK(stcb);
4118								continue;
4119							}
4120						}
4121						shared_key = sctp_alloc_sharedkey();
4122						if (shared_key == NULL) {
4123							sctp_free_key(key);
4124							SCTP_TCB_UNLOCK(stcb);
4125							continue;
4126						}
4127						shared_key->key = key;
4128						shared_key->keyid = sca->sca_keynumber;
4129						error = sctp_insert_sharedkey(shared_keys, shared_key);
4130						SCTP_TCB_UNLOCK(stcb);
4131					}
4132					SCTP_INP_RUNLOCK(inp);
4133				}
4134			}
4135			break;
4136		}
4137	case SCTP_HMAC_IDENT:
4138		{
4139			struct sctp_hmacalgo *shmac;
4140			sctp_hmaclist_t *hmaclist;
4141			uint16_t hmacid;
4142			uint32_t i;
4143
4144			SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, optsize);
4145			if (optsize < sizeof(struct sctp_hmacalgo) + shmac->shmac_number_of_idents * sizeof(uint16_t)) {
4146				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4147				error = EINVAL;
4148				break;
4149			}
4150			hmaclist = sctp_alloc_hmaclist(shmac->shmac_number_of_idents);
4151			if (hmaclist == NULL) {
4152				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4153				error = ENOMEM;
4154				break;
4155			}
4156			for (i = 0; i < shmac->shmac_number_of_idents; i++) {
4157				hmacid = shmac->shmac_idents[i];
4158				if (sctp_auth_add_hmacid(hmaclist, hmacid)) {
4159					 /* invalid HMACs were found */ ;
4160					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4161					error = EINVAL;
4162					sctp_free_hmaclist(hmaclist);
4163					goto sctp_set_hmac_done;
4164				}
4165			}
4166			for (i = 0; i < hmaclist->num_algo; i++) {
4167				if (hmaclist->hmac[i] == SCTP_AUTH_HMAC_ID_SHA1) {
4168					/* already in list */
4169					break;
4170				}
4171			}
4172			if (i == hmaclist->num_algo) {
4173				/* not found in list */
4174				sctp_free_hmaclist(hmaclist);
4175				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4176				error = EINVAL;
4177				break;
4178			}
4179			/* set it on the endpoint */
4180			SCTP_INP_WLOCK(inp);
4181			if (inp->sctp_ep.local_hmacs)
4182				sctp_free_hmaclist(inp->sctp_ep.local_hmacs);
4183			inp->sctp_ep.local_hmacs = hmaclist;
4184			SCTP_INP_WUNLOCK(inp);
4185	sctp_set_hmac_done:
4186			break;
4187		}
4188	case SCTP_AUTH_ACTIVE_KEY:
4189		{
4190			struct sctp_authkeyid *scact;
4191
4192			SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, optsize);
4193			SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id);
4194
4195			/* set the active key on the right place */
4196			if (stcb) {
4197				/* set the active key on the assoc */
4198				if (sctp_auth_setactivekey(stcb,
4199				    scact->scact_keynumber)) {
4200					SCTP_LTRACE_ERR_RET(inp, NULL, NULL,
4201					    SCTP_FROM_SCTP_USRREQ,
4202					    EINVAL);
4203					error = EINVAL;
4204				}
4205				SCTP_TCB_UNLOCK(stcb);
4206			} else {
4207				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4208				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4209				    (scact->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
4210				    (scact->scact_assoc_id == SCTP_ALL_ASSOC)) {
4211					SCTP_INP_WLOCK(inp);
4212					if (sctp_auth_setactivekey_ep(inp, scact->scact_keynumber)) {
4213						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4214						error = EINVAL;
4215					}
4216					SCTP_INP_WUNLOCK(inp);
4217				}
4218				if ((scact->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
4219				    (scact->scact_assoc_id == SCTP_ALL_ASSOC)) {
4220					SCTP_INP_RLOCK(inp);
4221					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4222						SCTP_TCB_LOCK(stcb);
4223						sctp_auth_setactivekey(stcb, scact->scact_keynumber);
4224						SCTP_TCB_UNLOCK(stcb);
4225					}
4226					SCTP_INP_RUNLOCK(inp);
4227				}
4228			}
4229			break;
4230		}
4231	case SCTP_AUTH_DELETE_KEY:
4232		{
4233			struct sctp_authkeyid *scdel;
4234
4235			SCTP_CHECK_AND_CAST(scdel, optval, struct sctp_authkeyid, optsize);
4236			SCTP_FIND_STCB(inp, stcb, scdel->scact_assoc_id);
4237
4238			/* delete the key from the right place */
4239			if (stcb) {
4240				if (sctp_delete_sharedkey(stcb, scdel->scact_keynumber)) {
4241					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4242					error = EINVAL;
4243				}
4244				SCTP_TCB_UNLOCK(stcb);
4245			} else {
4246				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4247				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4248				    (scdel->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
4249				    (scdel->scact_assoc_id == SCTP_ALL_ASSOC)) {
4250					SCTP_INP_WLOCK(inp);
4251					if (sctp_delete_sharedkey_ep(inp, scdel->scact_keynumber)) {
4252						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4253						error = EINVAL;
4254					}
4255					SCTP_INP_WUNLOCK(inp);
4256				}
4257				if ((scdel->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
4258				    (scdel->scact_assoc_id == SCTP_ALL_ASSOC)) {
4259					SCTP_INP_RLOCK(inp);
4260					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4261						SCTP_TCB_LOCK(stcb);
4262						sctp_delete_sharedkey(stcb, scdel->scact_keynumber);
4263						SCTP_TCB_UNLOCK(stcb);
4264					}
4265					SCTP_INP_RUNLOCK(inp);
4266				}
4267			}
4268			break;
4269		}
4270	case SCTP_AUTH_DEACTIVATE_KEY:
4271		{
4272			struct sctp_authkeyid *keyid;
4273
4274			SCTP_CHECK_AND_CAST(keyid, optval, struct sctp_authkeyid, optsize);
4275			SCTP_FIND_STCB(inp, stcb, keyid->scact_assoc_id);
4276
4277			/* deactivate the key from the right place */
4278			if (stcb) {
4279				if (sctp_deact_sharedkey(stcb, keyid->scact_keynumber)) {
4280					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4281					error = EINVAL;
4282				}
4283				SCTP_TCB_UNLOCK(stcb);
4284			} else {
4285				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4286				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4287				    (keyid->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
4288				    (keyid->scact_assoc_id == SCTP_ALL_ASSOC)) {
4289					SCTP_INP_WLOCK(inp);
4290					if (sctp_deact_sharedkey_ep(inp, keyid->scact_keynumber)) {
4291						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4292						error = EINVAL;
4293					}
4294					SCTP_INP_WUNLOCK(inp);
4295				}
4296				if ((keyid->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
4297				    (keyid->scact_assoc_id == SCTP_ALL_ASSOC)) {
4298					SCTP_INP_RLOCK(inp);
4299					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4300						SCTP_TCB_LOCK(stcb);
4301						sctp_deact_sharedkey(stcb, keyid->scact_keynumber);
4302						SCTP_TCB_UNLOCK(stcb);
4303					}
4304					SCTP_INP_RUNLOCK(inp);
4305				}
4306			}
4307			break;
4308		}
4309	case SCTP_ENABLE_STREAM_RESET:
4310		{
4311			struct sctp_assoc_value *av;
4312
4313			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4314			if (av->assoc_value & (~SCTP_ENABLE_VALUE_MASK)) {
4315				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4316				error = EINVAL;
4317				break;
4318			}
4319			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4320			if (stcb) {
4321				stcb->asoc.local_strreset_support = (uint8_t) av->assoc_value;
4322				SCTP_TCB_UNLOCK(stcb);
4323			} else {
4324				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4325				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4326				    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
4327				    (av->assoc_id == SCTP_ALL_ASSOC)) {
4328					SCTP_INP_WLOCK(inp);
4329					inp->local_strreset_support = (uint8_t) av->assoc_value;
4330					SCTP_INP_WUNLOCK(inp);
4331				}
4332				if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4333				    (av->assoc_id == SCTP_ALL_ASSOC)) {
4334					SCTP_INP_RLOCK(inp);
4335					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4336						SCTP_TCB_LOCK(stcb);
4337						stcb->asoc.local_strreset_support = (uint8_t) av->assoc_value;
4338						SCTP_TCB_UNLOCK(stcb);
4339					}
4340					SCTP_INP_RUNLOCK(inp);
4341				}
4342			}
4343			break;
4344		}
4345	case SCTP_RESET_STREAMS:
4346		{
4347			struct sctp_reset_streams *strrst;
4348			int i, send_out = 0;
4349			int send_in = 0;
4350
4351			SCTP_CHECK_AND_CAST(strrst, optval, struct sctp_reset_streams, optsize);
4352			SCTP_FIND_STCB(inp, stcb, strrst->srs_assoc_id);
4353			if (stcb == NULL) {
4354				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4355				error = ENOENT;
4356				break;
4357			}
4358			if (stcb->asoc.reconfig_supported == 0) {
4359				/*
4360				 * Peer does not support the chunk type.
4361				 */
4362				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4363				error = EOPNOTSUPP;
4364				SCTP_TCB_UNLOCK(stcb);
4365				break;
4366			}
4367			if (stcb->asoc.stream_reset_outstanding) {
4368				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4369				error = EALREADY;
4370				SCTP_TCB_UNLOCK(stcb);
4371				break;
4372			}
4373			if (strrst->srs_flags & SCTP_STREAM_RESET_INCOMING) {
4374				send_in = 1;
4375			}
4376			if (strrst->srs_flags & SCTP_STREAM_RESET_OUTGOING) {
4377				send_out = 1;
4378			}
4379			if ((send_in == 0) && (send_out == 0)) {
4380				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4381				error = EINVAL;
4382				SCTP_TCB_UNLOCK(stcb);
4383				break;
4384			}
4385			for (i = 0; i < strrst->srs_number_streams; i++) {
4386				if ((send_in) &&
4387				    (strrst->srs_stream_list[i] > stcb->asoc.streamincnt)) {
4388					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4389					error = EINVAL;
4390					break;
4391				}
4392				if ((send_out) &&
4393				    (strrst->srs_stream_list[i] > stcb->asoc.streamoutcnt)) {
4394					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4395					error = EINVAL;
4396					break;
4397				}
4398			}
4399			if (error) {
4400				SCTP_TCB_UNLOCK(stcb);
4401				break;
4402			}
4403			error = sctp_send_str_reset_req(stcb, strrst->srs_number_streams,
4404			    strrst->srs_stream_list,
4405			    send_out, send_in, 0, 0, 0, 0, 0);
4406
4407			sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
4408			SCTP_TCB_UNLOCK(stcb);
4409			break;
4410		}
4411	case SCTP_ADD_STREAMS:
4412		{
4413			struct sctp_add_streams *stradd;
4414			uint8_t addstream = 0;
4415			uint16_t add_o_strmcnt = 0;
4416			uint16_t add_i_strmcnt = 0;
4417
4418			SCTP_CHECK_AND_CAST(stradd, optval, struct sctp_add_streams, optsize);
4419			SCTP_FIND_STCB(inp, stcb, stradd->sas_assoc_id);
4420			if (stcb == NULL) {
4421				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4422				error = ENOENT;
4423				break;
4424			}
4425			if (stcb->asoc.reconfig_supported == 0) {
4426				/*
4427				 * Peer does not support the chunk type.
4428				 */
4429				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4430				error = EOPNOTSUPP;
4431				SCTP_TCB_UNLOCK(stcb);
4432				break;
4433			}
4434			if (stcb->asoc.stream_reset_outstanding) {
4435				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4436				error = EALREADY;
4437				SCTP_TCB_UNLOCK(stcb);
4438				break;
4439			}
4440			if ((stradd->sas_outstrms == 0) &&
4441			    (stradd->sas_instrms == 0)) {
4442				error = EINVAL;
4443				goto skip_stuff;
4444			}
4445			if (stradd->sas_outstrms) {
4446				addstream = 1;
4447				/* We allocate here */
4448				add_o_strmcnt = stradd->sas_outstrms;
4449				if ((((int)add_o_strmcnt) + ((int)stcb->asoc.streamoutcnt)) > 0x0000ffff) {
4450					/* You can't have more than 64k */
4451					error = EINVAL;
4452					goto skip_stuff;
4453				}
4454			}
4455			if (stradd->sas_instrms) {
4456				int cnt;
4457
4458				addstream |= 2;
4459				/*
4460				 * We allocate inside
4461				 * sctp_send_str_reset_req()
4462				 */
4463				add_i_strmcnt = stradd->sas_instrms;
4464				cnt = add_i_strmcnt;
4465				cnt += stcb->asoc.streamincnt;
4466				if (cnt > 0x0000ffff) {
4467					/* You can't have more than 64k */
4468					error = EINVAL;
4469					goto skip_stuff;
4470				}
4471				if (cnt > (int)stcb->asoc.max_inbound_streams) {
4472					/* More than you are allowed */
4473					error = EINVAL;
4474					goto skip_stuff;
4475				}
4476			}
4477			error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 0, addstream, add_o_strmcnt, add_i_strmcnt, 0);
4478			sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
4479	skip_stuff:
4480			SCTP_TCB_UNLOCK(stcb);
4481			break;
4482		}
4483	case SCTP_RESET_ASSOC:
4484		{
4485			uint32_t *value;
4486
4487			SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
4488			SCTP_FIND_STCB(inp, stcb, (sctp_assoc_t) * value);
4489			if (stcb == NULL) {
4490				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4491				error = ENOENT;
4492				break;
4493			}
4494			if (stcb->asoc.reconfig_supported == 0) {
4495				/*
4496				 * Peer does not support the chunk type.
4497				 */
4498				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4499				error = EOPNOTSUPP;
4500				SCTP_TCB_UNLOCK(stcb);
4501				break;
4502			}
4503			if (stcb->asoc.stream_reset_outstanding) {
4504				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4505				error = EALREADY;
4506				SCTP_TCB_UNLOCK(stcb);
4507				break;
4508			}
4509			error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 1, 0, 0, 0, 0);
4510			sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
4511			SCTP_TCB_UNLOCK(stcb);
4512			break;
4513		}
4514	case SCTP_CONNECT_X:
4515		if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
4516			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4517			error = EINVAL;
4518			break;
4519		}
4520		error = sctp_do_connect_x(so, inp, optval, optsize, p, 0);
4521		break;
4522	case SCTP_CONNECT_X_DELAYED:
4523		if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
4524			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4525			error = EINVAL;
4526			break;
4527		}
4528		error = sctp_do_connect_x(so, inp, optval, optsize, p, 1);
4529		break;
4530	case SCTP_CONNECT_X_COMPLETE:
4531		{
4532			struct sockaddr *sa;
4533			struct sctp_nets *net;
4534
4535			/* FIXME MT: check correct? */
4536			SCTP_CHECK_AND_CAST(sa, optval, struct sockaddr, optsize);
4537
4538			/* find tcb */
4539			if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
4540				SCTP_INP_RLOCK(inp);
4541				stcb = LIST_FIRST(&inp->sctp_asoc_list);
4542				if (stcb) {
4543					SCTP_TCB_LOCK(stcb);
4544					net = sctp_findnet(stcb, sa);
4545				}
4546				SCTP_INP_RUNLOCK(inp);
4547			} else {
4548				/*
4549				 * We increment here since
4550				 * sctp_findassociation_ep_addr() wil do a
4551				 * decrement if it finds the stcb as long as
4552				 * the locked tcb (last argument) is NOT a
4553				 * TCB.. aka NULL.
4554				 */
4555				SCTP_INP_INCR_REF(inp);
4556				stcb = sctp_findassociation_ep_addr(&inp, sa, &net, NULL, NULL);
4557				if (stcb == NULL) {
4558					SCTP_INP_DECR_REF(inp);
4559				}
4560			}
4561
4562			if (stcb == NULL) {
4563				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4564				error = ENOENT;
4565				break;
4566			}
4567			if (stcb->asoc.delayed_connection == 1) {
4568				stcb->asoc.delayed_connection = 0;
4569				(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
4570				sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb,
4571				    stcb->asoc.primary_destination,
4572				    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_9);
4573				sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
4574			} else {
4575				/*
4576				 * already expired or did not use delayed
4577				 * connectx
4578				 */
4579				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4580				error = EALREADY;
4581			}
4582			SCTP_TCB_UNLOCK(stcb);
4583			break;
4584		}
4585	case SCTP_MAX_BURST:
4586		{
4587			struct sctp_assoc_value *av;
4588
4589			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4590			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4591
4592			if (stcb) {
4593				stcb->asoc.max_burst = av->assoc_value;
4594				SCTP_TCB_UNLOCK(stcb);
4595			} else {
4596				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4597				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4598				    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
4599				    (av->assoc_id == SCTP_ALL_ASSOC)) {
4600					SCTP_INP_WLOCK(inp);
4601					inp->sctp_ep.max_burst = av->assoc_value;
4602					SCTP_INP_WUNLOCK(inp);
4603				}
4604				if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4605				    (av->assoc_id == SCTP_ALL_ASSOC)) {
4606					SCTP_INP_RLOCK(inp);
4607					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4608						SCTP_TCB_LOCK(stcb);
4609						stcb->asoc.max_burst = av->assoc_value;
4610						SCTP_TCB_UNLOCK(stcb);
4611					}
4612					SCTP_INP_RUNLOCK(inp);
4613				}
4614			}
4615			break;
4616		}
4617	case SCTP_MAXSEG:
4618		{
4619			struct sctp_assoc_value *av;
4620			int ovh;
4621
4622			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4623			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4624
4625			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
4626				ovh = SCTP_MED_OVERHEAD;
4627			} else {
4628				ovh = SCTP_MED_V4_OVERHEAD;
4629			}
4630			if (stcb) {
4631				if (av->assoc_value) {
4632					stcb->asoc.sctp_frag_point = (av->assoc_value + ovh);
4633				} else {
4634					stcb->asoc.sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
4635				}
4636				SCTP_TCB_UNLOCK(stcb);
4637			} else {
4638				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4639				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4640				    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
4641					SCTP_INP_WLOCK(inp);
4642					/*
4643					 * FIXME MT: I think this is not in
4644					 * tune with the API ID
4645					 */
4646					if (av->assoc_value) {
4647						inp->sctp_frag_point = (av->assoc_value + ovh);
4648					} else {
4649						inp->sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
4650					}
4651					SCTP_INP_WUNLOCK(inp);
4652				} else {
4653					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4654					error = EINVAL;
4655				}
4656			}
4657			break;
4658		}
4659	case SCTP_EVENTS:
4660		{
4661			struct sctp_event_subscribe *events;
4662
4663			SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, optsize);
4664
4665			SCTP_INP_WLOCK(inp);
4666			if (events->sctp_data_io_event) {
4667				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
4668			} else {
4669				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
4670			}
4671
4672			if (events->sctp_association_event) {
4673				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
4674			} else {
4675				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
4676			}
4677
4678			if (events->sctp_address_event) {
4679				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
4680			} else {
4681				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
4682			}
4683
4684			if (events->sctp_send_failure_event) {
4685				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
4686			} else {
4687				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
4688			}
4689
4690			if (events->sctp_peer_error_event) {
4691				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPEERERR);
4692			} else {
4693				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPEERERR);
4694			}
4695
4696			if (events->sctp_shutdown_event) {
4697				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
4698			} else {
4699				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
4700			}
4701
4702			if (events->sctp_partial_delivery_event) {
4703				sctp_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
4704			} else {
4705				sctp_feature_off(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
4706			}
4707
4708			if (events->sctp_adaptation_layer_event) {
4709				sctp_feature_on(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
4710			} else {
4711				sctp_feature_off(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
4712			}
4713
4714			if (events->sctp_authentication_event) {
4715				sctp_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT);
4716			} else {
4717				sctp_feature_off(inp, SCTP_PCB_FLAGS_AUTHEVNT);
4718			}
4719
4720			if (events->sctp_sender_dry_event) {
4721				sctp_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT);
4722			} else {
4723				sctp_feature_off(inp, SCTP_PCB_FLAGS_DRYEVNT);
4724			}
4725
4726			if (events->sctp_stream_reset_event) {
4727				sctp_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
4728			} else {
4729				sctp_feature_off(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
4730			}
4731			SCTP_INP_WUNLOCK(inp);
4732
4733			SCTP_INP_RLOCK(inp);
4734			LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4735				SCTP_TCB_LOCK(stcb);
4736				if (events->sctp_association_event) {
4737					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
4738				} else {
4739					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
4740				}
4741				if (events->sctp_address_event) {
4742					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
4743				} else {
4744					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
4745				}
4746				if (events->sctp_send_failure_event) {
4747					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
4748				} else {
4749					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
4750				}
4751				if (events->sctp_peer_error_event) {
4752					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
4753				} else {
4754					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
4755				}
4756				if (events->sctp_shutdown_event) {
4757					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
4758				} else {
4759					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
4760				}
4761				if (events->sctp_partial_delivery_event) {
4762					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
4763				} else {
4764					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
4765				}
4766				if (events->sctp_adaptation_layer_event) {
4767					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
4768				} else {
4769					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
4770				}
4771				if (events->sctp_authentication_event) {
4772					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
4773				} else {
4774					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
4775				}
4776				if (events->sctp_sender_dry_event) {
4777					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
4778				} else {
4779					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
4780				}
4781				if (events->sctp_stream_reset_event) {
4782					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
4783				} else {
4784					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
4785				}
4786				SCTP_TCB_UNLOCK(stcb);
4787			}
4788			/*
4789			 * Send up the sender dry event only for 1-to-1
4790			 * style sockets.
4791			 */
4792			if (events->sctp_sender_dry_event) {
4793				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4794				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
4795					stcb = LIST_FIRST(&inp->sctp_asoc_list);
4796					if (stcb) {
4797						SCTP_TCB_LOCK(stcb);
4798						if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
4799						    TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
4800						    (stcb->asoc.stream_queue_cnt == 0)) {
4801							sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_LOCKED);
4802						}
4803						SCTP_TCB_UNLOCK(stcb);
4804					}
4805				}
4806			}
4807			SCTP_INP_RUNLOCK(inp);
4808			break;
4809		}
4810	case SCTP_ADAPTATION_LAYER:
4811		{
4812			struct sctp_setadaptation *adap_bits;
4813
4814			SCTP_CHECK_AND_CAST(adap_bits, optval, struct sctp_setadaptation, optsize);
4815			SCTP_INP_WLOCK(inp);
4816			inp->sctp_ep.adaptation_layer_indicator = adap_bits->ssb_adaptation_ind;
4817			inp->sctp_ep.adaptation_layer_indicator_provided = 1;
4818			SCTP_INP_WUNLOCK(inp);
4819			break;
4820		}
4821#ifdef SCTP_DEBUG
4822	case SCTP_SET_INITIAL_DBG_SEQ:
4823		{
4824			uint32_t *vvv;
4825
4826			SCTP_CHECK_AND_CAST(vvv, optval, uint32_t, optsize);
4827			SCTP_INP_WLOCK(inp);
4828			inp->sctp_ep.initial_sequence_debug = *vvv;
4829			SCTP_INP_WUNLOCK(inp);
4830			break;
4831		}
4832#endif
4833	case SCTP_DEFAULT_SEND_PARAM:
4834		{
4835			struct sctp_sndrcvinfo *s_info;
4836
4837			SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, optsize);
4838			SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
4839
4840			if (stcb) {
4841				if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
4842					memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
4843				} else {
4844					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4845					error = EINVAL;
4846				}
4847				SCTP_TCB_UNLOCK(stcb);
4848			} else {
4849				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4850				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4851				    (s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC) ||
4852				    (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)) {
4853					SCTP_INP_WLOCK(inp);
4854					memcpy(&inp->def_send, s_info, min(optsize, sizeof(inp->def_send)));
4855					SCTP_INP_WUNLOCK(inp);
4856				}
4857				if ((s_info->sinfo_assoc_id == SCTP_CURRENT_ASSOC) ||
4858				    (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)) {
4859					SCTP_INP_RLOCK(inp);
4860					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4861						SCTP_TCB_LOCK(stcb);
4862						if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
4863							memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
4864						}
4865						SCTP_TCB_UNLOCK(stcb);
4866					}
4867					SCTP_INP_RUNLOCK(inp);
4868				}
4869			}
4870			break;
4871		}
4872	case SCTP_PEER_ADDR_PARAMS:
4873		{
4874			struct sctp_paddrparams *paddrp;
4875			struct sctp_nets *net;
4876
4877			SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, optsize);
4878			SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
4879			net = NULL;
4880			if (stcb) {
4881				net = sctp_findnet(stcb, (struct sockaddr *)&paddrp->spp_address);
4882			} else {
4883				/*
4884				 * We increment here since
4885				 * sctp_findassociation_ep_addr() wil do a
4886				 * decrement if it finds the stcb as long as
4887				 * the locked tcb (last argument) is NOT a
4888				 * TCB.. aka NULL.
4889				 */
4890				SCTP_INP_INCR_REF(inp);
4891				stcb = sctp_findassociation_ep_addr(&inp,
4892				    (struct sockaddr *)&paddrp->spp_address,
4893				    &net, NULL, NULL);
4894				if (stcb == NULL) {
4895					SCTP_INP_DECR_REF(inp);
4896				}
4897			}
4898			if (stcb && (net == NULL)) {
4899				struct sockaddr *sa;
4900
4901				sa = (struct sockaddr *)&paddrp->spp_address;
4902#ifdef INET
4903				if (sa->sa_family == AF_INET) {
4904
4905					struct sockaddr_in *sin;
4906
4907					sin = (struct sockaddr_in *)sa;
4908					if (sin->sin_addr.s_addr) {
4909						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4910						SCTP_TCB_UNLOCK(stcb);
4911						error = EINVAL;
4912						break;
4913					}
4914				} else
4915#endif
4916#ifdef INET6
4917				if (sa->sa_family == AF_INET6) {
4918					struct sockaddr_in6 *sin6;
4919
4920					sin6 = (struct sockaddr_in6 *)sa;
4921					if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
4922						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4923						SCTP_TCB_UNLOCK(stcb);
4924						error = EINVAL;
4925						break;
4926					}
4927				} else
4928#endif
4929				{
4930					error = EAFNOSUPPORT;
4931					SCTP_TCB_UNLOCK(stcb);
4932					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
4933					break;
4934				}
4935			}
4936			/* sanity checks */
4937			if ((paddrp->spp_flags & SPP_HB_ENABLE) && (paddrp->spp_flags & SPP_HB_DISABLE)) {
4938				if (stcb)
4939					SCTP_TCB_UNLOCK(stcb);
4940				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4941				return (EINVAL);
4942			}
4943			if ((paddrp->spp_flags & SPP_PMTUD_ENABLE) && (paddrp->spp_flags & SPP_PMTUD_DISABLE)) {
4944				if (stcb)
4945					SCTP_TCB_UNLOCK(stcb);
4946				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4947				return (EINVAL);
4948			}
4949			if (stcb) {
4950				/************************TCB SPECIFIC SET ******************/
4951				/*
4952				 * do we change the timer for HB, we run
4953				 * only one?
4954				 */
4955				int ovh = 0;
4956
4957				if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
4958					ovh = SCTP_MED_OVERHEAD;
4959				} else {
4960					ovh = SCTP_MED_V4_OVERHEAD;
4961				}
4962
4963				/* network sets ? */
4964				if (net) {
4965					/************************NET SPECIFIC SET ******************/
4966					if (paddrp->spp_flags & SPP_HB_DISABLE) {
4967						if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
4968						    !(net->dest_state & SCTP_ADDR_NOHB)) {
4969							sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
4970							    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
4971						}
4972						net->dest_state |= SCTP_ADDR_NOHB;
4973					}
4974					if (paddrp->spp_flags & SPP_HB_ENABLE) {
4975						if (paddrp->spp_hbinterval) {
4976							net->heart_beat_delay = paddrp->spp_hbinterval;
4977						} else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
4978							net->heart_beat_delay = 0;
4979						}
4980						sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
4981						    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
4982						sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
4983						net->dest_state &= ~SCTP_ADDR_NOHB;
4984					}
4985					if (paddrp->spp_flags & SPP_HB_DEMAND) {
4986						/* on demand HB */
4987						sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
4988						sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED);
4989						sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
4990					}
4991					if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
4992						if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
4993							sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
4994							    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
4995						}
4996						net->dest_state |= SCTP_ADDR_NO_PMTUD;
4997						net->mtu = paddrp->spp_pathmtu + ovh;
4998						if (net->mtu < stcb->asoc.smallest_mtu) {
4999							sctp_pathmtu_adjustment(stcb, net->mtu);
5000						}
5001					}
5002					if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
5003						if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
5004							sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
5005						}
5006						net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
5007					}
5008					if (paddrp->spp_pathmaxrxt) {
5009						if (net->dest_state & SCTP_ADDR_PF) {
5010							if (net->error_count > paddrp->spp_pathmaxrxt) {
5011								net->dest_state &= ~SCTP_ADDR_PF;
5012							}
5013						} else {
5014							if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
5015							    (net->error_count > net->pf_threshold)) {
5016								net->dest_state |= SCTP_ADDR_PF;
5017								sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5018								sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
5019								sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
5020							}
5021						}
5022						if (net->dest_state & SCTP_ADDR_REACHABLE) {
5023							if (net->error_count > paddrp->spp_pathmaxrxt) {
5024								net->dest_state &= ~SCTP_ADDR_REACHABLE;
5025								sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
5026							}
5027						} else {
5028							if (net->error_count <= paddrp->spp_pathmaxrxt) {
5029								net->dest_state |= SCTP_ADDR_REACHABLE;
5030								sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
5031							}
5032						}
5033						net->failure_threshold = paddrp->spp_pathmaxrxt;
5034					}
5035					if (paddrp->spp_flags & SPP_DSCP) {
5036						net->dscp = paddrp->spp_dscp & 0xfc;
5037						net->dscp |= 0x01;
5038					}
5039#ifdef INET6
5040					if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
5041						if (net->ro._l_addr.sa.sa_family == AF_INET6) {
5042							net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5043							net->flowlabel |= 0x80000000;
5044						}
5045					}
5046#endif
5047				} else {
5048					/************************ASSOC ONLY -- NO NET SPECIFIC SET ******************/
5049					if (paddrp->spp_pathmaxrxt) {
5050						stcb->asoc.def_net_failure = paddrp->spp_pathmaxrxt;
5051						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5052							if (net->dest_state & SCTP_ADDR_PF) {
5053								if (net->error_count > paddrp->spp_pathmaxrxt) {
5054									net->dest_state &= ~SCTP_ADDR_PF;
5055								}
5056							} else {
5057								if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
5058								    (net->error_count > net->pf_threshold)) {
5059									net->dest_state |= SCTP_ADDR_PF;
5060									sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5061									sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
5062									sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
5063								}
5064							}
5065							if (net->dest_state & SCTP_ADDR_REACHABLE) {
5066								if (net->error_count > paddrp->spp_pathmaxrxt) {
5067									net->dest_state &= ~SCTP_ADDR_REACHABLE;
5068									sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
5069								}
5070							} else {
5071								if (net->error_count <= paddrp->spp_pathmaxrxt) {
5072									net->dest_state |= SCTP_ADDR_REACHABLE;
5073									sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
5074								}
5075							}
5076							net->failure_threshold = paddrp->spp_pathmaxrxt;
5077						}
5078					}
5079					if (paddrp->spp_flags & SPP_HB_ENABLE) {
5080						if (paddrp->spp_hbinterval) {
5081							stcb->asoc.heart_beat_delay = paddrp->spp_hbinterval;
5082						} else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
5083							stcb->asoc.heart_beat_delay = 0;
5084						}
5085						/* Turn back on the timer */
5086						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5087							if (paddrp->spp_hbinterval) {
5088								net->heart_beat_delay = paddrp->spp_hbinterval;
5089							} else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
5090								net->heart_beat_delay = 0;
5091							}
5092							if (net->dest_state & SCTP_ADDR_NOHB) {
5093								net->dest_state &= ~SCTP_ADDR_NOHB;
5094							}
5095							sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
5096							    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
5097							sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
5098						}
5099						sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5100					}
5101					if (paddrp->spp_flags & SPP_HB_DISABLE) {
5102						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5103							if (!(net->dest_state & SCTP_ADDR_NOHB)) {
5104								net->dest_state |= SCTP_ADDR_NOHB;
5105								if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED)) {
5106									sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
5107								}
5108							}
5109						}
5110						sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5111					}
5112					if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
5113						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5114							if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
5115								sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
5116								    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
5117							}
5118							net->dest_state |= SCTP_ADDR_NO_PMTUD;
5119							net->mtu = paddrp->spp_pathmtu + ovh;
5120							if (net->mtu < stcb->asoc.smallest_mtu) {
5121								sctp_pathmtu_adjustment(stcb, net->mtu);
5122							}
5123						}
5124						sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5125					}
5126					if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
5127						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5128							if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
5129								sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
5130							}
5131							net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
5132						}
5133						sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5134					}
5135					if (paddrp->spp_flags & SPP_DSCP) {
5136						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5137							net->dscp = paddrp->spp_dscp & 0xfc;
5138							net->dscp |= 0x01;
5139						}
5140						stcb->asoc.default_dscp = paddrp->spp_dscp & 0xfc;
5141						stcb->asoc.default_dscp |= 0x01;
5142					}
5143#ifdef INET6
5144					if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
5145						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5146							if (net->ro._l_addr.sa.sa_family == AF_INET6) {
5147								net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5148								net->flowlabel |= 0x80000000;
5149							}
5150						}
5151						stcb->asoc.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5152						stcb->asoc.default_flowlabel |= 0x80000000;
5153					}
5154#endif
5155				}
5156				SCTP_TCB_UNLOCK(stcb);
5157			} else {
5158				/************************NO TCB, SET TO default stuff ******************/
5159				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5160				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5161				    (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC)) {
5162					SCTP_INP_WLOCK(inp);
5163					/*
5164					 * For the TOS/FLOWLABEL stuff you
5165					 * set it with the options on the
5166					 * socket
5167					 */
5168					if (paddrp->spp_pathmaxrxt) {
5169						inp->sctp_ep.def_net_failure = paddrp->spp_pathmaxrxt;
5170					}
5171					if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO)
5172						inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
5173					else if (paddrp->spp_hbinterval) {
5174						if (paddrp->spp_hbinterval > SCTP_MAX_HB_INTERVAL)
5175							paddrp->spp_hbinterval = SCTP_MAX_HB_INTERVAL;
5176						inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
5177					}
5178					if (paddrp->spp_flags & SPP_HB_ENABLE) {
5179						if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
5180							inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
5181						} else if (paddrp->spp_hbinterval) {
5182							inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
5183						}
5184						sctp_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5185					} else if (paddrp->spp_flags & SPP_HB_DISABLE) {
5186						sctp_feature_on(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5187					}
5188					if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
5189						sctp_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5190					} else if (paddrp->spp_flags & SPP_PMTUD_DISABLE) {
5191						sctp_feature_on(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5192					}
5193					if (paddrp->spp_flags & SPP_DSCP) {
5194						inp->sctp_ep.default_dscp = paddrp->spp_dscp & 0xfc;
5195						inp->sctp_ep.default_dscp |= 0x01;
5196					}
5197#ifdef INET6
5198					if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
5199						if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
5200							inp->sctp_ep.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5201							inp->sctp_ep.default_flowlabel |= 0x80000000;
5202						}
5203					}
5204#endif
5205					SCTP_INP_WUNLOCK(inp);
5206				} else {
5207					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5208					error = EINVAL;
5209				}
5210			}
5211			break;
5212		}
5213	case SCTP_RTOINFO:
5214		{
5215			struct sctp_rtoinfo *srto;
5216			uint32_t new_init, new_min, new_max;
5217
5218			SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, optsize);
5219			SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
5220
5221			if (stcb) {
5222				if (srto->srto_initial)
5223					new_init = srto->srto_initial;
5224				else
5225					new_init = stcb->asoc.initial_rto;
5226				if (srto->srto_max)
5227					new_max = srto->srto_max;
5228				else
5229					new_max = stcb->asoc.maxrto;
5230				if (srto->srto_min)
5231					new_min = srto->srto_min;
5232				else
5233					new_min = stcb->asoc.minrto;
5234				if ((new_min <= new_init) && (new_init <= new_max)) {
5235					stcb->asoc.initial_rto = new_init;
5236					stcb->asoc.maxrto = new_max;
5237					stcb->asoc.minrto = new_min;
5238				} else {
5239					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5240					error = EINVAL;
5241				}
5242				SCTP_TCB_UNLOCK(stcb);
5243			} else {
5244				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5245				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5246				    (srto->srto_assoc_id == SCTP_FUTURE_ASSOC)) {
5247					SCTP_INP_WLOCK(inp);
5248					if (srto->srto_initial)
5249						new_init = srto->srto_initial;
5250					else
5251						new_init = inp->sctp_ep.initial_rto;
5252					if (srto->srto_max)
5253						new_max = srto->srto_max;
5254					else
5255						new_max = inp->sctp_ep.sctp_maxrto;
5256					if (srto->srto_min)
5257						new_min = srto->srto_min;
5258					else
5259						new_min = inp->sctp_ep.sctp_minrto;
5260					if ((new_min <= new_init) && (new_init <= new_max)) {
5261						inp->sctp_ep.initial_rto = new_init;
5262						inp->sctp_ep.sctp_maxrto = new_max;
5263						inp->sctp_ep.sctp_minrto = new_min;
5264					} else {
5265						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5266						error = EINVAL;
5267					}
5268					SCTP_INP_WUNLOCK(inp);
5269				} else {
5270					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5271					error = EINVAL;
5272				}
5273			}
5274			break;
5275		}
5276	case SCTP_ASSOCINFO:
5277		{
5278			struct sctp_assocparams *sasoc;
5279
5280			SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, optsize);
5281			SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
5282			if (sasoc->sasoc_cookie_life) {
5283				/* boundary check the cookie life */
5284				if (sasoc->sasoc_cookie_life < 1000)
5285					sasoc->sasoc_cookie_life = 1000;
5286				if (sasoc->sasoc_cookie_life > SCTP_MAX_COOKIE_LIFE) {
5287					sasoc->sasoc_cookie_life = SCTP_MAX_COOKIE_LIFE;
5288				}
5289			}
5290			if (stcb) {
5291				if (sasoc->sasoc_asocmaxrxt)
5292					stcb->asoc.max_send_times = sasoc->sasoc_asocmaxrxt;
5293				if (sasoc->sasoc_cookie_life) {
5294					stcb->asoc.cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
5295				}
5296				SCTP_TCB_UNLOCK(stcb);
5297			} else {
5298				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5299				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5300				    (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC)) {
5301					SCTP_INP_WLOCK(inp);
5302					if (sasoc->sasoc_asocmaxrxt)
5303						inp->sctp_ep.max_send_times = sasoc->sasoc_asocmaxrxt;
5304					if (sasoc->sasoc_cookie_life) {
5305						inp->sctp_ep.def_cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
5306					}
5307					SCTP_INP_WUNLOCK(inp);
5308				} else {
5309					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5310					error = EINVAL;
5311				}
5312			}
5313			break;
5314		}
5315	case SCTP_INITMSG:
5316		{
5317			struct sctp_initmsg *sinit;
5318
5319			SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, optsize);
5320			SCTP_INP_WLOCK(inp);
5321			if (sinit->sinit_num_ostreams)
5322				inp->sctp_ep.pre_open_stream_count = sinit->sinit_num_ostreams;
5323
5324			if (sinit->sinit_max_instreams)
5325				inp->sctp_ep.max_open_streams_intome = sinit->sinit_max_instreams;
5326
5327			if (sinit->sinit_max_attempts)
5328				inp->sctp_ep.max_init_times = sinit->sinit_max_attempts;
5329
5330			if (sinit->sinit_max_init_timeo)
5331				inp->sctp_ep.initial_init_rto_max = sinit->sinit_max_init_timeo;
5332			SCTP_INP_WUNLOCK(inp);
5333			break;
5334		}
5335	case SCTP_PRIMARY_ADDR:
5336		{
5337			struct sctp_setprim *spa;
5338			struct sctp_nets *net;
5339
5340			SCTP_CHECK_AND_CAST(spa, optval, struct sctp_setprim, optsize);
5341			SCTP_FIND_STCB(inp, stcb, spa->ssp_assoc_id);
5342
5343			net = NULL;
5344			if (stcb) {
5345				net = sctp_findnet(stcb, (struct sockaddr *)&spa->ssp_addr);
5346			} else {
5347				/*
5348				 * We increment here since
5349				 * sctp_findassociation_ep_addr() wil do a
5350				 * decrement if it finds the stcb as long as
5351				 * the locked tcb (last argument) is NOT a
5352				 * TCB.. aka NULL.
5353				 */
5354				SCTP_INP_INCR_REF(inp);
5355				stcb = sctp_findassociation_ep_addr(&inp,
5356				    (struct sockaddr *)&spa->ssp_addr,
5357				    &net, NULL, NULL);
5358				if (stcb == NULL) {
5359					SCTP_INP_DECR_REF(inp);
5360				}
5361			}
5362
5363			if ((stcb) && (net)) {
5364				if ((net != stcb->asoc.primary_destination) &&
5365				    (!(net->dest_state & SCTP_ADDR_UNCONFIRMED))) {
5366					/* Ok we need to set it */
5367					if (sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net) == 0) {
5368						if ((stcb->asoc.alternate) &&
5369						    (!(net->dest_state & SCTP_ADDR_PF)) &&
5370						    (net->dest_state & SCTP_ADDR_REACHABLE)) {
5371							sctp_free_remote_addr(stcb->asoc.alternate);
5372							stcb->asoc.alternate = NULL;
5373						}
5374					}
5375				}
5376			} else {
5377				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5378				error = EINVAL;
5379			}
5380			if (stcb) {
5381				SCTP_TCB_UNLOCK(stcb);
5382			}
5383			break;
5384		}
5385	case SCTP_SET_DYNAMIC_PRIMARY:
5386		{
5387			union sctp_sockstore *ss;
5388
5389			error = priv_check(curthread,
5390			    PRIV_NETINET_RESERVEDPORT);
5391			if (error)
5392				break;
5393
5394			SCTP_CHECK_AND_CAST(ss, optval, union sctp_sockstore, optsize);
5395			/* SUPER USER CHECK? */
5396			error = sctp_dynamic_set_primary(&ss->sa, vrf_id);
5397			break;
5398		}
5399	case SCTP_SET_PEER_PRIMARY_ADDR:
5400		{
5401			struct sctp_setpeerprim *sspp;
5402
5403			SCTP_CHECK_AND_CAST(sspp, optval, struct sctp_setpeerprim, optsize);
5404			SCTP_FIND_STCB(inp, stcb, sspp->sspp_assoc_id);
5405			if (stcb != NULL) {
5406				struct sctp_ifa *ifa;
5407
5408				ifa = sctp_find_ifa_by_addr((struct sockaddr *)&sspp->sspp_addr,
5409				    stcb->asoc.vrf_id, SCTP_ADDR_NOT_LOCKED);
5410				if (ifa == NULL) {
5411					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5412					error = EINVAL;
5413					goto out_of_it;
5414				}
5415				if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
5416					/*
5417					 * Must validate the ifa found is in
5418					 * our ep
5419					 */
5420					struct sctp_laddr *laddr;
5421					int found = 0;
5422
5423					LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
5424						if (laddr->ifa == NULL) {
5425							SCTPDBG(SCTP_DEBUG_OUTPUT1, "%s: NULL ifa\n",
5426							    __FUNCTION__);
5427							continue;
5428						}
5429						if (laddr->ifa == ifa) {
5430							found = 1;
5431							break;
5432						}
5433					}
5434					if (!found) {
5435						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5436						error = EINVAL;
5437						goto out_of_it;
5438					}
5439				} else {
5440					switch (sspp->sspp_addr.ss_family) {
5441#ifdef INET
5442					case AF_INET:
5443						{
5444							struct sockaddr_in *sin;
5445
5446							sin = (struct sockaddr_in *)&sspp->sspp_addr;
5447							if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
5448							    &sin->sin_addr) != 0) {
5449								SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5450								error = EINVAL;
5451								goto out_of_it;
5452							}
5453							break;
5454						}
5455#endif
5456#ifdef INET6
5457					case AF_INET6:
5458						{
5459							struct sockaddr_in6 *sin6;
5460
5461							sin6 = (struct sockaddr_in6 *)&sspp->sspp_addr;
5462							if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
5463							    &sin6->sin6_addr) != 0) {
5464								SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5465								error = EINVAL;
5466								goto out_of_it;
5467							}
5468							break;
5469						}
5470#endif
5471					default:
5472						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5473						error = EINVAL;
5474						goto out_of_it;
5475					}
5476				}
5477				if (sctp_set_primary_ip_address_sa(stcb,
5478				    (struct sockaddr *)&sspp->sspp_addr) != 0) {
5479					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5480					error = EINVAL;
5481				}
5482		out_of_it:
5483				SCTP_TCB_UNLOCK(stcb);
5484			} else {
5485				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5486				error = EINVAL;
5487			}
5488			break;
5489		}
5490	case SCTP_BINDX_ADD_ADDR:
5491		{
5492			struct sctp_getaddresses *addrs;
5493			struct thread *td;
5494
5495			td = (struct thread *)p;
5496			SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses,
5497			    optsize);
5498#ifdef INET
5499			if (addrs->addr->sa_family == AF_INET) {
5500				if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in)) {
5501					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5502					error = EINVAL;
5503					break;
5504				}
5505				if (td != NULL && (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)(addrs->addr))->sin_addr)))) {
5506					SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
5507					break;
5508				}
5509			} else
5510#endif
5511#ifdef INET6
5512			if (addrs->addr->sa_family == AF_INET6) {
5513				if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6)) {
5514					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5515					error = EINVAL;
5516					break;
5517				}
5518				if (td != NULL && (error = prison_local_ip6(td->td_ucred, &(((struct sockaddr_in6 *)(addrs->addr))->sin6_addr),
5519				    (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
5520					SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
5521					break;
5522				}
5523			} else
5524#endif
5525			{
5526				error = EAFNOSUPPORT;
5527				break;
5528			}
5529			sctp_bindx_add_address(so, inp, addrs->addr,
5530			    addrs->sget_assoc_id, vrf_id,
5531			    &error, p);
5532			break;
5533		}
5534	case SCTP_BINDX_REM_ADDR:
5535		{
5536			struct sctp_getaddresses *addrs;
5537			struct thread *td;
5538
5539			td = (struct thread *)p;
5540
5541			SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses, optsize);
5542#ifdef INET
5543			if (addrs->addr->sa_family == AF_INET) {
5544				if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in)) {
5545					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5546					error = EINVAL;
5547					break;
5548				}
5549				if (td != NULL && (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)(addrs->addr))->sin_addr)))) {
5550					SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
5551					break;
5552				}
5553			} else
5554#endif
5555#ifdef INET6
5556			if (addrs->addr->sa_family == AF_INET6) {
5557				if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6)) {
5558					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5559					error = EINVAL;
5560					break;
5561				}
5562				if (td != NULL &&
5563				    (error = prison_local_ip6(td->td_ucred,
5564				    &(((struct sockaddr_in6 *)(addrs->addr))->sin6_addr),
5565				    (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
5566					SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
5567					break;
5568				}
5569			} else
5570#endif
5571			{
5572				error = EAFNOSUPPORT;
5573				break;
5574			}
5575			sctp_bindx_delete_address(inp, addrs->addr,
5576			    addrs->sget_assoc_id, vrf_id,
5577			    &error);
5578			break;
5579		}
5580	case SCTP_EVENT:
5581		{
5582			struct sctp_event *event;
5583			uint32_t event_type;
5584
5585			SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, optsize);
5586			SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
5587			switch (event->se_type) {
5588			case SCTP_ASSOC_CHANGE:
5589				event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
5590				break;
5591			case SCTP_PEER_ADDR_CHANGE:
5592				event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
5593				break;
5594			case SCTP_REMOTE_ERROR:
5595				event_type = SCTP_PCB_FLAGS_RECVPEERERR;
5596				break;
5597			case SCTP_SEND_FAILED:
5598				event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
5599				break;
5600			case SCTP_SHUTDOWN_EVENT:
5601				event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
5602				break;
5603			case SCTP_ADAPTATION_INDICATION:
5604				event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
5605				break;
5606			case SCTP_PARTIAL_DELIVERY_EVENT:
5607				event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
5608				break;
5609			case SCTP_AUTHENTICATION_EVENT:
5610				event_type = SCTP_PCB_FLAGS_AUTHEVNT;
5611				break;
5612			case SCTP_STREAM_RESET_EVENT:
5613				event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
5614				break;
5615			case SCTP_SENDER_DRY_EVENT:
5616				event_type = SCTP_PCB_FLAGS_DRYEVNT;
5617				break;
5618			case SCTP_NOTIFICATIONS_STOPPED_EVENT:
5619				event_type = 0;
5620				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
5621				error = ENOTSUP;
5622				break;
5623			case SCTP_ASSOC_RESET_EVENT:
5624				event_type = SCTP_PCB_FLAGS_ASSOC_RESETEVNT;
5625				break;
5626			case SCTP_STREAM_CHANGE_EVENT:
5627				event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT;
5628				break;
5629			case SCTP_SEND_FAILED_EVENT:
5630				event_type = SCTP_PCB_FLAGS_RECVNSENDFAILEVNT;
5631				break;
5632			default:
5633				event_type = 0;
5634				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5635				error = EINVAL;
5636				break;
5637			}
5638			if (event_type > 0) {
5639				if (stcb) {
5640					if (event->se_on) {
5641						sctp_stcb_feature_on(inp, stcb, event_type);
5642						if (event_type == SCTP_PCB_FLAGS_DRYEVNT) {
5643							if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
5644							    TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
5645							    (stcb->asoc.stream_queue_cnt == 0)) {
5646								sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_LOCKED);
5647							}
5648						}
5649					} else {
5650						sctp_stcb_feature_off(inp, stcb, event_type);
5651					}
5652					SCTP_TCB_UNLOCK(stcb);
5653				} else {
5654					/*
5655					 * We don't want to send up a storm
5656					 * of events, so return an error for
5657					 * sender dry events
5658					 */
5659					if ((event_type == SCTP_PCB_FLAGS_DRYEVNT) &&
5660					    ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) == 0) &&
5661					    ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
5662					    ((event->se_assoc_id == SCTP_ALL_ASSOC) ||
5663					    (event->se_assoc_id == SCTP_CURRENT_ASSOC))) {
5664						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
5665						error = ENOTSUP;
5666						break;
5667					}
5668					if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5669					    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5670					    (event->se_assoc_id == SCTP_FUTURE_ASSOC) ||
5671					    (event->se_assoc_id == SCTP_ALL_ASSOC)) {
5672						SCTP_INP_WLOCK(inp);
5673						if (event->se_on) {
5674							sctp_feature_on(inp, event_type);
5675						} else {
5676							sctp_feature_off(inp, event_type);
5677						}
5678						SCTP_INP_WUNLOCK(inp);
5679					}
5680					if ((event->se_assoc_id == SCTP_CURRENT_ASSOC) ||
5681					    (event->se_assoc_id == SCTP_ALL_ASSOC)) {
5682						SCTP_INP_RLOCK(inp);
5683						LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5684							SCTP_TCB_LOCK(stcb);
5685							if (event->se_on) {
5686								sctp_stcb_feature_on(inp, stcb, event_type);
5687							} else {
5688								sctp_stcb_feature_off(inp, stcb, event_type);
5689							}
5690							SCTP_TCB_UNLOCK(stcb);
5691						}
5692						SCTP_INP_RUNLOCK(inp);
5693					}
5694				}
5695			}
5696			break;
5697		}
5698	case SCTP_RECVRCVINFO:
5699		{
5700			int *onoff;
5701
5702			SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
5703			SCTP_INP_WLOCK(inp);
5704			if (*onoff != 0) {
5705				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
5706			} else {
5707				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
5708			}
5709			SCTP_INP_WUNLOCK(inp);
5710			break;
5711		}
5712	case SCTP_RECVNXTINFO:
5713		{
5714			int *onoff;
5715
5716			SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
5717			SCTP_INP_WLOCK(inp);
5718			if (*onoff != 0) {
5719				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
5720			} else {
5721				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
5722			}
5723			SCTP_INP_WUNLOCK(inp);
5724			break;
5725		}
5726	case SCTP_DEFAULT_SNDINFO:
5727		{
5728			struct sctp_sndinfo *info;
5729			uint16_t policy;
5730
5731			SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, optsize);
5732			SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
5733
5734			if (stcb) {
5735				if (info->snd_sid < stcb->asoc.streamoutcnt) {
5736					stcb->asoc.def_send.sinfo_stream = info->snd_sid;
5737					policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
5738					stcb->asoc.def_send.sinfo_flags = info->snd_flags;
5739					stcb->asoc.def_send.sinfo_flags |= policy;
5740					stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
5741					stcb->asoc.def_send.sinfo_context = info->snd_context;
5742				} else {
5743					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5744					error = EINVAL;
5745				}
5746				SCTP_TCB_UNLOCK(stcb);
5747			} else {
5748				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5749				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5750				    (info->snd_assoc_id == SCTP_FUTURE_ASSOC) ||
5751				    (info->snd_assoc_id == SCTP_ALL_ASSOC)) {
5752					SCTP_INP_WLOCK(inp);
5753					inp->def_send.sinfo_stream = info->snd_sid;
5754					policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
5755					inp->def_send.sinfo_flags = info->snd_flags;
5756					inp->def_send.sinfo_flags |= policy;
5757					inp->def_send.sinfo_ppid = info->snd_ppid;
5758					inp->def_send.sinfo_context = info->snd_context;
5759					SCTP_INP_WUNLOCK(inp);
5760				}
5761				if ((info->snd_assoc_id == SCTP_CURRENT_ASSOC) ||
5762				    (info->snd_assoc_id == SCTP_ALL_ASSOC)) {
5763					SCTP_INP_RLOCK(inp);
5764					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5765						SCTP_TCB_LOCK(stcb);
5766						if (info->snd_sid < stcb->asoc.streamoutcnt) {
5767							stcb->asoc.def_send.sinfo_stream = info->snd_sid;
5768							policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
5769							stcb->asoc.def_send.sinfo_flags = info->snd_flags;
5770							stcb->asoc.def_send.sinfo_flags |= policy;
5771							stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
5772							stcb->asoc.def_send.sinfo_context = info->snd_context;
5773						}
5774						SCTP_TCB_UNLOCK(stcb);
5775					}
5776					SCTP_INP_RUNLOCK(inp);
5777				}
5778			}
5779			break;
5780		}
5781	case SCTP_DEFAULT_PRINFO:
5782		{
5783			struct sctp_default_prinfo *info;
5784
5785			SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, optsize);
5786			SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
5787
5788			if (PR_SCTP_INVALID_POLICY(info->pr_policy)) {
5789				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5790				error = EINVAL;
5791				break;
5792			}
5793			if (stcb) {
5794				stcb->asoc.def_send.sinfo_flags &= 0xfff0;
5795				stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
5796				stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
5797				SCTP_TCB_UNLOCK(stcb);
5798			} else {
5799				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5800				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5801				    (info->pr_assoc_id == SCTP_FUTURE_ASSOC) ||
5802				    (info->pr_assoc_id == SCTP_ALL_ASSOC)) {
5803					SCTP_INP_WLOCK(inp);
5804					inp->def_send.sinfo_flags &= 0xfff0;
5805					inp->def_send.sinfo_flags |= info->pr_policy;
5806					inp->def_send.sinfo_timetolive = info->pr_value;
5807					SCTP_INP_WUNLOCK(inp);
5808				}
5809				if ((info->pr_assoc_id == SCTP_CURRENT_ASSOC) ||
5810				    (info->pr_assoc_id == SCTP_ALL_ASSOC)) {
5811					SCTP_INP_RLOCK(inp);
5812					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5813						SCTP_TCB_LOCK(stcb);
5814						stcb->asoc.def_send.sinfo_flags &= 0xfff0;
5815						stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
5816						stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
5817						SCTP_TCB_UNLOCK(stcb);
5818					}
5819					SCTP_INP_RUNLOCK(inp);
5820				}
5821			}
5822			break;
5823		}
5824	case SCTP_PEER_ADDR_THLDS:
5825		/* Applies to the specific association */
5826		{
5827			struct sctp_paddrthlds *thlds;
5828			struct sctp_nets *net;
5829
5830			SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, optsize);
5831			SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
5832			net = NULL;
5833			if (stcb) {
5834				net = sctp_findnet(stcb, (struct sockaddr *)&thlds->spt_address);
5835			} else {
5836				/*
5837				 * We increment here since
5838				 * sctp_findassociation_ep_addr() wil do a
5839				 * decrement if it finds the stcb as long as
5840				 * the locked tcb (last argument) is NOT a
5841				 * TCB.. aka NULL.
5842				 */
5843				SCTP_INP_INCR_REF(inp);
5844				stcb = sctp_findassociation_ep_addr(&inp,
5845				    (struct sockaddr *)&thlds->spt_address,
5846				    &net, NULL, NULL);
5847				if (stcb == NULL) {
5848					SCTP_INP_DECR_REF(inp);
5849				}
5850			}
5851			if (stcb && (net == NULL)) {
5852				struct sockaddr *sa;
5853
5854				sa = (struct sockaddr *)&thlds->spt_address;
5855#ifdef INET
5856				if (sa->sa_family == AF_INET) {
5857
5858					struct sockaddr_in *sin;
5859
5860					sin = (struct sockaddr_in *)sa;
5861					if (sin->sin_addr.s_addr) {
5862						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5863						SCTP_TCB_UNLOCK(stcb);
5864						error = EINVAL;
5865						break;
5866					}
5867				} else
5868#endif
5869#ifdef INET6
5870				if (sa->sa_family == AF_INET6) {
5871					struct sockaddr_in6 *sin6;
5872
5873					sin6 = (struct sockaddr_in6 *)sa;
5874					if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
5875						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5876						SCTP_TCB_UNLOCK(stcb);
5877						error = EINVAL;
5878						break;
5879					}
5880				} else
5881#endif
5882				{
5883					error = EAFNOSUPPORT;
5884					SCTP_TCB_UNLOCK(stcb);
5885					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
5886					break;
5887				}
5888			}
5889			if (stcb) {
5890				if (net) {
5891					if (net->dest_state & SCTP_ADDR_PF) {
5892						if ((net->failure_threshold > thlds->spt_pathmaxrxt) ||
5893						    (net->failure_threshold <= thlds->spt_pathpfthld)) {
5894							net->dest_state &= ~SCTP_ADDR_PF;
5895						}
5896					} else {
5897						if ((net->failure_threshold > thlds->spt_pathpfthld) &&
5898						    (net->failure_threshold <= thlds->spt_pathmaxrxt)) {
5899							net->dest_state |= SCTP_ADDR_PF;
5900							sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5901							sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
5902							sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
5903						}
5904					}
5905					if (net->dest_state & SCTP_ADDR_REACHABLE) {
5906						if (net->failure_threshold > thlds->spt_pathmaxrxt) {
5907							net->dest_state &= ~SCTP_ADDR_REACHABLE;
5908							sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
5909						}
5910					} else {
5911						if (net->failure_threshold <= thlds->spt_pathmaxrxt) {
5912							net->dest_state |= SCTP_ADDR_REACHABLE;
5913							sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
5914						}
5915					}
5916					net->failure_threshold = thlds->spt_pathmaxrxt;
5917					net->pf_threshold = thlds->spt_pathpfthld;
5918				} else {
5919					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5920						if (net->dest_state & SCTP_ADDR_PF) {
5921							if ((net->failure_threshold > thlds->spt_pathmaxrxt) ||
5922							    (net->failure_threshold <= thlds->spt_pathpfthld)) {
5923								net->dest_state &= ~SCTP_ADDR_PF;
5924							}
5925						} else {
5926							if ((net->failure_threshold > thlds->spt_pathpfthld) &&
5927							    (net->failure_threshold <= thlds->spt_pathmaxrxt)) {
5928								net->dest_state |= SCTP_ADDR_PF;
5929								sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5930								sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
5931								sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
5932							}
5933						}
5934						if (net->dest_state & SCTP_ADDR_REACHABLE) {
5935							if (net->failure_threshold > thlds->spt_pathmaxrxt) {
5936								net->dest_state &= ~SCTP_ADDR_REACHABLE;
5937								sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
5938							}
5939						} else {
5940							if (net->failure_threshold <= thlds->spt_pathmaxrxt) {
5941								net->dest_state |= SCTP_ADDR_REACHABLE;
5942								sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
5943							}
5944						}
5945						net->failure_threshold = thlds->spt_pathmaxrxt;
5946						net->pf_threshold = thlds->spt_pathpfthld;
5947					}
5948					stcb->asoc.def_net_failure = thlds->spt_pathmaxrxt;
5949					stcb->asoc.def_net_pf_threshold = thlds->spt_pathpfthld;
5950				}
5951			} else {
5952				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5953				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5954				    (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC)) {
5955					SCTP_INP_WLOCK(inp);
5956					inp->sctp_ep.def_net_failure = thlds->spt_pathmaxrxt;
5957					inp->sctp_ep.def_net_pf_threshold = thlds->spt_pathpfthld;
5958					SCTP_INP_WUNLOCK(inp);
5959				} else {
5960					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5961					error = EINVAL;
5962				}
5963			}
5964			break;
5965		}
5966	case SCTP_REMOTE_UDP_ENCAPS_PORT:
5967		{
5968			struct sctp_udpencaps *encaps;
5969			struct sctp_nets *net;
5970
5971			SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, optsize);
5972			SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
5973			if (stcb) {
5974				net = sctp_findnet(stcb, (struct sockaddr *)&encaps->sue_address);
5975			} else {
5976				/*
5977				 * We increment here since
5978				 * sctp_findassociation_ep_addr() wil do a
5979				 * decrement if it finds the stcb as long as
5980				 * the locked tcb (last argument) is NOT a
5981				 * TCB.. aka NULL.
5982				 */
5983				net = NULL;
5984				SCTP_INP_INCR_REF(inp);
5985				stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&encaps->sue_address, &net, NULL, NULL);
5986				if (stcb == NULL) {
5987					SCTP_INP_DECR_REF(inp);
5988				}
5989			}
5990			if (stcb && (net == NULL)) {
5991				struct sockaddr *sa;
5992
5993				sa = (struct sockaddr *)&encaps->sue_address;
5994#ifdef INET
5995				if (sa->sa_family == AF_INET) {
5996
5997					struct sockaddr_in *sin;
5998
5999					sin = (struct sockaddr_in *)sa;
6000					if (sin->sin_addr.s_addr) {
6001						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6002						SCTP_TCB_UNLOCK(stcb);
6003						error = EINVAL;
6004						break;
6005					}
6006				} else
6007#endif
6008#ifdef INET6
6009				if (sa->sa_family == AF_INET6) {
6010					struct sockaddr_in6 *sin6;
6011
6012					sin6 = (struct sockaddr_in6 *)sa;
6013					if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
6014						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6015						SCTP_TCB_UNLOCK(stcb);
6016						error = EINVAL;
6017						break;
6018					}
6019				} else
6020#endif
6021				{
6022					error = EAFNOSUPPORT;
6023					SCTP_TCB_UNLOCK(stcb);
6024					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6025					break;
6026				}
6027			}
6028			if (stcb) {
6029				if (net) {
6030					net->port = encaps->sue_port;
6031				} else {
6032					stcb->asoc.port = encaps->sue_port;
6033				}
6034				SCTP_TCB_UNLOCK(stcb);
6035			} else {
6036				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6037				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6038				    (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC)) {
6039					SCTP_INP_WLOCK(inp);
6040					inp->sctp_ep.port = encaps->sue_port;
6041					SCTP_INP_WUNLOCK(inp);
6042				} else {
6043					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6044					error = EINVAL;
6045				}
6046			}
6047			break;
6048		}
6049	case SCTP_ECN_SUPPORTED:
6050		{
6051			struct sctp_assoc_value *av;
6052
6053			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6054			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6055
6056			if (stcb) {
6057				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6058				error = EINVAL;
6059				SCTP_TCB_UNLOCK(stcb);
6060			} else {
6061				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6062				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6063				    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
6064					SCTP_INP_WLOCK(inp);
6065					if (av->assoc_value == 0) {
6066						inp->ecn_supported = 0;
6067					} else {
6068						inp->ecn_supported = 1;
6069					}
6070					SCTP_INP_WUNLOCK(inp);
6071				} else {
6072					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6073					error = EINVAL;
6074				}
6075			}
6076			break;
6077		}
6078	case SCTP_PR_SUPPORTED:
6079		{
6080			struct sctp_assoc_value *av;
6081
6082			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6083			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6084
6085			if (stcb) {
6086				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6087				error = EINVAL;
6088				SCTP_TCB_UNLOCK(stcb);
6089			} else {
6090				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6091				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6092				    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
6093					SCTP_INP_WLOCK(inp);
6094					if (av->assoc_value == 0) {
6095						inp->prsctp_supported = 0;
6096					} else {
6097						inp->prsctp_supported = 1;
6098					}
6099					SCTP_INP_WUNLOCK(inp);
6100				} else {
6101					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6102					error = EINVAL;
6103				}
6104			}
6105			break;
6106		}
6107	case SCTP_AUTH_SUPPORTED:
6108		{
6109			struct sctp_assoc_value *av;
6110
6111			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6112			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6113
6114			if (stcb) {
6115				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6116				error = EINVAL;
6117				SCTP_TCB_UNLOCK(stcb);
6118			} else {
6119				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6120				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6121				    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
6122					if ((av->assoc_value == 0) &&
6123					    (inp->asconf_supported == 1)) {
6124						/*
6125						 * AUTH is required for
6126						 * ASCONF
6127						 */
6128						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6129						error = EINVAL;
6130					} else {
6131						SCTP_INP_WLOCK(inp);
6132						if (av->assoc_value == 0) {
6133							inp->auth_supported = 0;
6134						} else {
6135							inp->auth_supported = 1;
6136						}
6137						SCTP_INP_WUNLOCK(inp);
6138					}
6139				} else {
6140					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6141					error = EINVAL;
6142				}
6143			}
6144			break;
6145		}
6146	case SCTP_ASCONF_SUPPORTED:
6147		{
6148			struct sctp_assoc_value *av;
6149
6150			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6151			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6152
6153			if (stcb) {
6154				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6155				error = EINVAL;
6156				SCTP_TCB_UNLOCK(stcb);
6157			} else {
6158				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6159				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6160				    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
6161					if ((av->assoc_value != 0) &&
6162					    (inp->auth_supported == 0)) {
6163						/*
6164						 * AUTH is required for
6165						 * ASCONF
6166						 */
6167						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6168						error = EINVAL;
6169					} else {
6170						SCTP_INP_WLOCK(inp);
6171						if (av->assoc_value == 0) {
6172							inp->asconf_supported = 0;
6173							sctp_auth_delete_chunk(SCTP_ASCONF,
6174							    inp->sctp_ep.local_auth_chunks);
6175							sctp_auth_delete_chunk(SCTP_ASCONF_ACK,
6176							    inp->sctp_ep.local_auth_chunks);
6177						} else {
6178							inp->asconf_supported = 1;
6179							sctp_auth_add_chunk(SCTP_ASCONF,
6180							    inp->sctp_ep.local_auth_chunks);
6181							sctp_auth_add_chunk(SCTP_ASCONF_ACK,
6182							    inp->sctp_ep.local_auth_chunks);
6183						}
6184						SCTP_INP_WUNLOCK(inp);
6185					}
6186				} else {
6187					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6188					error = EINVAL;
6189				}
6190			}
6191			break;
6192		}
6193	case SCTP_RECONFIG_SUPPORTED:
6194		{
6195			struct sctp_assoc_value *av;
6196
6197			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6198			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6199
6200			if (stcb) {
6201				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6202				error = EINVAL;
6203				SCTP_TCB_UNLOCK(stcb);
6204			} else {
6205				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6206				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6207				    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
6208					SCTP_INP_WLOCK(inp);
6209					if (av->assoc_value == 0) {
6210						inp->reconfig_supported = 0;
6211					} else {
6212						inp->reconfig_supported = 1;
6213					}
6214					SCTP_INP_WUNLOCK(inp);
6215				} else {
6216					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6217					error = EINVAL;
6218				}
6219			}
6220			break;
6221		}
6222	case SCTP_NRSACK_SUPPORTED:
6223		{
6224			struct sctp_assoc_value *av;
6225
6226			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6227			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6228
6229			if (stcb) {
6230				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6231				error = EINVAL;
6232				SCTP_TCB_UNLOCK(stcb);
6233			} else {
6234				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6235				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6236				    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
6237					SCTP_INP_WLOCK(inp);
6238					if (av->assoc_value == 0) {
6239						inp->nrsack_supported = 0;
6240					} else {
6241						inp->nrsack_supported = 1;
6242					}
6243					SCTP_INP_WUNLOCK(inp);
6244				} else {
6245					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6246					error = EINVAL;
6247				}
6248			}
6249			break;
6250		}
6251	case SCTP_PKTDROP_SUPPORTED:
6252		{
6253			struct sctp_assoc_value *av;
6254
6255			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6256			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6257
6258			if (stcb) {
6259				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6260				error = EINVAL;
6261				SCTP_TCB_UNLOCK(stcb);
6262			} else {
6263				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6264				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6265				    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
6266					SCTP_INP_WLOCK(inp);
6267					if (av->assoc_value == 0) {
6268						inp->pktdrop_supported = 0;
6269					} else {
6270						inp->pktdrop_supported = 1;
6271					}
6272					SCTP_INP_WUNLOCK(inp);
6273				} else {
6274					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6275					error = EINVAL;
6276				}
6277			}
6278			break;
6279		}
6280	default:
6281		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
6282		error = ENOPROTOOPT;
6283		break;
6284	}			/* end switch (opt) */
6285	return (error);
6286}
6287
6288int
6289sctp_ctloutput(struct socket *so, struct sockopt *sopt)
6290{
6291	void *optval = NULL;
6292	size_t optsize = 0;
6293	void *p;
6294	int error = 0;
6295
6296	if (sopt->sopt_level != IPPROTO_SCTP) {
6297		/* wrong proto level... send back up to IP */
6298#ifdef INET6
6299		if (INP_CHECK_SOCKAF(so, AF_INET6))
6300			error = ip6_ctloutput(so, sopt);
6301#endif				/* INET6 */
6302#if defined(INET) && defined(INET6)
6303		else
6304#endif
6305#ifdef INET
6306			error = ip_ctloutput(so, sopt);
6307#endif
6308		return (error);
6309	}
6310	optsize = sopt->sopt_valsize;
6311	if (optsize) {
6312		SCTP_MALLOC(optval, void *, optsize, SCTP_M_SOCKOPT);
6313		if (optval == NULL) {
6314			SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS);
6315			return (ENOBUFS);
6316		}
6317		error = sooptcopyin(sopt, optval, optsize, optsize);
6318		if (error) {
6319			SCTP_FREE(optval, SCTP_M_SOCKOPT);
6320			goto out;
6321		}
6322	}
6323	p = (void *)sopt->sopt_td;
6324	if (sopt->sopt_dir == SOPT_SET) {
6325		error = sctp_setopt(so, sopt->sopt_name, optval, optsize, p);
6326	} else if (sopt->sopt_dir == SOPT_GET) {
6327		error = sctp_getopt(so, sopt->sopt_name, optval, &optsize, p);
6328	} else {
6329		SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6330		error = EINVAL;
6331	}
6332	if ((error == 0) && (optval != NULL)) {
6333		error = sooptcopyout(sopt, optval, optsize);
6334		SCTP_FREE(optval, SCTP_M_SOCKOPT);
6335	} else if (optval != NULL) {
6336		SCTP_FREE(optval, SCTP_M_SOCKOPT);
6337	}
6338out:
6339	return (error);
6340}
6341
6342#ifdef INET
6343static int
6344sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
6345{
6346	int error = 0;
6347	int create_lock_on = 0;
6348	uint32_t vrf_id;
6349	struct sctp_inpcb *inp;
6350	struct sctp_tcb *stcb = NULL;
6351
6352	inp = (struct sctp_inpcb *)so->so_pcb;
6353	if (inp == NULL) {
6354		/* I made the same as TCP since we are not setup? */
6355		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6356		return (ECONNRESET);
6357	}
6358	if (addr == NULL) {
6359		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6360		return EINVAL;
6361	}
6362	switch (addr->sa_family) {
6363#ifdef INET6
6364	case AF_INET6:
6365		{
6366			struct sockaddr_in6 *sin6p;
6367
6368			if (addr->sa_len != sizeof(struct sockaddr_in6)) {
6369				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6370				return (EINVAL);
6371			}
6372			sin6p = (struct sockaddr_in6 *)addr;
6373			if (p != NULL && (error = prison_remote_ip6(p->td_ucred, &sin6p->sin6_addr)) != 0) {
6374				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6375				return (error);
6376			}
6377			break;
6378		}
6379#endif
6380#ifdef INET
6381	case AF_INET:
6382		{
6383			struct sockaddr_in *sinp;
6384
6385			if (addr->sa_len != sizeof(struct sockaddr_in)) {
6386				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6387				return (EINVAL);
6388			}
6389			sinp = (struct sockaddr_in *)addr;
6390			if (p != NULL && (error = prison_remote_ip4(p->td_ucred, &sinp->sin_addr)) != 0) {
6391				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6392				return (error);
6393			}
6394			break;
6395		}
6396#endif
6397	default:
6398		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
6399		return (EAFNOSUPPORT);
6400	}
6401	SCTP_INP_INCR_REF(inp);
6402	SCTP_ASOC_CREATE_LOCK(inp);
6403	create_lock_on = 1;
6404
6405
6406	if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
6407	    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
6408		/* Should I really unlock ? */
6409		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
6410		error = EFAULT;
6411		goto out_now;
6412	}
6413#ifdef INET6
6414	if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
6415	    (addr->sa_family == AF_INET6)) {
6416		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6417		error = EINVAL;
6418		goto out_now;
6419	}
6420#endif
6421	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
6422	    SCTP_PCB_FLAGS_UNBOUND) {
6423		/* Bind a ephemeral port */
6424		error = sctp_inpcb_bind(so, NULL, NULL, p);
6425		if (error) {
6426			goto out_now;
6427		}
6428	}
6429	/* Now do we connect? */
6430	if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
6431	    (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
6432		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6433		error = EINVAL;
6434		goto out_now;
6435	}
6436	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
6437	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
6438		/* We are already connected AND the TCP model */
6439		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
6440		error = EADDRINUSE;
6441		goto out_now;
6442	}
6443	if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
6444		SCTP_INP_RLOCK(inp);
6445		stcb = LIST_FIRST(&inp->sctp_asoc_list);
6446		SCTP_INP_RUNLOCK(inp);
6447	} else {
6448		/*
6449		 * We increment here since sctp_findassociation_ep_addr()
6450		 * will do a decrement if it finds the stcb as long as the
6451		 * locked tcb (last argument) is NOT a TCB.. aka NULL.
6452		 */
6453		SCTP_INP_INCR_REF(inp);
6454		stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
6455		if (stcb == NULL) {
6456			SCTP_INP_DECR_REF(inp);
6457		} else {
6458			SCTP_TCB_UNLOCK(stcb);
6459		}
6460	}
6461	if (stcb != NULL) {
6462		/* Already have or am bring up an association */
6463		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
6464		error = EALREADY;
6465		goto out_now;
6466	}
6467	vrf_id = inp->def_vrf_id;
6468	/* We are GOOD to go */
6469	stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, p);
6470	if (stcb == NULL) {
6471		/* Gak! no memory */
6472		goto out_now;
6473	}
6474	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
6475		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
6476		/* Set the connected flag so we can queue data */
6477		soisconnecting(so);
6478	}
6479	SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
6480	(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
6481
6482	/* initialize authentication parameters for the assoc */
6483	sctp_initialize_auth_params(inp, stcb);
6484
6485	sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
6486	SCTP_TCB_UNLOCK(stcb);
6487out_now:
6488	if (create_lock_on) {
6489		SCTP_ASOC_CREATE_UNLOCK(inp);
6490	}
6491	SCTP_INP_DECR_REF(inp);
6492	return (error);
6493}
6494
6495#endif
6496
6497int
6498sctp_listen(struct socket *so, int backlog, struct thread *p)
6499{
6500	/*
6501	 * Note this module depends on the protocol processing being called
6502	 * AFTER any socket level flags and backlog are applied to the
6503	 * socket. The traditional way that the socket flags are applied is
6504	 * AFTER protocol processing. We have made a change to the
6505	 * sys/kern/uipc_socket.c module to reverse this but this MUST be in
6506	 * place if the socket API for SCTP is to work properly.
6507	 */
6508
6509	int error = 0;
6510	struct sctp_inpcb *inp;
6511
6512	inp = (struct sctp_inpcb *)so->so_pcb;
6513	if (inp == NULL) {
6514		/* I made the same as TCP since we are not setup? */
6515		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6516		return (ECONNRESET);
6517	}
6518	if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) {
6519		/* See if we have a listener */
6520		struct sctp_inpcb *tinp;
6521		union sctp_sockstore store;
6522
6523		if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
6524			/* not bound all */
6525			struct sctp_laddr *laddr;
6526
6527			LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
6528				memcpy(&store, &laddr->ifa->address, sizeof(store));
6529				switch (store.sa.sa_family) {
6530#ifdef INET
6531				case AF_INET:
6532					store.sin.sin_port = inp->sctp_lport;
6533					break;
6534#endif
6535#ifdef INET6
6536				case AF_INET6:
6537					store.sin6.sin6_port = inp->sctp_lport;
6538					break;
6539#endif
6540				default:
6541					break;
6542				}
6543				tinp = sctp_pcb_findep(&store.sa, 0, 0, inp->def_vrf_id);
6544				if (tinp && (tinp != inp) &&
6545				    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
6546				    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
6547				    (tinp->sctp_socket->so_qlimit)) {
6548					/*
6549					 * we have a listener already and
6550					 * its not this inp.
6551					 */
6552					SCTP_INP_DECR_REF(tinp);
6553					return (EADDRINUSE);
6554				} else if (tinp) {
6555					SCTP_INP_DECR_REF(tinp);
6556				}
6557			}
6558		} else {
6559			/* Setup a local addr bound all */
6560			memset(&store, 0, sizeof(store));
6561#ifdef INET6
6562			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
6563				store.sa.sa_family = AF_INET6;
6564				store.sa.sa_len = sizeof(struct sockaddr_in6);
6565			}
6566#endif
6567#ifdef INET
6568			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
6569				store.sa.sa_family = AF_INET;
6570				store.sa.sa_len = sizeof(struct sockaddr_in);
6571			}
6572#endif
6573			switch (store.sa.sa_family) {
6574#ifdef INET
6575			case AF_INET:
6576				store.sin.sin_port = inp->sctp_lport;
6577				break;
6578#endif
6579#ifdef INET6
6580			case AF_INET6:
6581				store.sin6.sin6_port = inp->sctp_lport;
6582				break;
6583#endif
6584			default:
6585				break;
6586			}
6587			tinp = sctp_pcb_findep(&store.sa, 0, 0, inp->def_vrf_id);
6588			if (tinp && (tinp != inp) &&
6589			    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
6590			    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
6591			    (tinp->sctp_socket->so_qlimit)) {
6592				/*
6593				 * we have a listener already and its not
6594				 * this inp.
6595				 */
6596				SCTP_INP_DECR_REF(tinp);
6597				return (EADDRINUSE);
6598			} else if (tinp) {
6599				SCTP_INP_DECR_REF(inp);
6600			}
6601		}
6602	}
6603	SCTP_INP_RLOCK(inp);
6604#ifdef SCTP_LOCK_LOGGING
6605	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) {
6606		sctp_log_lock(inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_SOCK);
6607	}
6608#endif
6609	SOCK_LOCK(so);
6610	error = solisten_proto_check(so);
6611	if (error) {
6612		SOCK_UNLOCK(so);
6613		SCTP_INP_RUNLOCK(inp);
6614		return (error);
6615	}
6616	if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) &&
6617	    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
6618		/*
6619		 * The unlucky case - We are in the tcp pool with this guy.
6620		 * - Someone else is in the main inp slot. - We must move
6621		 * this guy (the listener) to the main slot - We must then
6622		 * move the guy that was listener to the TCP Pool.
6623		 */
6624		if (sctp_swap_inpcb_for_listen(inp)) {
6625			goto in_use;
6626		}
6627	}
6628	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
6629	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
6630		/* We are already connected AND the TCP model */
6631in_use:
6632		SCTP_INP_RUNLOCK(inp);
6633		SOCK_UNLOCK(so);
6634		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
6635		return (EADDRINUSE);
6636	}
6637	SCTP_INP_RUNLOCK(inp);
6638	if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
6639		/* We must do a bind. */
6640		SOCK_UNLOCK(so);
6641		if ((error = sctp_inpcb_bind(so, NULL, NULL, p))) {
6642			/* bind error, probably perm */
6643			return (error);
6644		}
6645		SOCK_LOCK(so);
6646	}
6647	/* It appears for 7.0 and on, we must always call this. */
6648	solisten_proto(so, backlog);
6649	if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
6650		/* remove the ACCEPTCONN flag for one-to-many sockets */
6651		so->so_options &= ~SO_ACCEPTCONN;
6652	}
6653	if (backlog == 0) {
6654		/* turning off listen */
6655		so->so_options &= ~SO_ACCEPTCONN;
6656	}
6657	SOCK_UNLOCK(so);
6658	return (error);
6659}
6660
6661static int sctp_defered_wakeup_cnt = 0;
6662
6663int
6664sctp_accept(struct socket *so, struct sockaddr **addr)
6665{
6666	struct sctp_tcb *stcb;
6667	struct sctp_inpcb *inp;
6668	union sctp_sockstore store;
6669
6670#ifdef INET6
6671	int error;
6672
6673#endif
6674	inp = (struct sctp_inpcb *)so->so_pcb;
6675
6676	if (inp == NULL) {
6677		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6678		return (ECONNRESET);
6679	}
6680	SCTP_INP_RLOCK(inp);
6681	if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
6682		SCTP_INP_RUNLOCK(inp);
6683		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
6684		return (EOPNOTSUPP);
6685	}
6686	if (so->so_state & SS_ISDISCONNECTED) {
6687		SCTP_INP_RUNLOCK(inp);
6688		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ECONNABORTED);
6689		return (ECONNABORTED);
6690	}
6691	stcb = LIST_FIRST(&inp->sctp_asoc_list);
6692	if (stcb == NULL) {
6693		SCTP_INP_RUNLOCK(inp);
6694		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6695		return (ECONNRESET);
6696	}
6697	SCTP_TCB_LOCK(stcb);
6698	SCTP_INP_RUNLOCK(inp);
6699	store = stcb->asoc.primary_destination->ro._l_addr;
6700	stcb->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE;
6701	SCTP_TCB_UNLOCK(stcb);
6702	switch (store.sa.sa_family) {
6703#ifdef INET
6704	case AF_INET:
6705		{
6706			struct sockaddr_in *sin;
6707
6708			SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
6709			if (sin == NULL)
6710				return (ENOMEM);
6711			sin->sin_family = AF_INET;
6712			sin->sin_len = sizeof(*sin);
6713			sin->sin_port = store.sin.sin_port;
6714			sin->sin_addr = store.sin.sin_addr;
6715			*addr = (struct sockaddr *)sin;
6716			break;
6717		}
6718#endif
6719#ifdef INET6
6720	case AF_INET6:
6721		{
6722			struct sockaddr_in6 *sin6;
6723
6724			SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
6725			if (sin6 == NULL)
6726				return (ENOMEM);
6727			sin6->sin6_family = AF_INET6;
6728			sin6->sin6_len = sizeof(*sin6);
6729			sin6->sin6_port = store.sin6.sin6_port;
6730			sin6->sin6_addr = store.sin6.sin6_addr;
6731			if ((error = sa6_recoverscope(sin6)) != 0) {
6732				SCTP_FREE_SONAME(sin6);
6733				return (error);
6734			}
6735			*addr = (struct sockaddr *)sin6;
6736			break;
6737		}
6738#endif
6739	default:
6740		/* TSNH */
6741		break;
6742	}
6743	/* Wake any delayed sleep action */
6744	if (inp->sctp_flags & SCTP_PCB_FLAGS_DONT_WAKE) {
6745		SCTP_INP_WLOCK(inp);
6746		inp->sctp_flags &= ~SCTP_PCB_FLAGS_DONT_WAKE;
6747		if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEOUTPUT) {
6748			inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEOUTPUT;
6749			SCTP_INP_WUNLOCK(inp);
6750			SOCKBUF_LOCK(&inp->sctp_socket->so_snd);
6751			if (sowriteable(inp->sctp_socket)) {
6752				sowwakeup_locked(inp->sctp_socket);
6753			} else {
6754				SOCKBUF_UNLOCK(&inp->sctp_socket->so_snd);
6755			}
6756			SCTP_INP_WLOCK(inp);
6757		}
6758		if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEINPUT) {
6759			inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEINPUT;
6760			SCTP_INP_WUNLOCK(inp);
6761			SOCKBUF_LOCK(&inp->sctp_socket->so_rcv);
6762			if (soreadable(inp->sctp_socket)) {
6763				sctp_defered_wakeup_cnt++;
6764				sorwakeup_locked(inp->sctp_socket);
6765			} else {
6766				SOCKBUF_UNLOCK(&inp->sctp_socket->so_rcv);
6767			}
6768			SCTP_INP_WLOCK(inp);
6769		}
6770		SCTP_INP_WUNLOCK(inp);
6771	}
6772	if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
6773		SCTP_TCB_LOCK(stcb);
6774		sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_7);
6775	}
6776	return (0);
6777}
6778
6779#ifdef INET
6780int
6781sctp_ingetaddr(struct socket *so, struct sockaddr **addr)
6782{
6783	struct sockaddr_in *sin;
6784	uint32_t vrf_id;
6785	struct sctp_inpcb *inp;
6786	struct sctp_ifa *sctp_ifa;
6787
6788	/*
6789	 * Do the malloc first in case it blocks.
6790	 */
6791	SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
6792	if (sin == NULL)
6793		return (ENOMEM);
6794	sin->sin_family = AF_INET;
6795	sin->sin_len = sizeof(*sin);
6796	inp = (struct sctp_inpcb *)so->so_pcb;
6797	if (!inp) {
6798		SCTP_FREE_SONAME(sin);
6799		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6800		return (ECONNRESET);
6801	}
6802	SCTP_INP_RLOCK(inp);
6803	sin->sin_port = inp->sctp_lport;
6804	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
6805		if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
6806			struct sctp_tcb *stcb;
6807			struct sockaddr_in *sin_a;
6808			struct sctp_nets *net;
6809			int fnd;
6810
6811			stcb = LIST_FIRST(&inp->sctp_asoc_list);
6812			if (stcb == NULL) {
6813				goto notConn;
6814			}
6815			fnd = 0;
6816			sin_a = NULL;
6817			SCTP_TCB_LOCK(stcb);
6818			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6819				sin_a = (struct sockaddr_in *)&net->ro._l_addr;
6820				if (sin_a == NULL)
6821					/* this will make coverity happy */
6822					continue;
6823
6824				if (sin_a->sin_family == AF_INET) {
6825					fnd = 1;
6826					break;
6827				}
6828			}
6829			if ((!fnd) || (sin_a == NULL)) {
6830				/* punt */
6831				SCTP_TCB_UNLOCK(stcb);
6832				goto notConn;
6833			}
6834			vrf_id = inp->def_vrf_id;
6835			sctp_ifa = sctp_source_address_selection(inp,
6836			    stcb,
6837			    (sctp_route_t *) & net->ro,
6838			    net, 0, vrf_id);
6839			if (sctp_ifa) {
6840				sin->sin_addr = sctp_ifa->address.sin.sin_addr;
6841				sctp_free_ifa(sctp_ifa);
6842			}
6843			SCTP_TCB_UNLOCK(stcb);
6844		} else {
6845			/* For the bound all case you get back 0 */
6846	notConn:
6847			sin->sin_addr.s_addr = 0;
6848		}
6849
6850	} else {
6851		/* Take the first IPv4 address in the list */
6852		struct sctp_laddr *laddr;
6853		int fnd = 0;
6854
6855		LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
6856			if (laddr->ifa->address.sa.sa_family == AF_INET) {
6857				struct sockaddr_in *sin_a;
6858
6859				sin_a = (struct sockaddr_in *)&laddr->ifa->address.sa;
6860				sin->sin_addr = sin_a->sin_addr;
6861				fnd = 1;
6862				break;
6863			}
6864		}
6865		if (!fnd) {
6866			SCTP_FREE_SONAME(sin);
6867			SCTP_INP_RUNLOCK(inp);
6868			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
6869			return (ENOENT);
6870		}
6871	}
6872	SCTP_INP_RUNLOCK(inp);
6873	(*addr) = (struct sockaddr *)sin;
6874	return (0);
6875}
6876
6877int
6878sctp_peeraddr(struct socket *so, struct sockaddr **addr)
6879{
6880	struct sockaddr_in *sin;
6881	int fnd;
6882	struct sockaddr_in *sin_a;
6883	struct sctp_inpcb *inp;
6884	struct sctp_tcb *stcb;
6885	struct sctp_nets *net;
6886
6887	/* Do the malloc first in case it blocks. */
6888	SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
6889	if (sin == NULL)
6890		return (ENOMEM);
6891	sin->sin_family = AF_INET;
6892	sin->sin_len = sizeof(*sin);
6893
6894	inp = (struct sctp_inpcb *)so->so_pcb;
6895	if ((inp == NULL) ||
6896	    ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
6897		/* UDP type and listeners will drop out here */
6898		SCTP_FREE_SONAME(sin);
6899		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
6900		return (ENOTCONN);
6901	}
6902	SCTP_INP_RLOCK(inp);
6903	stcb = LIST_FIRST(&inp->sctp_asoc_list);
6904	if (stcb) {
6905		SCTP_TCB_LOCK(stcb);
6906	}
6907	SCTP_INP_RUNLOCK(inp);
6908	if (stcb == NULL) {
6909		SCTP_FREE_SONAME(sin);
6910		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6911		return (ECONNRESET);
6912	}
6913	fnd = 0;
6914	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6915		sin_a = (struct sockaddr_in *)&net->ro._l_addr;
6916		if (sin_a->sin_family == AF_INET) {
6917			fnd = 1;
6918			sin->sin_port = stcb->rport;
6919			sin->sin_addr = sin_a->sin_addr;
6920			break;
6921		}
6922	}
6923	SCTP_TCB_UNLOCK(stcb);
6924	if (!fnd) {
6925		/* No IPv4 address */
6926		SCTP_FREE_SONAME(sin);
6927		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
6928		return (ENOENT);
6929	}
6930	(*addr) = (struct sockaddr *)sin;
6931	return (0);
6932}
6933
6934struct pr_usrreqs sctp_usrreqs = {
6935	.pru_abort = sctp_abort,
6936	.pru_accept = sctp_accept,
6937	.pru_attach = sctp_attach,
6938	.pru_bind = sctp_bind,
6939	.pru_connect = sctp_connect,
6940	.pru_control = in_control,
6941	.pru_close = sctp_close,
6942	.pru_detach = sctp_close,
6943	.pru_sopoll = sopoll_generic,
6944	.pru_flush = sctp_flush,
6945	.pru_disconnect = sctp_disconnect,
6946	.pru_listen = sctp_listen,
6947	.pru_peeraddr = sctp_peeraddr,
6948	.pru_send = sctp_sendm,
6949	.pru_shutdown = sctp_shutdown,
6950	.pru_sockaddr = sctp_ingetaddr,
6951	.pru_sosend = sctp_sosend,
6952	.pru_soreceive = sctp_soreceive
6953};
6954
6955#endif
6956