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