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