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