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