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