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