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