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