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