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