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