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