sctp_usrreq.c revision 235021
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 235021 2012-05-04 17:18:02Z 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			case SCTP_ASSOC_RESET_EVENT:
2987				event_type = SCTP_PCB_FLAGS_ASSOC_RESETEVNT;
2988				break;
2989			case SCTP_STREAM_CHANGE_EVENT:
2990				event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT;
2991				break;
2992			default:
2993				event_type = 0;
2994				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2995				error = EINVAL;
2996				break;
2997			}
2998			if (event_type > 0) {
2999				if (stcb) {
3000					event->se_on = sctp_stcb_is_feature_on(inp, stcb, event_type);
3001					SCTP_TCB_UNLOCK(stcb);
3002				} else {
3003					if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3004					    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3005					    (event->se_assoc_id == SCTP_FUTURE_ASSOC)) {
3006						SCTP_INP_RLOCK(inp);
3007						event->se_on = sctp_is_feature_on(inp, event_type);
3008						SCTP_INP_RUNLOCK(inp);
3009					} else {
3010						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3011						error = EINVAL;
3012					}
3013				}
3014			}
3015			if (error == 0) {
3016				*optsize = sizeof(struct sctp_event);
3017			}
3018			break;
3019		}
3020	case SCTP_RECVRCVINFO:
3021		{
3022			int onoff;
3023
3024			if (*optsize < sizeof(int)) {
3025				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3026				error = EINVAL;
3027			} else {
3028				SCTP_INP_RLOCK(inp);
3029				onoff = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
3030				SCTP_INP_RUNLOCK(inp);
3031			}
3032			if (error == 0) {
3033				/* return the option value */
3034				*(int *)optval = onoff;
3035				*optsize = sizeof(int);
3036			}
3037			break;
3038		}
3039	case SCTP_RECVNXTINFO:
3040		{
3041			int onoff;
3042
3043			if (*optsize < sizeof(int)) {
3044				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3045				error = EINVAL;
3046			} else {
3047				SCTP_INP_RLOCK(inp);
3048				onoff = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
3049				SCTP_INP_RUNLOCK(inp);
3050			}
3051			if (error == 0) {
3052				/* return the option value */
3053				*(int *)optval = onoff;
3054				*optsize = sizeof(int);
3055			}
3056			break;
3057		}
3058	case SCTP_DEFAULT_SNDINFO:
3059		{
3060			struct sctp_sndinfo *info;
3061
3062			SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, *optsize);
3063			SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
3064
3065			if (stcb) {
3066				info->snd_sid = stcb->asoc.def_send.sinfo_stream;
3067				info->snd_flags = stcb->asoc.def_send.sinfo_flags;
3068				info->snd_flags &= 0xfff0;
3069				info->snd_ppid = stcb->asoc.def_send.sinfo_ppid;
3070				info->snd_context = stcb->asoc.def_send.sinfo_context;
3071				SCTP_TCB_UNLOCK(stcb);
3072			} else {
3073				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3074				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3075				    (info->snd_assoc_id == SCTP_FUTURE_ASSOC)) {
3076					SCTP_INP_RLOCK(inp);
3077					info->snd_sid = inp->def_send.sinfo_stream;
3078					info->snd_flags = inp->def_send.sinfo_flags;
3079					info->snd_flags &= 0xfff0;
3080					info->snd_ppid = inp->def_send.sinfo_ppid;
3081					info->snd_context = inp->def_send.sinfo_context;
3082					SCTP_INP_RUNLOCK(inp);
3083				} else {
3084					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3085					error = EINVAL;
3086				}
3087			}
3088			if (error == 0) {
3089				*optsize = sizeof(struct sctp_sndinfo);
3090			}
3091			break;
3092		}
3093	case SCTP_DEFAULT_PRINFO:
3094		{
3095			struct sctp_default_prinfo *info;
3096
3097			SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, *optsize);
3098			SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
3099
3100			if (stcb) {
3101				info->pr_policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
3102				info->pr_value = stcb->asoc.def_send.sinfo_timetolive;
3103				SCTP_TCB_UNLOCK(stcb);
3104			} else {
3105				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3106				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3107				    (info->pr_assoc_id == SCTP_FUTURE_ASSOC)) {
3108					SCTP_INP_RLOCK(inp);
3109					info->pr_policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
3110					info->pr_value = inp->def_send.sinfo_timetolive;
3111					SCTP_INP_RUNLOCK(inp);
3112				} else {
3113					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3114					error = EINVAL;
3115				}
3116			}
3117			if (error == 0) {
3118				*optsize = sizeof(struct sctp_default_prinfo);
3119			}
3120			break;
3121		}
3122	case SCTP_PEER_ADDR_THLDS:
3123		{
3124			struct sctp_paddrthlds *thlds;
3125			struct sctp_nets *net;
3126
3127			SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, *optsize);
3128			SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
3129
3130			net = NULL;
3131			if (stcb) {
3132				net = sctp_findnet(stcb, (struct sockaddr *)&thlds->spt_address);
3133			} else {
3134				/*
3135				 * We increment here since
3136				 * sctp_findassociation_ep_addr() wil do a
3137				 * decrement if it finds the stcb as long as
3138				 * the locked tcb (last argument) is NOT a
3139				 * TCB.. aka NULL.
3140				 */
3141				SCTP_INP_INCR_REF(inp);
3142				stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&thlds->spt_address, &net, NULL, NULL);
3143				if (stcb == NULL) {
3144					SCTP_INP_DECR_REF(inp);
3145				}
3146			}
3147			if (stcb && (net == NULL)) {
3148				struct sockaddr *sa;
3149
3150				sa = (struct sockaddr *)&thlds->spt_address;
3151#ifdef INET
3152				if (sa->sa_family == AF_INET) {
3153					struct sockaddr_in *sin;
3154
3155					sin = (struct sockaddr_in *)sa;
3156					if (sin->sin_addr.s_addr) {
3157						error = EINVAL;
3158						SCTP_TCB_UNLOCK(stcb);
3159						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3160						break;
3161					}
3162				} else
3163#endif
3164#ifdef INET6
3165				if (sa->sa_family == AF_INET6) {
3166					struct sockaddr_in6 *sin6;
3167
3168					sin6 = (struct sockaddr_in6 *)sa;
3169					if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
3170						error = EINVAL;
3171						SCTP_TCB_UNLOCK(stcb);
3172						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3173						break;
3174					}
3175				} else
3176#endif
3177				{
3178					error = EAFNOSUPPORT;
3179					SCTP_TCB_UNLOCK(stcb);
3180					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3181					break;
3182				}
3183			}
3184			if (stcb) {
3185				if (net) {
3186					thlds->spt_pathmaxrxt = net->failure_threshold;
3187					thlds->spt_pathpfthld = net->pf_threshold;
3188				} else {
3189					thlds->spt_pathmaxrxt = stcb->asoc.def_net_failure;
3190					thlds->spt_pathpfthld = stcb->asoc.def_net_pf_threshold;
3191				}
3192				thlds->spt_assoc_id = sctp_get_associd(stcb);
3193				SCTP_TCB_UNLOCK(stcb);
3194			} else {
3195				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3196				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3197				    (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC)) {
3198					/* Use endpoint defaults */
3199					SCTP_INP_RLOCK(inp);
3200					thlds->spt_pathmaxrxt = inp->sctp_ep.def_net_failure;
3201					thlds->spt_pathpfthld = inp->sctp_ep.def_net_pf_threshold;
3202					SCTP_INP_RUNLOCK(inp);
3203				} else {
3204					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3205					error = EINVAL;
3206				}
3207			}
3208			if (error == 0) {
3209				*optsize = sizeof(struct sctp_paddrthlds);
3210			}
3211			break;
3212		}
3213	case SCTP_REMOTE_UDP_ENCAPS_PORT:
3214		{
3215			struct sctp_udpencaps *encaps;
3216			struct sctp_nets *net;
3217
3218			SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, *optsize);
3219			SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
3220
3221			if (stcb) {
3222				net = sctp_findnet(stcb, (struct sockaddr *)&encaps->sue_address);
3223			} else {
3224				/*
3225				 * We increment here since
3226				 * sctp_findassociation_ep_addr() wil do a
3227				 * decrement if it finds the stcb as long as
3228				 * the locked tcb (last argument) is NOT a
3229				 * TCB.. aka NULL.
3230				 */
3231				net = NULL;
3232				SCTP_INP_INCR_REF(inp);
3233				stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&encaps->sue_address, &net, NULL, NULL);
3234				if (stcb == NULL) {
3235					SCTP_INP_DECR_REF(inp);
3236				}
3237			}
3238			if (stcb && (net == NULL)) {
3239				struct sockaddr *sa;
3240
3241				sa = (struct sockaddr *)&encaps->sue_address;
3242#ifdef INET
3243				if (sa->sa_family == AF_INET) {
3244					struct sockaddr_in *sin;
3245
3246					sin = (struct sockaddr_in *)sa;
3247					if (sin->sin_addr.s_addr) {
3248						error = EINVAL;
3249						SCTP_TCB_UNLOCK(stcb);
3250						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3251						break;
3252					}
3253				} else
3254#endif
3255#ifdef INET6
3256				if (sa->sa_family == AF_INET6) {
3257					struct sockaddr_in6 *sin6;
3258
3259					sin6 = (struct sockaddr_in6 *)sa;
3260					if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
3261						error = EINVAL;
3262						SCTP_TCB_UNLOCK(stcb);
3263						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3264						break;
3265					}
3266				} else
3267#endif
3268				{
3269					error = EAFNOSUPPORT;
3270					SCTP_TCB_UNLOCK(stcb);
3271					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3272					break;
3273				}
3274			}
3275			if (stcb) {
3276				if (net) {
3277					encaps->sue_port = net->port;
3278				} else {
3279					encaps->sue_port = stcb->asoc.port;
3280				}
3281				SCTP_TCB_UNLOCK(stcb);
3282			} else {
3283				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3284				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3285				    (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC)) {
3286					SCTP_INP_RLOCK(inp);
3287					encaps->sue_port = inp->sctp_ep.port;
3288					SCTP_INP_RUNLOCK(inp);
3289				} else {
3290					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3291					error = EINVAL;
3292				}
3293			}
3294			if (error == 0) {
3295				*optsize = sizeof(struct sctp_paddrparams);
3296			}
3297			break;
3298		}
3299	case SCTP_ENABLE_STREAM_RESET:
3300		{
3301			struct sctp_assoc_value *av;
3302
3303			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
3304			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3305
3306			if (stcb) {
3307				av->assoc_value = (uint32_t) stcb->asoc.local_strreset_support;
3308				SCTP_TCB_UNLOCK(stcb);
3309			} else {
3310				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3311				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3312				    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
3313					SCTP_INP_RLOCK(inp);
3314					av->assoc_value = (uint32_t) inp->local_strreset_support;
3315					SCTP_INP_RUNLOCK(inp);
3316				} else {
3317					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3318					error = EINVAL;
3319				}
3320			}
3321			if (error == 0) {
3322				*optsize = sizeof(struct sctp_assoc_value);
3323			}
3324			break;
3325		}
3326	default:
3327		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
3328		error = ENOPROTOOPT;
3329		break;
3330	}			/* end switch (sopt->sopt_name) */
3331	if (error) {
3332		*optsize = 0;
3333	}
3334	return (error);
3335}
3336
3337static int
3338sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
3339    void *p)
3340{
3341	int error, set_opt;
3342	uint32_t *mopt;
3343	struct sctp_tcb *stcb = NULL;
3344	struct sctp_inpcb *inp = NULL;
3345	uint32_t vrf_id;
3346
3347	if (optval == NULL) {
3348		SCTP_PRINTF("optval is NULL\n");
3349		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3350		return (EINVAL);
3351	}
3352	inp = (struct sctp_inpcb *)so->so_pcb;
3353	if (inp == NULL) {
3354		SCTP_PRINTF("inp is NULL?\n");
3355		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3356		return (EINVAL);
3357	}
3358	vrf_id = inp->def_vrf_id;
3359
3360	error = 0;
3361	switch (optname) {
3362	case SCTP_NODELAY:
3363	case SCTP_AUTOCLOSE:
3364	case SCTP_AUTO_ASCONF:
3365	case SCTP_EXPLICIT_EOR:
3366	case SCTP_DISABLE_FRAGMENTS:
3367	case SCTP_USE_EXT_RCVINFO:
3368	case SCTP_I_WANT_MAPPED_V4_ADDR:
3369		/* copy in the option value */
3370		SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
3371		set_opt = 0;
3372		if (error)
3373			break;
3374		switch (optname) {
3375		case SCTP_DISABLE_FRAGMENTS:
3376			set_opt = SCTP_PCB_FLAGS_NO_FRAGMENT;
3377			break;
3378		case SCTP_AUTO_ASCONF:
3379			/*
3380			 * NOTE: we don't really support this flag
3381			 */
3382			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
3383				/* only valid for bound all sockets */
3384				if ((SCTP_BASE_SYSCTL(sctp_auto_asconf) == 0) &&
3385				    (*mopt != 0)) {
3386					/* forbidden by admin */
3387					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EPERM);
3388					return (EPERM);
3389				}
3390				set_opt = SCTP_PCB_FLAGS_AUTO_ASCONF;
3391			} else {
3392				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3393				return (EINVAL);
3394			}
3395			break;
3396		case SCTP_EXPLICIT_EOR:
3397			set_opt = SCTP_PCB_FLAGS_EXPLICIT_EOR;
3398			break;
3399		case SCTP_USE_EXT_RCVINFO:
3400			set_opt = SCTP_PCB_FLAGS_EXT_RCVINFO;
3401			break;
3402		case SCTP_I_WANT_MAPPED_V4_ADDR:
3403			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
3404				set_opt = SCTP_PCB_FLAGS_NEEDS_MAPPED_V4;
3405			} else {
3406				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3407				return (EINVAL);
3408			}
3409			break;
3410		case SCTP_NODELAY:
3411			set_opt = SCTP_PCB_FLAGS_NODELAY;
3412			break;
3413		case SCTP_AUTOCLOSE:
3414			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3415			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
3416				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3417				return (EINVAL);
3418			}
3419			set_opt = SCTP_PCB_FLAGS_AUTOCLOSE;
3420			/*
3421			 * The value is in ticks. Note this does not effect
3422			 * old associations, only new ones.
3423			 */
3424			inp->sctp_ep.auto_close_time = SEC_TO_TICKS(*mopt);
3425			break;
3426		}
3427		SCTP_INP_WLOCK(inp);
3428		if (*mopt != 0) {
3429			sctp_feature_on(inp, set_opt);
3430		} else {
3431			sctp_feature_off(inp, set_opt);
3432		}
3433		SCTP_INP_WUNLOCK(inp);
3434		break;
3435	case SCTP_REUSE_PORT:
3436		{
3437			SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
3438			if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) {
3439				/* Can't set it after we are bound */
3440				error = EINVAL;
3441				break;
3442			}
3443			if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
3444				/* Can't do this for a 1-m socket */
3445				error = EINVAL;
3446				break;
3447			}
3448			if (optval)
3449				sctp_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE);
3450			else
3451				sctp_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE);
3452			break;
3453		}
3454	case SCTP_PARTIAL_DELIVERY_POINT:
3455		{
3456			uint32_t *value;
3457
3458			SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
3459			if (*value > SCTP_SB_LIMIT_RCV(so)) {
3460				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3461				error = EINVAL;
3462				break;
3463			}
3464			inp->partial_delivery_point = *value;
3465			break;
3466		}
3467	case SCTP_FRAGMENT_INTERLEAVE:
3468		/* not yet until we re-write sctp_recvmsg() */
3469		{
3470			uint32_t *level;
3471
3472			SCTP_CHECK_AND_CAST(level, optval, uint32_t, optsize);
3473			if (*level == SCTP_FRAG_LEVEL_2) {
3474				sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
3475				sctp_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
3476			} else if (*level == SCTP_FRAG_LEVEL_1) {
3477				sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
3478				sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
3479			} else if (*level == SCTP_FRAG_LEVEL_0) {
3480				sctp_feature_off(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
3481				sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
3482
3483			} else {
3484				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3485				error = EINVAL;
3486			}
3487			break;
3488		}
3489	case SCTP_CMT_ON_OFF:
3490		if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
3491			struct sctp_assoc_value *av;
3492
3493			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
3494			if (av->assoc_value > SCTP_CMT_MAX) {
3495				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3496				error = EINVAL;
3497				break;
3498			}
3499			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3500			if (stcb) {
3501				stcb->asoc.sctp_cmt_on_off = av->assoc_value;
3502				SCTP_TCB_UNLOCK(stcb);
3503			} else {
3504				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3505				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3506				    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
3507				    (av->assoc_id == SCTP_ALL_ASSOC)) {
3508					SCTP_INP_WLOCK(inp);
3509					inp->sctp_cmt_on_off = av->assoc_value;
3510					SCTP_INP_WUNLOCK(inp);
3511				}
3512				if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
3513				    (av->assoc_id == SCTP_ALL_ASSOC)) {
3514					SCTP_INP_RLOCK(inp);
3515					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3516						SCTP_TCB_LOCK(stcb);
3517						stcb->asoc.sctp_cmt_on_off = av->assoc_value;
3518						SCTP_TCB_UNLOCK(stcb);
3519					}
3520					SCTP_INP_RUNLOCK(inp);
3521				}
3522			}
3523		} else {
3524			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
3525			error = ENOPROTOOPT;
3526		}
3527		break;
3528	case SCTP_PLUGGABLE_CC:
3529		{
3530			struct sctp_assoc_value *av;
3531			struct sctp_nets *net;
3532
3533			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
3534			if ((av->assoc_value != SCTP_CC_RFC2581) &&
3535			    (av->assoc_value != SCTP_CC_HSTCP) &&
3536			    (av->assoc_value != SCTP_CC_HTCP) &&
3537			    (av->assoc_value != SCTP_CC_RTCC)) {
3538				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3539				error = EINVAL;
3540				break;
3541			}
3542			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3543			if (stcb) {
3544				stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
3545				stcb->asoc.congestion_control_module = av->assoc_value;
3546				if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
3547					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
3548						stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
3549					}
3550				}
3551				SCTP_TCB_UNLOCK(stcb);
3552			} else {
3553				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3554				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3555				    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
3556				    (av->assoc_id == SCTP_ALL_ASSOC)) {
3557					SCTP_INP_WLOCK(inp);
3558					inp->sctp_ep.sctp_default_cc_module = av->assoc_value;
3559					SCTP_INP_WUNLOCK(inp);
3560				}
3561				if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
3562				    (av->assoc_id == SCTP_ALL_ASSOC)) {
3563					SCTP_INP_RLOCK(inp);
3564					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3565						SCTP_TCB_LOCK(stcb);
3566						stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
3567						stcb->asoc.congestion_control_module = av->assoc_value;
3568						if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
3569							TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
3570								stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
3571							}
3572						}
3573						SCTP_TCB_UNLOCK(stcb);
3574					}
3575					SCTP_INP_RUNLOCK(inp);
3576				}
3577			}
3578			break;
3579		}
3580	case SCTP_CC_OPTION:
3581		{
3582			struct sctp_cc_option *cc_opt;
3583
3584			SCTP_CHECK_AND_CAST(cc_opt, optval, struct sctp_cc_option, optsize);
3585			SCTP_FIND_STCB(inp, stcb, cc_opt->aid_value.assoc_id);
3586			if (stcb == NULL) {
3587				if (cc_opt->aid_value.assoc_id == SCTP_CURRENT_ASSOC) {
3588					SCTP_INP_RLOCK(inp);
3589					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3590						SCTP_TCB_LOCK(stcb);
3591						if (stcb->asoc.cc_functions.sctp_cwnd_socket_option) {
3592							(*stcb->asoc.cc_functions.sctp_cwnd_socket_option) (stcb, 1, cc_opt);
3593						}
3594						SCTP_TCB_UNLOCK(stcb);
3595					}
3596					SCTP_INP_RUNLOCK(inp);
3597				} else {
3598					error = EINVAL;
3599				}
3600			} else {
3601				if (stcb->asoc.cc_functions.sctp_cwnd_socket_option == NULL) {
3602					error = ENOTSUP;
3603				} else {
3604					error = (*stcb->asoc.cc_functions.sctp_cwnd_socket_option) (stcb, 1,
3605					    cc_opt);
3606				}
3607				SCTP_TCB_UNLOCK(stcb);
3608			}
3609			break;
3610		}
3611	case SCTP_PLUGGABLE_SS:
3612		{
3613			struct sctp_assoc_value *av;
3614
3615			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
3616			if ((av->assoc_value != SCTP_SS_DEFAULT) &&
3617			    (av->assoc_value != SCTP_SS_ROUND_ROBIN) &&
3618			    (av->assoc_value != SCTP_SS_ROUND_ROBIN_PACKET) &&
3619			    (av->assoc_value != SCTP_SS_PRIORITY) &&
3620			    (av->assoc_value != SCTP_SS_FAIR_BANDWITH) &&
3621			    (av->assoc_value != SCTP_SS_FIRST_COME)) {
3622				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3623				error = EINVAL;
3624				break;
3625			}
3626			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3627			if (stcb) {
3628				stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1);
3629				stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
3630				stcb->asoc.stream_scheduling_module = av->assoc_value;
3631				stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
3632				SCTP_TCB_UNLOCK(stcb);
3633			} else {
3634				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3635				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3636				    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
3637				    (av->assoc_id == SCTP_ALL_ASSOC)) {
3638					SCTP_INP_WLOCK(inp);
3639					inp->sctp_ep.sctp_default_ss_module = av->assoc_value;
3640					SCTP_INP_WUNLOCK(inp);
3641				}
3642				if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
3643				    (av->assoc_id == SCTP_ALL_ASSOC)) {
3644					SCTP_INP_RLOCK(inp);
3645					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3646						SCTP_TCB_LOCK(stcb);
3647						stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1);
3648						stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
3649						stcb->asoc.stream_scheduling_module = av->assoc_value;
3650						stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
3651						SCTP_TCB_UNLOCK(stcb);
3652					}
3653					SCTP_INP_RUNLOCK(inp);
3654				}
3655			}
3656			break;
3657		}
3658	case SCTP_SS_VALUE:
3659		{
3660			struct sctp_stream_value *av;
3661
3662			SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, optsize);
3663			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3664			if (stcb) {
3665				if (stcb->asoc.ss_functions.sctp_ss_set_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id],
3666				    av->stream_value) < 0) {
3667					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3668					error = EINVAL;
3669				}
3670				SCTP_TCB_UNLOCK(stcb);
3671			} else {
3672				if (av->assoc_id == SCTP_CURRENT_ASSOC) {
3673					SCTP_INP_RLOCK(inp);
3674					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3675						SCTP_TCB_LOCK(stcb);
3676						stcb->asoc.ss_functions.sctp_ss_set_value(stcb,
3677						    &stcb->asoc,
3678						    &stcb->asoc.strmout[av->stream_id],
3679						    av->stream_value);
3680						SCTP_TCB_UNLOCK(stcb);
3681					}
3682					SCTP_INP_RUNLOCK(inp);
3683
3684				} else {
3685					/*
3686					 * Can't set stream value without
3687					 * association
3688					 */
3689					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3690					error = EINVAL;
3691				}
3692			}
3693			break;
3694		}
3695	case SCTP_CLR_STAT_LOG:
3696		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
3697		error = EOPNOTSUPP;
3698		break;
3699	case SCTP_CONTEXT:
3700		{
3701			struct sctp_assoc_value *av;
3702
3703			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
3704			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3705
3706			if (stcb) {
3707				stcb->asoc.context = av->assoc_value;
3708				SCTP_TCB_UNLOCK(stcb);
3709			} else {
3710				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3711				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3712				    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
3713				    (av->assoc_id == SCTP_ALL_ASSOC)) {
3714					SCTP_INP_WLOCK(inp);
3715					inp->sctp_context = av->assoc_value;
3716					SCTP_INP_WUNLOCK(inp);
3717				}
3718				if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
3719				    (av->assoc_id == SCTP_ALL_ASSOC)) {
3720					SCTP_INP_RLOCK(inp);
3721					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3722						SCTP_TCB_LOCK(stcb);
3723						stcb->asoc.context = av->assoc_value;
3724						SCTP_TCB_UNLOCK(stcb);
3725					}
3726					SCTP_INP_RUNLOCK(inp);
3727				}
3728			}
3729			break;
3730		}
3731	case SCTP_VRF_ID:
3732		{
3733			uint32_t *default_vrfid;
3734
3735			SCTP_CHECK_AND_CAST(default_vrfid, optval, uint32_t, optsize);
3736			if (*default_vrfid > SCTP_MAX_VRF_ID) {
3737				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3738				error = EINVAL;
3739				break;
3740			}
3741			inp->def_vrf_id = *default_vrfid;
3742			break;
3743		}
3744	case SCTP_DEL_VRF_ID:
3745		{
3746			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
3747			error = EOPNOTSUPP;
3748			break;
3749		}
3750	case SCTP_ADD_VRF_ID:
3751		{
3752			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
3753			error = EOPNOTSUPP;
3754			break;
3755		}
3756	case SCTP_DELAYED_SACK:
3757		{
3758			struct sctp_sack_info *sack;
3759
3760			SCTP_CHECK_AND_CAST(sack, optval, struct sctp_sack_info, optsize);
3761			SCTP_FIND_STCB(inp, stcb, sack->sack_assoc_id);
3762			if (sack->sack_delay) {
3763				if (sack->sack_delay > SCTP_MAX_SACK_DELAY)
3764					sack->sack_delay = SCTP_MAX_SACK_DELAY;
3765				if (MSEC_TO_TICKS(sack->sack_delay) < 1) {
3766					sack->sack_delay = TICKS_TO_MSEC(1);
3767				}
3768			}
3769			if (stcb) {
3770				if (sack->sack_delay) {
3771					stcb->asoc.delayed_ack = sack->sack_delay;
3772				}
3773				if (sack->sack_freq) {
3774					stcb->asoc.sack_freq = sack->sack_freq;
3775				}
3776				SCTP_TCB_UNLOCK(stcb);
3777			} else {
3778				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3779				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3780				    (sack->sack_assoc_id == SCTP_FUTURE_ASSOC) ||
3781				    (sack->sack_assoc_id == SCTP_ALL_ASSOC)) {
3782					SCTP_INP_WLOCK(inp);
3783					if (sack->sack_delay) {
3784						inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV] = MSEC_TO_TICKS(sack->sack_delay);
3785					}
3786					if (sack->sack_freq) {
3787						inp->sctp_ep.sctp_sack_freq = sack->sack_freq;
3788					}
3789					SCTP_INP_WUNLOCK(inp);
3790				}
3791				if ((sack->sack_assoc_id == SCTP_CURRENT_ASSOC) ||
3792				    (sack->sack_assoc_id == SCTP_ALL_ASSOC)) {
3793					SCTP_INP_RLOCK(inp);
3794					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3795						SCTP_TCB_LOCK(stcb);
3796						if (sack->sack_delay) {
3797							stcb->asoc.delayed_ack = sack->sack_delay;
3798						}
3799						if (sack->sack_freq) {
3800							stcb->asoc.sack_freq = sack->sack_freq;
3801						}
3802						SCTP_TCB_UNLOCK(stcb);
3803					}
3804					SCTP_INP_RUNLOCK(inp);
3805				}
3806			}
3807			break;
3808		}
3809	case SCTP_AUTH_CHUNK:
3810		{
3811			struct sctp_authchunk *sauth;
3812
3813			SCTP_CHECK_AND_CAST(sauth, optval, struct sctp_authchunk, optsize);
3814
3815			SCTP_INP_WLOCK(inp);
3816			if (sctp_auth_add_chunk(sauth->sauth_chunk, inp->sctp_ep.local_auth_chunks)) {
3817				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3818				error = EINVAL;
3819			}
3820			SCTP_INP_WUNLOCK(inp);
3821			break;
3822		}
3823	case SCTP_AUTH_KEY:
3824		{
3825			struct sctp_authkey *sca;
3826			struct sctp_keyhead *shared_keys;
3827			sctp_sharedkey_t *shared_key;
3828			sctp_key_t *key = NULL;
3829			size_t size;
3830
3831			SCTP_CHECK_AND_CAST(sca, optval, struct sctp_authkey, optsize);
3832			if (sca->sca_keylength == 0) {
3833				size = optsize - sizeof(struct sctp_authkey);
3834			} else {
3835				if (sca->sca_keylength + sizeof(struct sctp_authkey) <= optsize) {
3836					size = sca->sca_keylength;
3837				} else {
3838					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3839					error = EINVAL;
3840					break;
3841				}
3842			}
3843			SCTP_FIND_STCB(inp, stcb, sca->sca_assoc_id);
3844
3845			if (stcb) {
3846				shared_keys = &stcb->asoc.shared_keys;
3847				/* clear the cached keys for this key id */
3848				sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
3849				/*
3850				 * create the new shared key and
3851				 * insert/replace it
3852				 */
3853				if (size > 0) {
3854					key = sctp_set_key(sca->sca_key, (uint32_t) size);
3855					if (key == NULL) {
3856						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
3857						error = ENOMEM;
3858						SCTP_TCB_UNLOCK(stcb);
3859						break;
3860					}
3861				}
3862				shared_key = sctp_alloc_sharedkey();
3863				if (shared_key == NULL) {
3864					sctp_free_key(key);
3865					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
3866					error = ENOMEM;
3867					SCTP_TCB_UNLOCK(stcb);
3868					break;
3869				}
3870				shared_key->key = key;
3871				shared_key->keyid = sca->sca_keynumber;
3872				error = sctp_insert_sharedkey(shared_keys, shared_key);
3873				SCTP_TCB_UNLOCK(stcb);
3874			} else {
3875				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3876				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3877				    (sca->sca_assoc_id == SCTP_FUTURE_ASSOC) ||
3878				    (sca->sca_assoc_id == SCTP_ALL_ASSOC)) {
3879					SCTP_INP_WLOCK(inp);
3880					shared_keys = &inp->sctp_ep.shared_keys;
3881					/*
3882					 * clear the cached keys on all
3883					 * assocs for this key id
3884					 */
3885					sctp_clear_cachedkeys_ep(inp, sca->sca_keynumber);
3886					/*
3887					 * create the new shared key and
3888					 * insert/replace it
3889					 */
3890					if (size > 0) {
3891						key = sctp_set_key(sca->sca_key, (uint32_t) size);
3892						if (key == NULL) {
3893							SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
3894							error = ENOMEM;
3895							SCTP_INP_WUNLOCK(inp);
3896							break;
3897						}
3898					}
3899					shared_key = sctp_alloc_sharedkey();
3900					if (shared_key == NULL) {
3901						sctp_free_key(key);
3902						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
3903						error = ENOMEM;
3904						SCTP_INP_WUNLOCK(inp);
3905						break;
3906					}
3907					shared_key->key = key;
3908					shared_key->keyid = sca->sca_keynumber;
3909					error = sctp_insert_sharedkey(shared_keys, shared_key);
3910					SCTP_INP_WUNLOCK(inp);
3911				}
3912				if ((sca->sca_assoc_id == SCTP_CURRENT_ASSOC) ||
3913				    (sca->sca_assoc_id == SCTP_ALL_ASSOC)) {
3914					SCTP_INP_RLOCK(inp);
3915					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3916						SCTP_TCB_LOCK(stcb);
3917						shared_keys = &stcb->asoc.shared_keys;
3918						/*
3919						 * clear the cached keys for
3920						 * this key id
3921						 */
3922						sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
3923						/*
3924						 * create the new shared key
3925						 * and insert/replace it
3926						 */
3927						if (size > 0) {
3928							key = sctp_set_key(sca->sca_key, (uint32_t) size);
3929							if (key == NULL) {
3930								SCTP_TCB_UNLOCK(stcb);
3931								continue;
3932							}
3933						}
3934						shared_key = sctp_alloc_sharedkey();
3935						if (shared_key == NULL) {
3936							sctp_free_key(key);
3937							SCTP_TCB_UNLOCK(stcb);
3938							continue;
3939						}
3940						shared_key->key = key;
3941						shared_key->keyid = sca->sca_keynumber;
3942						error = sctp_insert_sharedkey(shared_keys, shared_key);
3943						SCTP_TCB_UNLOCK(stcb);
3944					}
3945					SCTP_INP_RUNLOCK(inp);
3946				}
3947			}
3948			break;
3949		}
3950	case SCTP_HMAC_IDENT:
3951		{
3952			struct sctp_hmacalgo *shmac;
3953			sctp_hmaclist_t *hmaclist;
3954			uint16_t hmacid;
3955			uint32_t i;
3956			size_t found;
3957
3958			SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, optsize);
3959			if (optsize < sizeof(struct sctp_hmacalgo) + shmac->shmac_number_of_idents * sizeof(uint16_t)) {
3960				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3961				error = EINVAL;
3962				break;
3963			}
3964			hmaclist = sctp_alloc_hmaclist(shmac->shmac_number_of_idents);
3965			if (hmaclist == NULL) {
3966				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
3967				error = ENOMEM;
3968				break;
3969			}
3970			for (i = 0; i < shmac->shmac_number_of_idents; i++) {
3971				hmacid = shmac->shmac_idents[i];
3972				if (sctp_auth_add_hmacid(hmaclist, hmacid)) {
3973					 /* invalid HMACs were found */ ;
3974					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3975					error = EINVAL;
3976					sctp_free_hmaclist(hmaclist);
3977					goto sctp_set_hmac_done;
3978				}
3979			}
3980			found = 0;
3981			for (i = 0; i < hmaclist->num_algo; i++) {
3982				if (hmaclist->hmac[i] == SCTP_AUTH_HMAC_ID_SHA1) {
3983					/* already in list */
3984					found = 1;
3985				}
3986			}
3987			if (!found) {
3988				sctp_free_hmaclist(hmaclist);
3989				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3990				error = EINVAL;
3991				break;
3992			}
3993			/* set it on the endpoint */
3994			SCTP_INP_WLOCK(inp);
3995			if (inp->sctp_ep.local_hmacs)
3996				sctp_free_hmaclist(inp->sctp_ep.local_hmacs);
3997			inp->sctp_ep.local_hmacs = hmaclist;
3998			SCTP_INP_WUNLOCK(inp);
3999	sctp_set_hmac_done:
4000			break;
4001		}
4002	case SCTP_AUTH_ACTIVE_KEY:
4003		{
4004			struct sctp_authkeyid *scact;
4005
4006			SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, optsize);
4007			SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id);
4008
4009			/* set the active key on the right place */
4010			if (stcb) {
4011				/* set the active key on the assoc */
4012				if (sctp_auth_setactivekey(stcb,
4013				    scact->scact_keynumber)) {
4014					SCTP_LTRACE_ERR_RET(inp, NULL, NULL,
4015					    SCTP_FROM_SCTP_USRREQ,
4016					    EINVAL);
4017					error = EINVAL;
4018				}
4019				SCTP_TCB_UNLOCK(stcb);
4020			} else {
4021				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4022				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4023				    (scact->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
4024				    (scact->scact_assoc_id == SCTP_ALL_ASSOC)) {
4025					SCTP_INP_WLOCK(inp);
4026					if (sctp_auth_setactivekey_ep(inp, scact->scact_keynumber)) {
4027						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4028						error = EINVAL;
4029					}
4030					SCTP_INP_WUNLOCK(inp);
4031				}
4032				if ((scact->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
4033				    (scact->scact_assoc_id == SCTP_ALL_ASSOC)) {
4034					SCTP_INP_RLOCK(inp);
4035					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4036						SCTP_TCB_LOCK(stcb);
4037						sctp_auth_setactivekey(stcb, scact->scact_keynumber);
4038						SCTP_TCB_UNLOCK(stcb);
4039					}
4040					SCTP_INP_RUNLOCK(inp);
4041				}
4042			}
4043			break;
4044		}
4045	case SCTP_AUTH_DELETE_KEY:
4046		{
4047			struct sctp_authkeyid *scdel;
4048
4049			SCTP_CHECK_AND_CAST(scdel, optval, struct sctp_authkeyid, optsize);
4050			SCTP_FIND_STCB(inp, stcb, scdel->scact_assoc_id);
4051
4052			/* delete the key from the right place */
4053			if (stcb) {
4054				if (sctp_delete_sharedkey(stcb, scdel->scact_keynumber)) {
4055					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4056					error = EINVAL;
4057				}
4058				SCTP_TCB_UNLOCK(stcb);
4059			} else {
4060				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4061				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4062				    (scdel->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
4063				    (scdel->scact_assoc_id == SCTP_ALL_ASSOC)) {
4064					SCTP_INP_WLOCK(inp);
4065					if (sctp_delete_sharedkey_ep(inp, scdel->scact_keynumber)) {
4066						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4067						error = EINVAL;
4068					}
4069					SCTP_INP_WUNLOCK(inp);
4070				}
4071				if ((scdel->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
4072				    (scdel->scact_assoc_id == SCTP_ALL_ASSOC)) {
4073					SCTP_INP_RLOCK(inp);
4074					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4075						SCTP_TCB_LOCK(stcb);
4076						sctp_delete_sharedkey(stcb, scdel->scact_keynumber);
4077						SCTP_TCB_UNLOCK(stcb);
4078					}
4079					SCTP_INP_RUNLOCK(inp);
4080				}
4081			}
4082			break;
4083		}
4084	case SCTP_AUTH_DEACTIVATE_KEY:
4085		{
4086			struct sctp_authkeyid *keyid;
4087
4088			SCTP_CHECK_AND_CAST(keyid, optval, struct sctp_authkeyid, optsize);
4089			SCTP_FIND_STCB(inp, stcb, keyid->scact_assoc_id);
4090
4091			/* deactivate the key from the right place */
4092			if (stcb) {
4093				if (sctp_deact_sharedkey(stcb, keyid->scact_keynumber)) {
4094					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4095					error = EINVAL;
4096				}
4097				SCTP_TCB_UNLOCK(stcb);
4098			} else {
4099				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4100				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4101				    (keyid->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
4102				    (keyid->scact_assoc_id == SCTP_ALL_ASSOC)) {
4103					SCTP_INP_WLOCK(inp);
4104					if (sctp_deact_sharedkey_ep(inp, keyid->scact_keynumber)) {
4105						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4106						error = EINVAL;
4107					}
4108					SCTP_INP_WUNLOCK(inp);
4109				}
4110				if ((keyid->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
4111				    (keyid->scact_assoc_id == SCTP_ALL_ASSOC)) {
4112					SCTP_INP_RLOCK(inp);
4113					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4114						SCTP_TCB_LOCK(stcb);
4115						sctp_deact_sharedkey(stcb, keyid->scact_keynumber);
4116						SCTP_TCB_UNLOCK(stcb);
4117					}
4118					SCTP_INP_RUNLOCK(inp);
4119				}
4120			}
4121			break;
4122		}
4123	case SCTP_ENABLE_STREAM_RESET:
4124		{
4125			struct sctp_assoc_value *av;
4126
4127			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4128			if (av->assoc_value & (~SCTP_ENABLE_VALUE_MASK)) {
4129				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4130				error = EINVAL;
4131				break;
4132			}
4133			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4134			if (stcb) {
4135				stcb->asoc.local_strreset_support = (uint8_t) av->assoc_value;
4136				SCTP_TCB_UNLOCK(stcb);
4137			} else {
4138				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4139				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4140				    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
4141				    (av->assoc_id == SCTP_ALL_ASSOC)) {
4142					SCTP_INP_WLOCK(inp);
4143					inp->local_strreset_support = (uint8_t) av->assoc_value;
4144					SCTP_INP_WUNLOCK(inp);
4145				}
4146				if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4147				    (av->assoc_id == SCTP_ALL_ASSOC)) {
4148					SCTP_INP_RLOCK(inp);
4149					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4150						SCTP_TCB_LOCK(stcb);
4151						stcb->asoc.local_strreset_support = (uint8_t) av->assoc_value;
4152						SCTP_TCB_UNLOCK(stcb);
4153					}
4154					SCTP_INP_RUNLOCK(inp);
4155				}
4156			}
4157			break;
4158		}
4159	case SCTP_RESET_STREAMS:
4160		{
4161			struct sctp_reset_streams *strrst;
4162			int i, send_out = 0;
4163			int send_in = 0;
4164
4165			SCTP_CHECK_AND_CAST(strrst, optval, struct sctp_reset_streams, optsize);
4166			SCTP_FIND_STCB(inp, stcb, strrst->srs_assoc_id);
4167
4168			if (stcb == NULL) {
4169				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4170				error = ENOENT;
4171				break;
4172			}
4173			if (stcb->asoc.peer_supports_strreset == 0) {
4174				/*
4175				 * Peer does not support the chunk type.
4176				 */
4177				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4178				error = EOPNOTSUPP;
4179				SCTP_TCB_UNLOCK(stcb);
4180				break;
4181			}
4182			if (!(stcb->asoc.local_strreset_support & SCTP_ENABLE_RESET_STREAM_REQ)) {
4183				/*
4184				 * User did not enable the operation.
4185				 */
4186				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EPERM);
4187				error = EPERM;
4188				SCTP_TCB_UNLOCK(stcb);
4189				break;
4190			}
4191			if (stcb->asoc.stream_reset_outstanding) {
4192				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4193				error = EALREADY;
4194				SCTP_TCB_UNLOCK(stcb);
4195				break;
4196			}
4197			if (strrst->srs_flags & SCTP_STREAM_RESET_INCOMING) {
4198				send_in = 1;
4199			}
4200			if (strrst->srs_flags & SCTP_STREAM_RESET_OUTGOING) {
4201				send_out = 1;
4202			}
4203			if ((send_in == 0) && (send_out == 0)) {
4204				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4205				error = EINVAL;
4206				SCTP_TCB_UNLOCK(stcb);
4207				break;
4208			}
4209			for (i = 0; i < strrst->srs_number_streams; i++) {
4210				if ((send_in) &&
4211				    (strrst->srs_stream_list[i] > stcb->asoc.streamincnt)) {
4212					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4213					error = EINVAL;
4214					break;
4215				}
4216				if ((send_out) &&
4217				    (strrst->srs_stream_list[i] > stcb->asoc.streamoutcnt)) {
4218					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4219					error = EINVAL;
4220					break;
4221				}
4222			}
4223			if (error) {
4224				SCTP_TCB_UNLOCK(stcb);
4225				break;
4226			}
4227			error = sctp_send_str_reset_req(stcb, strrst->srs_number_streams,
4228			    strrst->srs_stream_list,
4229			    send_out, send_in, 0, 0, 0, 0, 0);
4230
4231			sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
4232			SCTP_TCB_UNLOCK(stcb);
4233			break;
4234		}
4235	case SCTP_ADD_STREAMS:
4236		{
4237			struct sctp_add_streams *stradd;
4238			uint8_t addstream = 0;
4239			uint16_t add_o_strmcnt = 0;
4240			uint16_t add_i_strmcnt = 0;
4241
4242			SCTP_CHECK_AND_CAST(stradd, optval, struct sctp_add_streams, optsize);
4243			SCTP_FIND_STCB(inp, stcb, stradd->sas_assoc_id);
4244			if (stcb == NULL) {
4245				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4246				error = ENOENT;
4247				break;
4248			}
4249			if ((stradd->sas_outstrms == 0) &&
4250			    (stradd->sas_instrms == 0)) {
4251				error = EINVAL;
4252				goto skip_stuff;
4253			}
4254			if (stradd->sas_outstrms) {
4255				addstream = 1;
4256				/* We allocate here */
4257				add_o_strmcnt = stradd->sas_outstrms;
4258				if ((((int)add_o_strmcnt) + ((int)stcb->asoc.streamoutcnt)) > 0x0000ffff) {
4259					/* You can't have more than 64k */
4260					error = EINVAL;
4261					goto skip_stuff;
4262				}
4263			}
4264			if (stradd->sas_instrms) {
4265				int cnt;
4266
4267				addstream |= 2;
4268				/*
4269				 * We allocate inside
4270				 * sctp_send_str_reset_req()
4271				 */
4272				add_i_strmcnt = stradd->sas_instrms;
4273				cnt = add_i_strmcnt;
4274				cnt += stcb->asoc.streamincnt;
4275				if (cnt > 0x0000ffff) {
4276					/* You can't have more than 64k */
4277					error = EINVAL;
4278					goto skip_stuff;
4279				}
4280				if (cnt > (int)stcb->asoc.max_inbound_streams) {
4281					/* More than you are allowed */
4282					error = EINVAL;
4283					goto skip_stuff;
4284				}
4285			}
4286			error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 0, addstream, add_o_strmcnt, add_i_strmcnt, 0);
4287			sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
4288	skip_stuff:
4289			SCTP_TCB_UNLOCK(stcb);
4290			break;
4291		}
4292	case SCTP_RESET_ASSOC:
4293		{
4294			uint32_t *value;
4295
4296			SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
4297			SCTP_FIND_STCB(inp, stcb, (sctp_assoc_t) * value);
4298			if (stcb == NULL) {
4299				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4300				error = ENOENT;
4301				break;
4302			}
4303			if (stcb->asoc.peer_supports_strreset == 0) {
4304				/*
4305				 * Peer does not support the chunk type.
4306				 */
4307				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4308				error = EOPNOTSUPP;
4309				SCTP_TCB_UNLOCK(stcb);
4310				break;
4311			}
4312			if (!(stcb->asoc.local_strreset_support & SCTP_ENABLE_RESET_ASSOC_REQ)) {
4313				/*
4314				 * User did not enable the operation.
4315				 */
4316				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EPERM);
4317				error = EPERM;
4318				SCTP_TCB_UNLOCK(stcb);
4319				break;
4320			}
4321			if (stcb->asoc.stream_reset_outstanding) {
4322				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4323				error = EALREADY;
4324				SCTP_TCB_UNLOCK(stcb);
4325				break;
4326			}
4327			error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 1, 0, 0, 0, 0);
4328			sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
4329			SCTP_TCB_UNLOCK(stcb);
4330			break;
4331		}
4332	case SCTP_CONNECT_X:
4333		if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
4334			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4335			error = EINVAL;
4336			break;
4337		}
4338		error = sctp_do_connect_x(so, inp, optval, optsize, p, 0);
4339		break;
4340	case SCTP_CONNECT_X_DELAYED:
4341		if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
4342			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4343			error = EINVAL;
4344			break;
4345		}
4346		error = sctp_do_connect_x(so, inp, optval, optsize, p, 1);
4347		break;
4348	case SCTP_CONNECT_X_COMPLETE:
4349		{
4350			struct sockaddr *sa;
4351			struct sctp_nets *net;
4352
4353			/* FIXME MT: check correct? */
4354			SCTP_CHECK_AND_CAST(sa, optval, struct sockaddr, optsize);
4355
4356			/* find tcb */
4357			if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
4358				SCTP_INP_RLOCK(inp);
4359				stcb = LIST_FIRST(&inp->sctp_asoc_list);
4360				if (stcb) {
4361					SCTP_TCB_LOCK(stcb);
4362					net = sctp_findnet(stcb, sa);
4363				}
4364				SCTP_INP_RUNLOCK(inp);
4365			} else {
4366				/*
4367				 * We increment here since
4368				 * sctp_findassociation_ep_addr() wil do a
4369				 * decrement if it finds the stcb as long as
4370				 * the locked tcb (last argument) is NOT a
4371				 * TCB.. aka NULL.
4372				 */
4373				SCTP_INP_INCR_REF(inp);
4374				stcb = sctp_findassociation_ep_addr(&inp, sa, &net, NULL, NULL);
4375				if (stcb == NULL) {
4376					SCTP_INP_DECR_REF(inp);
4377				}
4378			}
4379
4380			if (stcb == NULL) {
4381				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4382				error = ENOENT;
4383				break;
4384			}
4385			if (stcb->asoc.delayed_connection == 1) {
4386				stcb->asoc.delayed_connection = 0;
4387				(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
4388				sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb,
4389				    stcb->asoc.primary_destination,
4390				    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_9);
4391				sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
4392			} else {
4393				/*
4394				 * already expired or did not use delayed
4395				 * connectx
4396				 */
4397				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4398				error = EALREADY;
4399			}
4400			SCTP_TCB_UNLOCK(stcb);
4401			break;
4402		}
4403	case SCTP_MAX_BURST:
4404		{
4405			struct sctp_assoc_value *av;
4406
4407			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4408			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4409
4410			if (stcb) {
4411				stcb->asoc.max_burst = av->assoc_value;
4412				SCTP_TCB_UNLOCK(stcb);
4413			} else {
4414				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4415				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4416				    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
4417				    (av->assoc_id == SCTP_ALL_ASSOC)) {
4418					SCTP_INP_WLOCK(inp);
4419					inp->sctp_ep.max_burst = av->assoc_value;
4420					SCTP_INP_WUNLOCK(inp);
4421				}
4422				if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4423				    (av->assoc_id == SCTP_ALL_ASSOC)) {
4424					SCTP_INP_RLOCK(inp);
4425					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4426						SCTP_TCB_LOCK(stcb);
4427						stcb->asoc.max_burst = av->assoc_value;
4428						SCTP_TCB_UNLOCK(stcb);
4429					}
4430					SCTP_INP_RUNLOCK(inp);
4431				}
4432			}
4433			break;
4434		}
4435	case SCTP_MAXSEG:
4436		{
4437			struct sctp_assoc_value *av;
4438			int ovh;
4439
4440			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4441			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4442
4443			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
4444				ovh = SCTP_MED_OVERHEAD;
4445			} else {
4446				ovh = SCTP_MED_V4_OVERHEAD;
4447			}
4448			if (stcb) {
4449				if (av->assoc_value) {
4450					stcb->asoc.sctp_frag_point = (av->assoc_value + ovh);
4451				} else {
4452					stcb->asoc.sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
4453				}
4454				SCTP_TCB_UNLOCK(stcb);
4455			} else {
4456				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4457				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4458				    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
4459					SCTP_INP_WLOCK(inp);
4460					/*
4461					 * FIXME MT: I think this is not in
4462					 * tune with the API ID
4463					 */
4464					if (av->assoc_value) {
4465						inp->sctp_frag_point = (av->assoc_value + ovh);
4466					} else {
4467						inp->sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
4468					}
4469					SCTP_INP_WUNLOCK(inp);
4470				} else {
4471					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4472					error = EINVAL;
4473				}
4474			}
4475			break;
4476		}
4477	case SCTP_EVENTS:
4478		{
4479			struct sctp_event_subscribe *events;
4480
4481			SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, optsize);
4482
4483			SCTP_INP_WLOCK(inp);
4484			if (events->sctp_data_io_event) {
4485				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
4486			} else {
4487				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
4488			}
4489
4490			if (events->sctp_association_event) {
4491				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
4492			} else {
4493				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
4494			}
4495
4496			if (events->sctp_address_event) {
4497				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
4498			} else {
4499				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
4500			}
4501
4502			if (events->sctp_send_failure_event) {
4503				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
4504			} else {
4505				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
4506			}
4507
4508			if (events->sctp_peer_error_event) {
4509				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPEERERR);
4510			} else {
4511				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPEERERR);
4512			}
4513
4514			if (events->sctp_shutdown_event) {
4515				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
4516			} else {
4517				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
4518			}
4519
4520			if (events->sctp_partial_delivery_event) {
4521				sctp_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
4522			} else {
4523				sctp_feature_off(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
4524			}
4525
4526			if (events->sctp_adaptation_layer_event) {
4527				sctp_feature_on(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
4528			} else {
4529				sctp_feature_off(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
4530			}
4531
4532			if (events->sctp_authentication_event) {
4533				sctp_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT);
4534			} else {
4535				sctp_feature_off(inp, SCTP_PCB_FLAGS_AUTHEVNT);
4536			}
4537
4538			if (events->sctp_sender_dry_event) {
4539				sctp_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT);
4540			} else {
4541				sctp_feature_off(inp, SCTP_PCB_FLAGS_DRYEVNT);
4542			}
4543
4544			if (events->sctp_stream_reset_event) {
4545				sctp_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
4546			} else {
4547				sctp_feature_off(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
4548			}
4549			SCTP_INP_WUNLOCK(inp);
4550
4551			SCTP_INP_RLOCK(inp);
4552			LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4553				SCTP_TCB_LOCK(stcb);
4554				if (events->sctp_association_event) {
4555					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
4556				} else {
4557					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
4558				}
4559				if (events->sctp_address_event) {
4560					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
4561				} else {
4562					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
4563				}
4564				if (events->sctp_send_failure_event) {
4565					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
4566				} else {
4567					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
4568				}
4569				if (events->sctp_peer_error_event) {
4570					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
4571				} else {
4572					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
4573				}
4574				if (events->sctp_shutdown_event) {
4575					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
4576				} else {
4577					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
4578				}
4579				if (events->sctp_partial_delivery_event) {
4580					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
4581				} else {
4582					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
4583				}
4584				if (events->sctp_adaptation_layer_event) {
4585					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
4586				} else {
4587					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
4588				}
4589				if (events->sctp_authentication_event) {
4590					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
4591				} else {
4592					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
4593				}
4594				if (events->sctp_sender_dry_event) {
4595					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
4596				} else {
4597					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
4598				}
4599				if (events->sctp_stream_reset_event) {
4600					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
4601				} else {
4602					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
4603				}
4604				SCTP_TCB_UNLOCK(stcb);
4605			}
4606			/*
4607			 * Send up the sender dry event only for 1-to-1
4608			 * style sockets.
4609			 */
4610			if (events->sctp_sender_dry_event) {
4611				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4612				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
4613					stcb = LIST_FIRST(&inp->sctp_asoc_list);
4614					if (stcb) {
4615						SCTP_TCB_LOCK(stcb);
4616						if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
4617						    TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
4618						    (stcb->asoc.stream_queue_cnt == 0)) {
4619							sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_LOCKED);
4620						}
4621						SCTP_TCB_UNLOCK(stcb);
4622					}
4623				}
4624			}
4625			SCTP_INP_RUNLOCK(inp);
4626			break;
4627		}
4628	case SCTP_ADAPTATION_LAYER:
4629		{
4630			struct sctp_setadaptation *adap_bits;
4631
4632			SCTP_CHECK_AND_CAST(adap_bits, optval, struct sctp_setadaptation, optsize);
4633			SCTP_INP_WLOCK(inp);
4634			inp->sctp_ep.adaptation_layer_indicator = adap_bits->ssb_adaptation_ind;
4635			SCTP_INP_WUNLOCK(inp);
4636			break;
4637		}
4638#ifdef SCTP_DEBUG
4639	case SCTP_SET_INITIAL_DBG_SEQ:
4640		{
4641			uint32_t *vvv;
4642
4643			SCTP_CHECK_AND_CAST(vvv, optval, uint32_t, optsize);
4644			SCTP_INP_WLOCK(inp);
4645			inp->sctp_ep.initial_sequence_debug = *vvv;
4646			SCTP_INP_WUNLOCK(inp);
4647			break;
4648		}
4649#endif
4650	case SCTP_DEFAULT_SEND_PARAM:
4651		{
4652			struct sctp_sndrcvinfo *s_info;
4653
4654			SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, optsize);
4655			SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
4656
4657			if (stcb) {
4658				if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
4659					memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
4660				} else {
4661					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4662					error = EINVAL;
4663				}
4664				SCTP_TCB_UNLOCK(stcb);
4665			} else {
4666				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4667				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4668				    (s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC) ||
4669				    (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)) {
4670					SCTP_INP_WLOCK(inp);
4671					memcpy(&inp->def_send, s_info, min(optsize, sizeof(inp->def_send)));
4672					SCTP_INP_WUNLOCK(inp);
4673				}
4674				if ((s_info->sinfo_assoc_id == SCTP_CURRENT_ASSOC) ||
4675				    (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)) {
4676					SCTP_INP_RLOCK(inp);
4677					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4678						SCTP_TCB_LOCK(stcb);
4679						if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
4680							memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
4681						}
4682						SCTP_TCB_UNLOCK(stcb);
4683					}
4684					SCTP_INP_RUNLOCK(inp);
4685				}
4686			}
4687			break;
4688		}
4689	case SCTP_PEER_ADDR_PARAMS:
4690		{
4691			struct sctp_paddrparams *paddrp;
4692			struct sctp_nets *net;
4693
4694			SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, optsize);
4695			SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
4696			net = NULL;
4697			if (stcb) {
4698				net = sctp_findnet(stcb, (struct sockaddr *)&paddrp->spp_address);
4699			} else {
4700				/*
4701				 * We increment here since
4702				 * sctp_findassociation_ep_addr() wil do a
4703				 * decrement if it finds the stcb as long as
4704				 * the locked tcb (last argument) is NOT a
4705				 * TCB.. aka NULL.
4706				 */
4707				SCTP_INP_INCR_REF(inp);
4708				stcb = sctp_findassociation_ep_addr(&inp,
4709				    (struct sockaddr *)&paddrp->spp_address,
4710				    &net, NULL, NULL);
4711				if (stcb == NULL) {
4712					SCTP_INP_DECR_REF(inp);
4713				}
4714			}
4715			if (stcb && (net == NULL)) {
4716				struct sockaddr *sa;
4717
4718				sa = (struct sockaddr *)&paddrp->spp_address;
4719#ifdef INET
4720				if (sa->sa_family == AF_INET) {
4721
4722					struct sockaddr_in *sin;
4723
4724					sin = (struct sockaddr_in *)sa;
4725					if (sin->sin_addr.s_addr) {
4726						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4727						SCTP_TCB_UNLOCK(stcb);
4728						error = EINVAL;
4729						break;
4730					}
4731				} else
4732#endif
4733#ifdef INET6
4734				if (sa->sa_family == AF_INET6) {
4735					struct sockaddr_in6 *sin6;
4736
4737					sin6 = (struct sockaddr_in6 *)sa;
4738					if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
4739						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4740						SCTP_TCB_UNLOCK(stcb);
4741						error = EINVAL;
4742						break;
4743					}
4744				} else
4745#endif
4746				{
4747					error = EAFNOSUPPORT;
4748					SCTP_TCB_UNLOCK(stcb);
4749					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
4750					break;
4751				}
4752			}
4753			/* sanity checks */
4754			if ((paddrp->spp_flags & SPP_HB_ENABLE) && (paddrp->spp_flags & SPP_HB_DISABLE)) {
4755				if (stcb)
4756					SCTP_TCB_UNLOCK(stcb);
4757				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4758				return (EINVAL);
4759			}
4760			if ((paddrp->spp_flags & SPP_PMTUD_ENABLE) && (paddrp->spp_flags & SPP_PMTUD_DISABLE)) {
4761				if (stcb)
4762					SCTP_TCB_UNLOCK(stcb);
4763				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4764				return (EINVAL);
4765			}
4766			if (stcb) {
4767				/************************TCB SPECIFIC SET ******************/
4768				/*
4769				 * do we change the timer for HB, we run
4770				 * only one?
4771				 */
4772				int ovh = 0;
4773
4774				if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
4775					ovh = SCTP_MED_OVERHEAD;
4776				} else {
4777					ovh = SCTP_MED_V4_OVERHEAD;
4778				}
4779
4780				/* network sets ? */
4781				if (net) {
4782					/************************NET SPECIFIC SET ******************/
4783					if (paddrp->spp_flags & SPP_HB_DISABLE) {
4784						if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
4785						    !(net->dest_state & SCTP_ADDR_NOHB)) {
4786							sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
4787							    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
4788						}
4789						net->dest_state |= SCTP_ADDR_NOHB;
4790					}
4791					if (paddrp->spp_flags & SPP_HB_ENABLE) {
4792						if (paddrp->spp_hbinterval) {
4793							net->heart_beat_delay = paddrp->spp_hbinterval;
4794						} else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
4795							net->heart_beat_delay = 0;
4796						}
4797						sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
4798						    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
4799						sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
4800						net->dest_state &= ~SCTP_ADDR_NOHB;
4801					}
4802					if (paddrp->spp_flags & SPP_HB_DEMAND) {
4803						/* on demand HB */
4804						sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
4805						sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED);
4806						sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
4807					}
4808					if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
4809						if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
4810							sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
4811							    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
4812						}
4813						net->dest_state |= SCTP_ADDR_NO_PMTUD;
4814						if (paddrp->spp_pathmtu > SCTP_DEFAULT_MINSEGMENT) {
4815							net->mtu = paddrp->spp_pathmtu + ovh;
4816							if (net->mtu < stcb->asoc.smallest_mtu) {
4817								sctp_pathmtu_adjustment(stcb, net->mtu);
4818							}
4819						}
4820					}
4821					if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
4822						if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
4823							sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
4824						}
4825						net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
4826					}
4827					if (paddrp->spp_pathmaxrxt) {
4828						if (net->dest_state & SCTP_ADDR_PF) {
4829							if (net->error_count > paddrp->spp_pathmaxrxt) {
4830								net->dest_state &= ~SCTP_ADDR_PF;
4831							}
4832						} else {
4833							if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
4834							    (net->error_count > net->pf_threshold)) {
4835								net->dest_state |= SCTP_ADDR_PF;
4836								sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
4837								sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
4838								sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
4839							}
4840						}
4841						if (net->dest_state & SCTP_ADDR_REACHABLE) {
4842							if (net->error_count > paddrp->spp_pathmaxrxt) {
4843								net->dest_state &= ~SCTP_ADDR_REACHABLE;
4844								sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, SCTP_RESPONSE_TO_USER_REQ, net, SCTP_SO_LOCKED);
4845							}
4846						} else {
4847							if (net->error_count <= paddrp->spp_pathmaxrxt) {
4848								net->dest_state |= SCTP_ADDR_REACHABLE;
4849								sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, SCTP_RESPONSE_TO_USER_REQ, net, SCTP_SO_LOCKED);
4850							}
4851						}
4852						net->failure_threshold = paddrp->spp_pathmaxrxt;
4853					}
4854					if (paddrp->spp_flags & SPP_DSCP) {
4855						net->dscp = paddrp->spp_dscp & 0xfc;
4856						net->dscp |= 0x01;
4857					}
4858#ifdef INET6
4859					if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
4860						if (net->ro._l_addr.sa.sa_family == AF_INET6) {
4861							net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
4862							net->flowlabel |= 0x80000000;
4863						}
4864					}
4865#endif
4866				} else {
4867					/************************ASSOC ONLY -- NO NET SPECIFIC SET ******************/
4868					if (paddrp->spp_pathmaxrxt) {
4869						stcb->asoc.def_net_failure = paddrp->spp_pathmaxrxt;
4870						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4871							if (net->dest_state & SCTP_ADDR_PF) {
4872								if (net->error_count > paddrp->spp_pathmaxrxt) {
4873									net->dest_state &= ~SCTP_ADDR_PF;
4874								}
4875							} else {
4876								if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
4877								    (net->error_count > net->pf_threshold)) {
4878									net->dest_state |= SCTP_ADDR_PF;
4879									sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
4880									sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
4881									sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
4882								}
4883							}
4884							if (net->dest_state & SCTP_ADDR_REACHABLE) {
4885								if (net->error_count > paddrp->spp_pathmaxrxt) {
4886									net->dest_state &= ~SCTP_ADDR_REACHABLE;
4887									sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, SCTP_RESPONSE_TO_USER_REQ, net, SCTP_SO_LOCKED);
4888								}
4889							} else {
4890								if (net->error_count <= paddrp->spp_pathmaxrxt) {
4891									net->dest_state |= SCTP_ADDR_REACHABLE;
4892									sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, SCTP_RESPONSE_TO_USER_REQ, net, SCTP_SO_LOCKED);
4893								}
4894							}
4895							net->failure_threshold = paddrp->spp_pathmaxrxt;
4896						}
4897					}
4898					if (paddrp->spp_flags & SPP_HB_ENABLE) {
4899						if (paddrp->spp_hbinterval) {
4900							stcb->asoc.heart_beat_delay = paddrp->spp_hbinterval;
4901						} else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
4902							stcb->asoc.heart_beat_delay = 0;
4903						}
4904						/* Turn back on the timer */
4905						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4906							if (paddrp->spp_hbinterval) {
4907								net->heart_beat_delay = paddrp->spp_hbinterval;
4908							} else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
4909								net->heart_beat_delay = 0;
4910							}
4911							if (net->dest_state & SCTP_ADDR_NOHB) {
4912								net->dest_state &= ~SCTP_ADDR_NOHB;
4913							}
4914							sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
4915							    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
4916							sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
4917						}
4918						sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
4919					}
4920					if (paddrp->spp_flags & SPP_HB_DISABLE) {
4921						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4922							if (!(net->dest_state & SCTP_ADDR_NOHB)) {
4923								net->dest_state |= SCTP_ADDR_NOHB;
4924								if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED)) {
4925									sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
4926								}
4927							}
4928						}
4929						sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
4930					}
4931					if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
4932						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4933							if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
4934								sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
4935								    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
4936							}
4937							net->dest_state |= SCTP_ADDR_NO_PMTUD;
4938							if (paddrp->spp_pathmtu > SCTP_DEFAULT_MINSEGMENT) {
4939								net->mtu = paddrp->spp_pathmtu + ovh;
4940								if (net->mtu < stcb->asoc.smallest_mtu) {
4941									sctp_pathmtu_adjustment(stcb, net->mtu);
4942								}
4943							}
4944						}
4945						sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
4946					}
4947					if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
4948						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4949							if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
4950								sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
4951							}
4952							net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
4953						}
4954						sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
4955					}
4956					if (paddrp->spp_flags & SPP_DSCP) {
4957						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4958							net->dscp = paddrp->spp_dscp & 0xfc;
4959							net->dscp |= 0x01;
4960						}
4961						stcb->asoc.default_dscp = paddrp->spp_dscp & 0xfc;
4962						stcb->asoc.default_dscp |= 0x01;
4963					}
4964#ifdef INET6
4965					if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
4966						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4967							if (net->ro._l_addr.sa.sa_family == AF_INET6) {
4968								net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
4969								net->flowlabel |= 0x80000000;
4970							}
4971						}
4972						stcb->asoc.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
4973						stcb->asoc.default_flowlabel |= 0x80000000;
4974					}
4975#endif
4976				}
4977				SCTP_TCB_UNLOCK(stcb);
4978			} else {
4979				/************************NO TCB, SET TO default stuff ******************/
4980				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4981				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4982				    (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC)) {
4983					SCTP_INP_WLOCK(inp);
4984					/*
4985					 * For the TOS/FLOWLABEL stuff you
4986					 * set it with the options on the
4987					 * socket
4988					 */
4989					if (paddrp->spp_pathmaxrxt) {
4990						inp->sctp_ep.def_net_failure = paddrp->spp_pathmaxrxt;
4991					}
4992					if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO)
4993						inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
4994					else if (paddrp->spp_hbinterval) {
4995						if (paddrp->spp_hbinterval > SCTP_MAX_HB_INTERVAL)
4996							paddrp->spp_hbinterval = SCTP_MAX_HB_INTERVAL;
4997						inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
4998					}
4999					if (paddrp->spp_flags & SPP_HB_ENABLE) {
5000						if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
5001							inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
5002						} else if (paddrp->spp_hbinterval) {
5003							inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
5004						}
5005						sctp_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5006					} else if (paddrp->spp_flags & SPP_HB_DISABLE) {
5007						sctp_feature_on(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5008					}
5009					if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
5010						sctp_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5011					} else if (paddrp->spp_flags & SPP_PMTUD_DISABLE) {
5012						sctp_feature_on(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5013					}
5014					if (paddrp->spp_flags & SPP_DSCP) {
5015						inp->sctp_ep.default_dscp = paddrp->spp_dscp & 0xfc;
5016						inp->sctp_ep.default_dscp |= 0x01;
5017					}
5018#ifdef INET6
5019					if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
5020						if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
5021							inp->sctp_ep.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5022							inp->sctp_ep.default_flowlabel |= 0x80000000;
5023						}
5024					}
5025#endif
5026					SCTP_INP_WUNLOCK(inp);
5027				} else {
5028					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5029					error = EINVAL;
5030				}
5031			}
5032			break;
5033		}
5034	case SCTP_RTOINFO:
5035		{
5036			struct sctp_rtoinfo *srto;
5037			uint32_t new_init, new_min, new_max;
5038
5039			SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, optsize);
5040			SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
5041
5042			if (stcb) {
5043				if (srto->srto_initial)
5044					new_init = srto->srto_initial;
5045				else
5046					new_init = stcb->asoc.initial_rto;
5047				if (srto->srto_max)
5048					new_max = srto->srto_max;
5049				else
5050					new_max = stcb->asoc.maxrto;
5051				if (srto->srto_min)
5052					new_min = srto->srto_min;
5053				else
5054					new_min = stcb->asoc.minrto;
5055				if ((new_min <= new_init) && (new_init <= new_max)) {
5056					stcb->asoc.initial_rto = new_init;
5057					stcb->asoc.maxrto = new_max;
5058					stcb->asoc.minrto = new_min;
5059				} else {
5060					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5061					error = EINVAL;
5062				}
5063				SCTP_TCB_UNLOCK(stcb);
5064			} else {
5065				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5066				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5067				    (srto->srto_assoc_id == SCTP_FUTURE_ASSOC)) {
5068					SCTP_INP_WLOCK(inp);
5069					if (srto->srto_initial)
5070						new_init = srto->srto_initial;
5071					else
5072						new_init = inp->sctp_ep.initial_rto;
5073					if (srto->srto_max)
5074						new_max = srto->srto_max;
5075					else
5076						new_max = inp->sctp_ep.sctp_maxrto;
5077					if (srto->srto_min)
5078						new_min = srto->srto_min;
5079					else
5080						new_min = inp->sctp_ep.sctp_minrto;
5081					if ((new_min <= new_init) && (new_init <= new_max)) {
5082						inp->sctp_ep.initial_rto = new_init;
5083						inp->sctp_ep.sctp_maxrto = new_max;
5084						inp->sctp_ep.sctp_minrto = new_min;
5085					} else {
5086						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5087						error = EINVAL;
5088					}
5089					SCTP_INP_WUNLOCK(inp);
5090				} else {
5091					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5092					error = EINVAL;
5093				}
5094			}
5095			break;
5096		}
5097	case SCTP_ASSOCINFO:
5098		{
5099			struct sctp_assocparams *sasoc;
5100
5101			SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, optsize);
5102			SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
5103			if (sasoc->sasoc_cookie_life) {
5104				/* boundary check the cookie life */
5105				if (sasoc->sasoc_cookie_life < 1000)
5106					sasoc->sasoc_cookie_life = 1000;
5107				if (sasoc->sasoc_cookie_life > SCTP_MAX_COOKIE_LIFE) {
5108					sasoc->sasoc_cookie_life = SCTP_MAX_COOKIE_LIFE;
5109				}
5110			}
5111			if (stcb) {
5112				if (sasoc->sasoc_asocmaxrxt)
5113					stcb->asoc.max_send_times = sasoc->sasoc_asocmaxrxt;
5114				if (sasoc->sasoc_cookie_life) {
5115					stcb->asoc.cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
5116				}
5117				SCTP_TCB_UNLOCK(stcb);
5118			} else {
5119				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5120				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5121				    (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC)) {
5122					SCTP_INP_WLOCK(inp);
5123					if (sasoc->sasoc_asocmaxrxt)
5124						inp->sctp_ep.max_send_times = sasoc->sasoc_asocmaxrxt;
5125					if (sasoc->sasoc_cookie_life) {
5126						inp->sctp_ep.def_cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
5127					}
5128					SCTP_INP_WUNLOCK(inp);
5129				} else {
5130					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5131					error = EINVAL;
5132				}
5133			}
5134			break;
5135		}
5136	case SCTP_INITMSG:
5137		{
5138			struct sctp_initmsg *sinit;
5139
5140			SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, optsize);
5141			SCTP_INP_WLOCK(inp);
5142			if (sinit->sinit_num_ostreams)
5143				inp->sctp_ep.pre_open_stream_count = sinit->sinit_num_ostreams;
5144
5145			if (sinit->sinit_max_instreams)
5146				inp->sctp_ep.max_open_streams_intome = sinit->sinit_max_instreams;
5147
5148			if (sinit->sinit_max_attempts)
5149				inp->sctp_ep.max_init_times = sinit->sinit_max_attempts;
5150
5151			if (sinit->sinit_max_init_timeo)
5152				inp->sctp_ep.initial_init_rto_max = sinit->sinit_max_init_timeo;
5153			SCTP_INP_WUNLOCK(inp);
5154			break;
5155		}
5156	case SCTP_PRIMARY_ADDR:
5157		{
5158			struct sctp_setprim *spa;
5159			struct sctp_nets *net;
5160
5161			SCTP_CHECK_AND_CAST(spa, optval, struct sctp_setprim, optsize);
5162			SCTP_FIND_STCB(inp, stcb, spa->ssp_assoc_id);
5163
5164			net = NULL;
5165			if (stcb) {
5166				net = sctp_findnet(stcb, (struct sockaddr *)&spa->ssp_addr);
5167			} else {
5168				/*
5169				 * We increment here since
5170				 * sctp_findassociation_ep_addr() wil do a
5171				 * decrement if it finds the stcb as long as
5172				 * the locked tcb (last argument) is NOT a
5173				 * TCB.. aka NULL.
5174				 */
5175				SCTP_INP_INCR_REF(inp);
5176				stcb = sctp_findassociation_ep_addr(&inp,
5177				    (struct sockaddr *)&spa->ssp_addr,
5178				    &net, NULL, NULL);
5179				if (stcb == NULL) {
5180					SCTP_INP_DECR_REF(inp);
5181				}
5182			}
5183
5184			if ((stcb) && (net)) {
5185				if ((net != stcb->asoc.primary_destination) &&
5186				    (!(net->dest_state & SCTP_ADDR_UNCONFIRMED))) {
5187					/* Ok we need to set it */
5188					if (sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net) == 0) {
5189						if ((stcb->asoc.alternate) &&
5190						    (!(net->dest_state & SCTP_ADDR_PF)) &&
5191						    (net->dest_state & SCTP_ADDR_REACHABLE)) {
5192							sctp_free_remote_addr(stcb->asoc.alternate);
5193							stcb->asoc.alternate = NULL;
5194						}
5195					}
5196				}
5197			} else {
5198				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5199				error = EINVAL;
5200			}
5201			if (stcb) {
5202				SCTP_TCB_UNLOCK(stcb);
5203			}
5204			break;
5205		}
5206	case SCTP_SET_DYNAMIC_PRIMARY:
5207		{
5208			union sctp_sockstore *ss;
5209
5210			error = priv_check(curthread,
5211			    PRIV_NETINET_RESERVEDPORT);
5212			if (error)
5213				break;
5214
5215			SCTP_CHECK_AND_CAST(ss, optval, union sctp_sockstore, optsize);
5216			/* SUPER USER CHECK? */
5217			error = sctp_dynamic_set_primary(&ss->sa, vrf_id);
5218			break;
5219		}
5220	case SCTP_SET_PEER_PRIMARY_ADDR:
5221		{
5222			struct sctp_setpeerprim *sspp;
5223
5224			SCTP_CHECK_AND_CAST(sspp, optval, struct sctp_setpeerprim, optsize);
5225			SCTP_FIND_STCB(inp, stcb, sspp->sspp_assoc_id);
5226			if (stcb != NULL) {
5227				struct sctp_ifa *ifa;
5228
5229				ifa = sctp_find_ifa_by_addr((struct sockaddr *)&sspp->sspp_addr,
5230				    stcb->asoc.vrf_id, SCTP_ADDR_NOT_LOCKED);
5231				if (ifa == NULL) {
5232					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5233					error = EINVAL;
5234					goto out_of_it;
5235				}
5236				if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
5237					/*
5238					 * Must validate the ifa found is in
5239					 * our ep
5240					 */
5241					struct sctp_laddr *laddr;
5242					int found = 0;
5243
5244					LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
5245						if (laddr->ifa == NULL) {
5246							SCTPDBG(SCTP_DEBUG_OUTPUT1, "%s: NULL ifa\n",
5247							    __FUNCTION__);
5248							continue;
5249						}
5250						if (laddr->ifa == ifa) {
5251							found = 1;
5252							break;
5253						}
5254					}
5255					if (!found) {
5256						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5257						error = EINVAL;
5258						goto out_of_it;
5259					}
5260				}
5261				if (sctp_set_primary_ip_address_sa(stcb,
5262				    (struct sockaddr *)&sspp->sspp_addr) != 0) {
5263					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5264					error = EINVAL;
5265				}
5266		out_of_it:
5267				SCTP_TCB_UNLOCK(stcb);
5268			} else {
5269				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5270				error = EINVAL;
5271			}
5272			break;
5273		}
5274	case SCTP_BINDX_ADD_ADDR:
5275		{
5276			struct sctp_getaddresses *addrs;
5277			size_t sz;
5278			struct thread *td;
5279
5280			td = (struct thread *)p;
5281			SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses,
5282			    optsize);
5283#ifdef INET
5284			if (addrs->addr->sa_family == AF_INET) {
5285				sz = sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in);
5286				if (optsize < sz) {
5287					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5288					error = EINVAL;
5289					break;
5290				}
5291				if (td != NULL && (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)(addrs->addr))->sin_addr)))) {
5292					SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
5293					break;
5294				}
5295			} else
5296#endif
5297#ifdef INET6
5298			if (addrs->addr->sa_family == AF_INET6) {
5299				sz = sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6);
5300				if (optsize < sz) {
5301					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5302					error = EINVAL;
5303					break;
5304				}
5305				if (td != NULL && (error = prison_local_ip6(td->td_ucred, &(((struct sockaddr_in6 *)(addrs->addr))->sin6_addr),
5306				    (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
5307					SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
5308					break;
5309				}
5310			} else
5311#endif
5312			{
5313				error = EAFNOSUPPORT;
5314				break;
5315			}
5316			sctp_bindx_add_address(so, inp, addrs->addr,
5317			    addrs->sget_assoc_id, vrf_id,
5318			    &error, p);
5319			break;
5320		}
5321	case SCTP_BINDX_REM_ADDR:
5322		{
5323			struct sctp_getaddresses *addrs;
5324			size_t sz;
5325			struct thread *td;
5326
5327			td = (struct thread *)p;
5328
5329			SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses, optsize);
5330#ifdef INET
5331			if (addrs->addr->sa_family == AF_INET) {
5332				sz = sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in);
5333				if (optsize < sz) {
5334					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5335					error = EINVAL;
5336					break;
5337				}
5338				if (td != NULL && (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)(addrs->addr))->sin_addr)))) {
5339					SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
5340					break;
5341				}
5342			} else
5343#endif
5344#ifdef INET6
5345			if (addrs->addr->sa_family == AF_INET6) {
5346				sz = sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6);
5347				if (optsize < sz) {
5348					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5349					error = EINVAL;
5350					break;
5351				}
5352				if (td != NULL &&
5353				    (error = prison_local_ip6(td->td_ucred,
5354				    &(((struct sockaddr_in6 *)(addrs->addr))->sin6_addr),
5355				    (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
5356					SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
5357					break;
5358				}
5359			} else
5360#endif
5361			{
5362				error = EAFNOSUPPORT;
5363				break;
5364			}
5365			sctp_bindx_delete_address(inp, addrs->addr,
5366			    addrs->sget_assoc_id, vrf_id,
5367			    &error);
5368			break;
5369		}
5370	case SCTP_EVENT:
5371		{
5372			struct sctp_event *event;
5373			uint32_t event_type;
5374
5375			SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, optsize);
5376			SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
5377			switch (event->se_type) {
5378			case SCTP_ASSOC_CHANGE:
5379				event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
5380				break;
5381			case SCTP_PEER_ADDR_CHANGE:
5382				event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
5383				break;
5384			case SCTP_REMOTE_ERROR:
5385				event_type = SCTP_PCB_FLAGS_RECVPEERERR;
5386				break;
5387			case SCTP_SEND_FAILED:
5388				event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
5389				break;
5390			case SCTP_SHUTDOWN_EVENT:
5391				event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
5392				break;
5393			case SCTP_ADAPTATION_INDICATION:
5394				event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
5395				break;
5396			case SCTP_PARTIAL_DELIVERY_EVENT:
5397				event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
5398				break;
5399			case SCTP_AUTHENTICATION_EVENT:
5400				event_type = SCTP_PCB_FLAGS_AUTHEVNT;
5401				break;
5402			case SCTP_STREAM_RESET_EVENT:
5403				event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
5404				break;
5405			case SCTP_SENDER_DRY_EVENT:
5406				event_type = SCTP_PCB_FLAGS_DRYEVNT;
5407				break;
5408			case SCTP_NOTIFICATIONS_STOPPED_EVENT:
5409				event_type = 0;
5410				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
5411				error = ENOTSUP;
5412				break;
5413			case SCTP_ASSOC_RESET_EVENT:
5414				event_type = SCTP_PCB_FLAGS_ASSOC_RESETEVNT;
5415				break;
5416			case SCTP_STREAM_CHANGE_EVENT:
5417				event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT;
5418				break;
5419			default:
5420				event_type = 0;
5421				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5422				error = EINVAL;
5423				break;
5424			}
5425			if (event_type > 0) {
5426				if (stcb) {
5427					if (event->se_on) {
5428						sctp_stcb_feature_on(inp, stcb, event_type);
5429						if (event_type == SCTP_PCB_FLAGS_DRYEVNT) {
5430							if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
5431							    TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
5432							    (stcb->asoc.stream_queue_cnt == 0)) {
5433								sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_LOCKED);
5434							}
5435						}
5436					} else {
5437						sctp_stcb_feature_off(inp, stcb, event_type);
5438					}
5439					SCTP_TCB_UNLOCK(stcb);
5440				} else {
5441					/*
5442					 * We don't want to send up a storm
5443					 * of events, so return an error for
5444					 * sender dry events
5445					 */
5446					if ((event_type == SCTP_PCB_FLAGS_DRYEVNT) &&
5447					    ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) == 0) &&
5448					    ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
5449					    ((event->se_assoc_id == SCTP_ALL_ASSOC) ||
5450					    (event->se_assoc_id == SCTP_CURRENT_ASSOC))) {
5451						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
5452						error = ENOTSUP;
5453						break;
5454					}
5455					if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5456					    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5457					    (event->se_assoc_id == SCTP_FUTURE_ASSOC) ||
5458					    (event->se_assoc_id == SCTP_ALL_ASSOC)) {
5459						SCTP_INP_WLOCK(inp);
5460						if (event->se_on) {
5461							sctp_feature_on(inp, event_type);
5462						} else {
5463							sctp_feature_off(inp, event_type);
5464						}
5465						SCTP_INP_WUNLOCK(inp);
5466					}
5467					if ((event->se_assoc_id == SCTP_CURRENT_ASSOC) ||
5468					    (event->se_assoc_id == SCTP_ALL_ASSOC)) {
5469						SCTP_INP_RLOCK(inp);
5470						LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5471							SCTP_TCB_LOCK(stcb);
5472							if (event->se_on) {
5473								sctp_stcb_feature_on(inp, stcb, event_type);
5474							} else {
5475								sctp_stcb_feature_off(inp, stcb, event_type);
5476							}
5477							SCTP_TCB_UNLOCK(stcb);
5478						}
5479						SCTP_INP_RUNLOCK(inp);
5480					}
5481				}
5482			}
5483			break;
5484		}
5485	case SCTP_RECVRCVINFO:
5486		{
5487			int *onoff;
5488
5489			SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
5490			SCTP_INP_WLOCK(inp);
5491			if (*onoff != 0) {
5492				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
5493			} else {
5494				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
5495			}
5496			SCTP_INP_WUNLOCK(inp);
5497			break;
5498		}
5499	case SCTP_RECVNXTINFO:
5500		{
5501			int *onoff;
5502
5503			SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
5504			SCTP_INP_WLOCK(inp);
5505			if (*onoff != 0) {
5506				sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
5507			} else {
5508				sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
5509			}
5510			SCTP_INP_WUNLOCK(inp);
5511			break;
5512		}
5513	case SCTP_DEFAULT_SNDINFO:
5514		{
5515			struct sctp_sndinfo *info;
5516			uint16_t policy;
5517
5518			SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, optsize);
5519			SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
5520
5521			if (stcb) {
5522				if (info->snd_sid < stcb->asoc.streamoutcnt) {
5523					stcb->asoc.def_send.sinfo_stream = info->snd_sid;
5524					policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
5525					stcb->asoc.def_send.sinfo_flags = info->snd_flags;
5526					stcb->asoc.def_send.sinfo_flags |= policy;
5527					stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
5528					stcb->asoc.def_send.sinfo_context = info->snd_context;
5529				} else {
5530					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5531					error = EINVAL;
5532				}
5533				SCTP_TCB_UNLOCK(stcb);
5534			} else {
5535				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5536				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5537				    (info->snd_assoc_id == SCTP_FUTURE_ASSOC) ||
5538				    (info->snd_assoc_id == SCTP_ALL_ASSOC)) {
5539					SCTP_INP_WLOCK(inp);
5540					inp->def_send.sinfo_stream = info->snd_sid;
5541					policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
5542					inp->def_send.sinfo_flags = info->snd_flags;
5543					inp->def_send.sinfo_flags |= policy;
5544					inp->def_send.sinfo_ppid = info->snd_ppid;
5545					inp->def_send.sinfo_context = info->snd_context;
5546					SCTP_INP_WUNLOCK(inp);
5547				}
5548				if ((info->snd_assoc_id == SCTP_CURRENT_ASSOC) ||
5549				    (info->snd_assoc_id == SCTP_ALL_ASSOC)) {
5550					SCTP_INP_RLOCK(inp);
5551					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5552						SCTP_TCB_LOCK(stcb);
5553						if (info->snd_sid < stcb->asoc.streamoutcnt) {
5554							stcb->asoc.def_send.sinfo_stream = info->snd_sid;
5555							policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
5556							stcb->asoc.def_send.sinfo_flags = info->snd_flags;
5557							stcb->asoc.def_send.sinfo_flags |= policy;
5558							stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
5559							stcb->asoc.def_send.sinfo_context = info->snd_context;
5560						}
5561						SCTP_TCB_UNLOCK(stcb);
5562					}
5563					SCTP_INP_RUNLOCK(inp);
5564				}
5565			}
5566			break;
5567		}
5568	case SCTP_DEFAULT_PRINFO:
5569		{
5570			struct sctp_default_prinfo *info;
5571
5572			SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, optsize);
5573			SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
5574
5575			if (PR_SCTP_INVALID_POLICY(info->pr_policy)) {
5576				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5577				error = EINVAL;
5578				break;
5579			}
5580			if (stcb) {
5581				stcb->asoc.def_send.sinfo_flags &= 0xfff0;
5582				stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
5583				stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
5584				SCTP_TCB_UNLOCK(stcb);
5585			} else {
5586				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5587				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5588				    (info->pr_assoc_id == SCTP_FUTURE_ASSOC) ||
5589				    (info->pr_assoc_id == SCTP_ALL_ASSOC)) {
5590					SCTP_INP_WLOCK(inp);
5591					inp->def_send.sinfo_flags &= 0xfff0;
5592					inp->def_send.sinfo_flags |= info->pr_policy;
5593					inp->def_send.sinfo_timetolive = info->pr_value;
5594					SCTP_INP_WUNLOCK(inp);
5595				}
5596				if ((info->pr_assoc_id == SCTP_CURRENT_ASSOC) ||
5597				    (info->pr_assoc_id == SCTP_ALL_ASSOC)) {
5598					SCTP_INP_RLOCK(inp);
5599					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5600						SCTP_TCB_LOCK(stcb);
5601						stcb->asoc.def_send.sinfo_flags &= 0xfff0;
5602						stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
5603						stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
5604						SCTP_TCB_UNLOCK(stcb);
5605					}
5606					SCTP_INP_RUNLOCK(inp);
5607				}
5608			}
5609			break;
5610		}
5611	case SCTP_PEER_ADDR_THLDS:
5612		/* Applies to the specific association */
5613		{
5614			struct sctp_paddrthlds *thlds;
5615			struct sctp_nets *net;
5616
5617			SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, optsize);
5618			SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
5619			net = NULL;
5620			if (stcb) {
5621				net = sctp_findnet(stcb, (struct sockaddr *)&thlds->spt_assoc_id);
5622			} else {
5623				/*
5624				 * We increment here since
5625				 * sctp_findassociation_ep_addr() wil do a
5626				 * decrement if it finds the stcb as long as
5627				 * the locked tcb (last argument) is NOT a
5628				 * TCB.. aka NULL.
5629				 */
5630				SCTP_INP_INCR_REF(inp);
5631				stcb = sctp_findassociation_ep_addr(&inp,
5632				    (struct sockaddr *)&thlds->spt_assoc_id,
5633				    &net, NULL, NULL);
5634				if (stcb == NULL) {
5635					SCTP_INP_DECR_REF(inp);
5636				}
5637			}
5638			if (stcb && (net == NULL)) {
5639				struct sockaddr *sa;
5640
5641				sa = (struct sockaddr *)&thlds->spt_assoc_id;
5642#ifdef INET
5643				if (sa->sa_family == AF_INET) {
5644
5645					struct sockaddr_in *sin;
5646
5647					sin = (struct sockaddr_in *)sa;
5648					if (sin->sin_addr.s_addr) {
5649						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5650						SCTP_TCB_UNLOCK(stcb);
5651						error = EINVAL;
5652						break;
5653					}
5654				} else
5655#endif
5656#ifdef INET6
5657				if (sa->sa_family == AF_INET6) {
5658					struct sockaddr_in6 *sin6;
5659
5660					sin6 = (struct sockaddr_in6 *)sa;
5661					if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
5662						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5663						SCTP_TCB_UNLOCK(stcb);
5664						error = EINVAL;
5665						break;
5666					}
5667				} else
5668#endif
5669				{
5670					error = EAFNOSUPPORT;
5671					SCTP_TCB_UNLOCK(stcb);
5672					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
5673					break;
5674				}
5675			}
5676			if (stcb) {
5677				if (net) {
5678					if (net->dest_state & SCTP_ADDR_PF) {
5679						if ((net->failure_threshold > thlds->spt_pathmaxrxt) ||
5680						    (net->failure_threshold <= thlds->spt_pathpfthld)) {
5681							net->dest_state &= ~SCTP_ADDR_PF;
5682						}
5683					} else {
5684						if ((net->failure_threshold > thlds->spt_pathpfthld) &&
5685						    (net->failure_threshold <= thlds->spt_pathmaxrxt)) {
5686							net->dest_state |= SCTP_ADDR_PF;
5687							sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5688							sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
5689							sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
5690						}
5691					}
5692					if (net->dest_state & SCTP_ADDR_REACHABLE) {
5693						if (net->failure_threshold > thlds->spt_pathmaxrxt) {
5694							net->dest_state &= ~SCTP_ADDR_REACHABLE;
5695							sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, SCTP_RESPONSE_TO_USER_REQ, net, SCTP_SO_LOCKED);
5696						}
5697					} else {
5698						if (net->failure_threshold <= thlds->spt_pathmaxrxt) {
5699							net->dest_state |= SCTP_ADDR_REACHABLE;
5700							sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, SCTP_RESPONSE_TO_USER_REQ, net, SCTP_SO_LOCKED);
5701						}
5702					}
5703					net->failure_threshold = thlds->spt_pathmaxrxt;
5704					net->pf_threshold = thlds->spt_pathpfthld;
5705				} else {
5706					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5707						if (net->dest_state & SCTP_ADDR_PF) {
5708							if ((net->failure_threshold > thlds->spt_pathmaxrxt) ||
5709							    (net->failure_threshold <= thlds->spt_pathpfthld)) {
5710								net->dest_state &= ~SCTP_ADDR_PF;
5711							}
5712						} else {
5713							if ((net->failure_threshold > thlds->spt_pathpfthld) &&
5714							    (net->failure_threshold <= thlds->spt_pathmaxrxt)) {
5715								net->dest_state |= SCTP_ADDR_PF;
5716								sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5717								sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
5718								sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
5719							}
5720						}
5721						if (net->dest_state & SCTP_ADDR_REACHABLE) {
5722							if (net->failure_threshold > thlds->spt_pathmaxrxt) {
5723								net->dest_state &= ~SCTP_ADDR_REACHABLE;
5724								sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, SCTP_RESPONSE_TO_USER_REQ, net, SCTP_SO_LOCKED);
5725							}
5726						} else {
5727							if (net->failure_threshold <= thlds->spt_pathmaxrxt) {
5728								net->dest_state |= SCTP_ADDR_REACHABLE;
5729								sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, SCTP_RESPONSE_TO_USER_REQ, net, SCTP_SO_LOCKED);
5730							}
5731						}
5732						net->failure_threshold = thlds->spt_pathmaxrxt;
5733						net->pf_threshold = thlds->spt_pathpfthld;
5734					}
5735					stcb->asoc.def_net_failure = thlds->spt_pathmaxrxt;
5736					stcb->asoc.def_net_pf_threshold = thlds->spt_pathpfthld;
5737				}
5738			} else {
5739				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5740				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5741				    (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC)) {
5742					SCTP_INP_WLOCK(inp);
5743					inp->sctp_ep.def_net_failure = thlds->spt_pathmaxrxt;
5744					inp->sctp_ep.def_net_pf_threshold = thlds->spt_pathpfthld;
5745					SCTP_INP_WUNLOCK(inp);
5746				} else {
5747					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5748					error = EINVAL;
5749				}
5750			}
5751			break;
5752		}
5753	case SCTP_REMOTE_UDP_ENCAPS_PORT:
5754		{
5755			struct sctp_udpencaps *encaps;
5756			struct sctp_nets *net;
5757
5758			SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, optsize);
5759			SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
5760			if (stcb) {
5761				net = sctp_findnet(stcb, (struct sockaddr *)&encaps->sue_address);
5762			} else {
5763				/*
5764				 * We increment here since
5765				 * sctp_findassociation_ep_addr() wil do a
5766				 * decrement if it finds the stcb as long as
5767				 * the locked tcb (last argument) is NOT a
5768				 * TCB.. aka NULL.
5769				 */
5770				net = NULL;
5771				SCTP_INP_INCR_REF(inp);
5772				stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&encaps->sue_address, &net, NULL, NULL);
5773				if (stcb == NULL) {
5774					SCTP_INP_DECR_REF(inp);
5775				}
5776			}
5777			if (stcb && (net == NULL)) {
5778				struct sockaddr *sa;
5779
5780				sa = (struct sockaddr *)&encaps->sue_address;
5781#ifdef INET
5782				if (sa->sa_family == AF_INET) {
5783
5784					struct sockaddr_in *sin;
5785
5786					sin = (struct sockaddr_in *)sa;
5787					if (sin->sin_addr.s_addr) {
5788						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5789						SCTP_TCB_UNLOCK(stcb);
5790						error = EINVAL;
5791						break;
5792					}
5793				} else
5794#endif
5795#ifdef INET6
5796				if (sa->sa_family == AF_INET6) {
5797					struct sockaddr_in6 *sin6;
5798
5799					sin6 = (struct sockaddr_in6 *)sa;
5800					if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
5801						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5802						SCTP_TCB_UNLOCK(stcb);
5803						error = EINVAL;
5804						break;
5805					}
5806				} else
5807#endif
5808				{
5809					error = EAFNOSUPPORT;
5810					SCTP_TCB_UNLOCK(stcb);
5811					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
5812					break;
5813				}
5814			}
5815			if (stcb) {
5816				if (net) {
5817					net->port = encaps->sue_port;
5818				} else {
5819					stcb->asoc.port = encaps->sue_port;
5820				}
5821				SCTP_TCB_UNLOCK(stcb);
5822			} else {
5823				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5824				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5825				    (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC)) {
5826					SCTP_INP_WLOCK(inp);
5827					inp->sctp_ep.port = encaps->sue_port;
5828					SCTP_INP_WUNLOCK(inp);
5829				} else {
5830					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5831					error = EINVAL;
5832				}
5833			}
5834			break;
5835		}
5836	default:
5837		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
5838		error = ENOPROTOOPT;
5839		break;
5840	}			/* end switch (opt) */
5841	return (error);
5842}
5843
5844int
5845sctp_ctloutput(struct socket *so, struct sockopt *sopt)
5846{
5847	void *optval = NULL;
5848	size_t optsize = 0;
5849	struct sctp_inpcb *inp;
5850	void *p;
5851	int error = 0;
5852
5853	if (sopt->sopt_level != IPPROTO_SCTP) {
5854		/* wrong proto level... send back up to IP */
5855#ifdef INET6
5856		if (INP_CHECK_SOCKAF(so, AF_INET6))
5857			error = ip6_ctloutput(so, sopt);
5858#endif				/* INET6 */
5859#if defined(INET) && defined (INET6)
5860		else
5861#endif
5862#ifdef INET
5863			error = ip_ctloutput(so, sopt);
5864#endif
5865		return (error);
5866	}
5867	inp = (struct sctp_inpcb *)so->so_pcb;
5868	optsize = sopt->sopt_valsize;
5869	if (optsize) {
5870		SCTP_MALLOC(optval, void *, optsize, SCTP_M_SOCKOPT);
5871		if (optval == NULL) {
5872			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS);
5873			return (ENOBUFS);
5874		}
5875		error = sooptcopyin(sopt, optval, optsize, optsize);
5876		if (error) {
5877			SCTP_FREE(optval, SCTP_M_SOCKOPT);
5878			goto out;
5879		}
5880	}
5881	p = (void *)sopt->sopt_td;
5882	if (sopt->sopt_dir == SOPT_SET) {
5883		error = sctp_setopt(so, sopt->sopt_name, optval, optsize, p);
5884	} else if (sopt->sopt_dir == SOPT_GET) {
5885		error = sctp_getopt(so, sopt->sopt_name, optval, &optsize, p);
5886	} else {
5887		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5888		error = EINVAL;
5889	}
5890	if ((error == 0) && (optval != NULL)) {
5891		error = sooptcopyout(sopt, optval, optsize);
5892		SCTP_FREE(optval, SCTP_M_SOCKOPT);
5893	} else if (optval != NULL) {
5894		SCTP_FREE(optval, SCTP_M_SOCKOPT);
5895	}
5896out:
5897	return (error);
5898}
5899
5900#ifdef INET
5901static int
5902sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
5903{
5904	int error = 0;
5905	int create_lock_on = 0;
5906	uint32_t vrf_id;
5907	struct sctp_inpcb *inp;
5908	struct sctp_tcb *stcb = NULL;
5909
5910	inp = (struct sctp_inpcb *)so->so_pcb;
5911	if (inp == NULL) {
5912		/* I made the same as TCP since we are not setup? */
5913		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5914		return (ECONNRESET);
5915	}
5916	if (addr == NULL) {
5917		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5918		return EINVAL;
5919	}
5920	switch (addr->sa_family) {
5921#ifdef INET6
5922	case AF_INET6:
5923		{
5924			struct sockaddr_in6 *sin6p;
5925
5926			if (addr->sa_len != sizeof(struct sockaddr_in6)) {
5927				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5928				return (EINVAL);
5929			}
5930			sin6p = (struct sockaddr_in6 *)addr;
5931			if (p != NULL && (error = prison_remote_ip6(p->td_ucred, &sin6p->sin6_addr)) != 0) {
5932				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
5933				return (error);
5934			}
5935			break;
5936		}
5937#endif
5938#ifdef INET
5939	case AF_INET:
5940		{
5941			struct sockaddr_in *sinp;
5942
5943			if (addr->sa_len != sizeof(struct sockaddr_in)) {
5944				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5945				return (EINVAL);
5946			}
5947			sinp = (struct sockaddr_in *)addr;
5948			if (p != NULL && (error = prison_remote_ip4(p->td_ucred, &sinp->sin_addr)) != 0) {
5949				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
5950				return (error);
5951			}
5952			break;
5953		}
5954#endif
5955	default:
5956		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
5957		return (EAFNOSUPPORT);
5958	}
5959	SCTP_INP_INCR_REF(inp);
5960	SCTP_ASOC_CREATE_LOCK(inp);
5961	create_lock_on = 1;
5962
5963
5964	if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
5965	    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
5966		/* Should I really unlock ? */
5967		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
5968		error = EFAULT;
5969		goto out_now;
5970	}
5971#ifdef INET6
5972	if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
5973	    (addr->sa_family == AF_INET6)) {
5974		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5975		error = EINVAL;
5976		goto out_now;
5977	}
5978#endif				/* INET6 */
5979	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
5980	    SCTP_PCB_FLAGS_UNBOUND) {
5981		/* Bind a ephemeral port */
5982		error = sctp_inpcb_bind(so, NULL, NULL, p);
5983		if (error) {
5984			goto out_now;
5985		}
5986	}
5987	/* Now do we connect? */
5988	if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
5989	    (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
5990		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5991		error = EINVAL;
5992		goto out_now;
5993	}
5994	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
5995	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
5996		/* We are already connected AND the TCP model */
5997		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
5998		error = EADDRINUSE;
5999		goto out_now;
6000	}
6001	if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
6002		SCTP_INP_RLOCK(inp);
6003		stcb = LIST_FIRST(&inp->sctp_asoc_list);
6004		SCTP_INP_RUNLOCK(inp);
6005	} else {
6006		/*
6007		 * We increment here since sctp_findassociation_ep_addr()
6008		 * will do a decrement if it finds the stcb as long as the
6009		 * locked tcb (last argument) is NOT a TCB.. aka NULL.
6010		 */
6011		SCTP_INP_INCR_REF(inp);
6012		stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
6013		if (stcb == NULL) {
6014			SCTP_INP_DECR_REF(inp);
6015		} else {
6016			SCTP_TCB_UNLOCK(stcb);
6017		}
6018	}
6019	if (stcb != NULL) {
6020		/* Already have or am bring up an association */
6021		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
6022		error = EALREADY;
6023		goto out_now;
6024	}
6025	vrf_id = inp->def_vrf_id;
6026	/* We are GOOD to go */
6027	stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, p);
6028	if (stcb == NULL) {
6029		/* Gak! no memory */
6030		goto out_now;
6031	}
6032	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
6033		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
6034		/* Set the connected flag so we can queue data */
6035		soisconnecting(so);
6036	}
6037	SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
6038	(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
6039
6040	/* initialize authentication parameters for the assoc */
6041	sctp_initialize_auth_params(inp, stcb);
6042
6043	sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
6044	SCTP_TCB_UNLOCK(stcb);
6045out_now:
6046	if (create_lock_on) {
6047		SCTP_ASOC_CREATE_UNLOCK(inp);
6048	}
6049	SCTP_INP_DECR_REF(inp);
6050	return (error);
6051}
6052
6053#endif
6054
6055int
6056sctp_listen(struct socket *so, int backlog, struct thread *p)
6057{
6058	/*
6059	 * Note this module depends on the protocol processing being called
6060	 * AFTER any socket level flags and backlog are applied to the
6061	 * socket. The traditional way that the socket flags are applied is
6062	 * AFTER protocol processing. We have made a change to the
6063	 * sys/kern/uipc_socket.c module to reverse this but this MUST be in
6064	 * place if the socket API for SCTP is to work properly.
6065	 */
6066
6067	int error = 0;
6068	struct sctp_inpcb *inp;
6069
6070	inp = (struct sctp_inpcb *)so->so_pcb;
6071	if (inp == NULL) {
6072		/* I made the same as TCP since we are not setup? */
6073		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6074		return (ECONNRESET);
6075	}
6076	if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) {
6077		/* See if we have a listener */
6078		struct sctp_inpcb *tinp;
6079		union sctp_sockstore store, *sp;
6080
6081		sp = &store;
6082		if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
6083			/* not bound all */
6084			struct sctp_laddr *laddr;
6085
6086			LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
6087				memcpy(&store, &laddr->ifa->address, sizeof(store));
6088				switch (sp->sa.sa_family) {
6089#ifdef INET
6090				case AF_INET:
6091					sp->sin.sin_port = inp->sctp_lport;
6092					break;
6093#endif
6094#ifdef INET6
6095				case AF_INET6:
6096					sp->sin6.sin6_port = inp->sctp_lport;
6097					break;
6098#endif
6099				default:
6100					break;
6101				}
6102				tinp = sctp_pcb_findep(&sp->sa, 0, 0, inp->def_vrf_id);
6103				if (tinp && (tinp != inp) &&
6104				    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
6105				    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
6106				    (tinp->sctp_socket->so_qlimit)) {
6107					/*
6108					 * we have a listener already and
6109					 * its not this inp.
6110					 */
6111					SCTP_INP_DECR_REF(tinp);
6112					return (EADDRINUSE);
6113				} else if (tinp) {
6114					SCTP_INP_DECR_REF(tinp);
6115				}
6116			}
6117		} else {
6118			/* Setup a local addr bound all */
6119			memset(&store, 0, sizeof(store));
6120			switch (sp->sa.sa_family) {
6121#ifdef INET
6122			case AF_INET:
6123				store.sin.sin_port = inp->sctp_lport;
6124				break;
6125#endif
6126#ifdef INET6
6127			case AF_INET6:
6128				sp->sin6.sin6_port = inp->sctp_lport;
6129				break;
6130#endif
6131			default:
6132				break;
6133			}
6134#ifdef INET6
6135			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
6136				store.sa.sa_family = AF_INET6;
6137				store.sa.sa_len = sizeof(struct sockaddr_in6);
6138			}
6139#endif
6140#ifdef INET
6141			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
6142				store.sa.sa_family = AF_INET;
6143				store.sa.sa_len = sizeof(struct sockaddr_in);
6144			}
6145#endif
6146			tinp = sctp_pcb_findep(&sp->sa, 0, 0, inp->def_vrf_id);
6147			if (tinp && (tinp != inp) &&
6148			    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
6149			    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
6150			    (tinp->sctp_socket->so_qlimit)) {
6151				/*
6152				 * we have a listener already and its not
6153				 * this inp.
6154				 */
6155				SCTP_INP_DECR_REF(tinp);
6156				return (EADDRINUSE);
6157			} else if (tinp) {
6158				SCTP_INP_DECR_REF(inp);
6159			}
6160		}
6161	}
6162	SCTP_INP_RLOCK(inp);
6163#ifdef SCTP_LOCK_LOGGING
6164	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) {
6165		sctp_log_lock(inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_SOCK);
6166	}
6167#endif
6168	SOCK_LOCK(so);
6169	error = solisten_proto_check(so);
6170	if (error) {
6171		SOCK_UNLOCK(so);
6172		SCTP_INP_RUNLOCK(inp);
6173		return (error);
6174	}
6175	if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) &&
6176	    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
6177		/*
6178		 * The unlucky case - We are in the tcp pool with this guy.
6179		 * - Someone else is in the main inp slot. - We must move
6180		 * this guy (the listener) to the main slot - We must then
6181		 * move the guy that was listener to the TCP Pool.
6182		 */
6183		if (sctp_swap_inpcb_for_listen(inp)) {
6184			goto in_use;
6185		}
6186	}
6187	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
6188	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
6189		/* We are already connected AND the TCP model */
6190in_use:
6191		SCTP_INP_RUNLOCK(inp);
6192		SOCK_UNLOCK(so);
6193		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
6194		return (EADDRINUSE);
6195	}
6196	SCTP_INP_RUNLOCK(inp);
6197	if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
6198		/* We must do a bind. */
6199		SOCK_UNLOCK(so);
6200		if ((error = sctp_inpcb_bind(so, NULL, NULL, p))) {
6201			/* bind error, probably perm */
6202			return (error);
6203		}
6204		SOCK_LOCK(so);
6205	}
6206	/* It appears for 7.0 and on, we must always call this. */
6207	solisten_proto(so, backlog);
6208	if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
6209		/* remove the ACCEPTCONN flag for one-to-many sockets */
6210		so->so_options &= ~SO_ACCEPTCONN;
6211	}
6212	if (backlog == 0) {
6213		/* turning off listen */
6214		so->so_options &= ~SO_ACCEPTCONN;
6215	}
6216	SOCK_UNLOCK(so);
6217	return (error);
6218}
6219
6220static int sctp_defered_wakeup_cnt = 0;
6221
6222int
6223sctp_accept(struct socket *so, struct sockaddr **addr)
6224{
6225	struct sctp_tcb *stcb;
6226	struct sctp_inpcb *inp;
6227	union sctp_sockstore store;
6228
6229#ifdef INET6
6230	int error;
6231
6232#endif
6233	inp = (struct sctp_inpcb *)so->so_pcb;
6234
6235	if (inp == NULL) {
6236		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6237		return (ECONNRESET);
6238	}
6239	SCTP_INP_RLOCK(inp);
6240	if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
6241		SCTP_INP_RUNLOCK(inp);
6242		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
6243		return (EOPNOTSUPP);
6244	}
6245	if (so->so_state & SS_ISDISCONNECTED) {
6246		SCTP_INP_RUNLOCK(inp);
6247		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ECONNABORTED);
6248		return (ECONNABORTED);
6249	}
6250	stcb = LIST_FIRST(&inp->sctp_asoc_list);
6251	if (stcb == NULL) {
6252		SCTP_INP_RUNLOCK(inp);
6253		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6254		return (ECONNRESET);
6255	}
6256	SCTP_TCB_LOCK(stcb);
6257	SCTP_INP_RUNLOCK(inp);
6258	store = stcb->asoc.primary_destination->ro._l_addr;
6259	stcb->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE;
6260	SCTP_TCB_UNLOCK(stcb);
6261	switch (store.sa.sa_family) {
6262#ifdef INET
6263	case AF_INET:
6264		{
6265			struct sockaddr_in *sin;
6266
6267			SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
6268			if (sin == NULL)
6269				return (ENOMEM);
6270			sin->sin_family = AF_INET;
6271			sin->sin_len = sizeof(*sin);
6272			sin->sin_port = ((struct sockaddr_in *)&store)->sin_port;
6273			sin->sin_addr = ((struct sockaddr_in *)&store)->sin_addr;
6274			*addr = (struct sockaddr *)sin;
6275			break;
6276		}
6277#endif
6278#ifdef INET6
6279	case AF_INET6:
6280		{
6281			struct sockaddr_in6 *sin6;
6282
6283			SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
6284			if (sin6 == NULL)
6285				return (ENOMEM);
6286			sin6->sin6_family = AF_INET6;
6287			sin6->sin6_len = sizeof(*sin6);
6288			sin6->sin6_port = ((struct sockaddr_in6 *)&store)->sin6_port;
6289
6290			sin6->sin6_addr = ((struct sockaddr_in6 *)&store)->sin6_addr;
6291			if ((error = sa6_recoverscope(sin6)) != 0) {
6292				SCTP_FREE_SONAME(sin6);
6293				return (error);
6294			}
6295			*addr = (struct sockaddr *)sin6;
6296			break;
6297		}
6298#endif
6299	default:
6300		/* TSNH */
6301		break;
6302	}
6303	/* Wake any delayed sleep action */
6304	if (inp->sctp_flags & SCTP_PCB_FLAGS_DONT_WAKE) {
6305		SCTP_INP_WLOCK(inp);
6306		inp->sctp_flags &= ~SCTP_PCB_FLAGS_DONT_WAKE;
6307		if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEOUTPUT) {
6308			inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEOUTPUT;
6309			SCTP_INP_WUNLOCK(inp);
6310			SOCKBUF_LOCK(&inp->sctp_socket->so_snd);
6311			if (sowriteable(inp->sctp_socket)) {
6312				sowwakeup_locked(inp->sctp_socket);
6313			} else {
6314				SOCKBUF_UNLOCK(&inp->sctp_socket->so_snd);
6315			}
6316			SCTP_INP_WLOCK(inp);
6317		}
6318		if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEINPUT) {
6319			inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEINPUT;
6320			SCTP_INP_WUNLOCK(inp);
6321			SOCKBUF_LOCK(&inp->sctp_socket->so_rcv);
6322			if (soreadable(inp->sctp_socket)) {
6323				sctp_defered_wakeup_cnt++;
6324				sorwakeup_locked(inp->sctp_socket);
6325			} else {
6326				SOCKBUF_UNLOCK(&inp->sctp_socket->so_rcv);
6327			}
6328			SCTP_INP_WLOCK(inp);
6329		}
6330		SCTP_INP_WUNLOCK(inp);
6331	}
6332	if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
6333		SCTP_TCB_LOCK(stcb);
6334		sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_7);
6335	}
6336	return (0);
6337}
6338
6339#ifdef INET
6340int
6341sctp_ingetaddr(struct socket *so, struct sockaddr **addr)
6342{
6343	struct sockaddr_in *sin;
6344	uint32_t vrf_id;
6345	struct sctp_inpcb *inp;
6346	struct sctp_ifa *sctp_ifa;
6347
6348	/*
6349	 * Do the malloc first in case it blocks.
6350	 */
6351	SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
6352	if (sin == NULL)
6353		return (ENOMEM);
6354	sin->sin_family = AF_INET;
6355	sin->sin_len = sizeof(*sin);
6356	inp = (struct sctp_inpcb *)so->so_pcb;
6357	if (!inp) {
6358		SCTP_FREE_SONAME(sin);
6359		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6360		return (ECONNRESET);
6361	}
6362	SCTP_INP_RLOCK(inp);
6363	sin->sin_port = inp->sctp_lport;
6364	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
6365		if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
6366			struct sctp_tcb *stcb;
6367			struct sockaddr_in *sin_a;
6368			struct sctp_nets *net;
6369			int fnd;
6370
6371			stcb = LIST_FIRST(&inp->sctp_asoc_list);
6372			if (stcb == NULL) {
6373				goto notConn;
6374			}
6375			fnd = 0;
6376			sin_a = NULL;
6377			SCTP_TCB_LOCK(stcb);
6378			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6379				sin_a = (struct sockaddr_in *)&net->ro._l_addr;
6380				if (sin_a == NULL)
6381					/* this will make coverity happy */
6382					continue;
6383
6384				if (sin_a->sin_family == AF_INET) {
6385					fnd = 1;
6386					break;
6387				}
6388			}
6389			if ((!fnd) || (sin_a == NULL)) {
6390				/* punt */
6391				SCTP_TCB_UNLOCK(stcb);
6392				goto notConn;
6393			}
6394			vrf_id = inp->def_vrf_id;
6395			sctp_ifa = sctp_source_address_selection(inp,
6396			    stcb,
6397			    (sctp_route_t *) & net->ro,
6398			    net, 0, vrf_id);
6399			if (sctp_ifa) {
6400				sin->sin_addr = sctp_ifa->address.sin.sin_addr;
6401				sctp_free_ifa(sctp_ifa);
6402			}
6403			SCTP_TCB_UNLOCK(stcb);
6404		} else {
6405			/* For the bound all case you get back 0 */
6406	notConn:
6407			sin->sin_addr.s_addr = 0;
6408		}
6409
6410	} else {
6411		/* Take the first IPv4 address in the list */
6412		struct sctp_laddr *laddr;
6413		int fnd = 0;
6414
6415		LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
6416			if (laddr->ifa->address.sa.sa_family == AF_INET) {
6417				struct sockaddr_in *sin_a;
6418
6419				sin_a = (struct sockaddr_in *)&laddr->ifa->address.sa;
6420				sin->sin_addr = sin_a->sin_addr;
6421				fnd = 1;
6422				break;
6423			}
6424		}
6425		if (!fnd) {
6426			SCTP_FREE_SONAME(sin);
6427			SCTP_INP_RUNLOCK(inp);
6428			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
6429			return (ENOENT);
6430		}
6431	}
6432	SCTP_INP_RUNLOCK(inp);
6433	(*addr) = (struct sockaddr *)sin;
6434	return (0);
6435}
6436
6437int
6438sctp_peeraddr(struct socket *so, struct sockaddr **addr)
6439{
6440	struct sockaddr_in *sin;
6441	int fnd;
6442	struct sockaddr_in *sin_a;
6443	struct sctp_inpcb *inp;
6444	struct sctp_tcb *stcb;
6445	struct sctp_nets *net;
6446
6447	/* Do the malloc first in case it blocks. */
6448	SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
6449	if (sin == NULL)
6450		return (ENOMEM);
6451	sin->sin_family = AF_INET;
6452	sin->sin_len = sizeof(*sin);
6453
6454	inp = (struct sctp_inpcb *)so->so_pcb;
6455	if ((inp == NULL) ||
6456	    ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
6457		/* UDP type and listeners will drop out here */
6458		SCTP_FREE_SONAME(sin);
6459		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
6460		return (ENOTCONN);
6461	}
6462	SCTP_INP_RLOCK(inp);
6463	stcb = LIST_FIRST(&inp->sctp_asoc_list);
6464	if (stcb) {
6465		SCTP_TCB_LOCK(stcb);
6466	}
6467	SCTP_INP_RUNLOCK(inp);
6468	if (stcb == NULL) {
6469		SCTP_FREE_SONAME(sin);
6470		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6471		return (ECONNRESET);
6472	}
6473	fnd = 0;
6474	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6475		sin_a = (struct sockaddr_in *)&net->ro._l_addr;
6476		if (sin_a->sin_family == AF_INET) {
6477			fnd = 1;
6478			sin->sin_port = stcb->rport;
6479			sin->sin_addr = sin_a->sin_addr;
6480			break;
6481		}
6482	}
6483	SCTP_TCB_UNLOCK(stcb);
6484	if (!fnd) {
6485		/* No IPv4 address */
6486		SCTP_FREE_SONAME(sin);
6487		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
6488		return (ENOENT);
6489	}
6490	(*addr) = (struct sockaddr *)sin;
6491	return (0);
6492}
6493
6494#ifdef INET
6495struct pr_usrreqs sctp_usrreqs = {
6496	.pru_abort = sctp_abort,
6497	.pru_accept = sctp_accept,
6498	.pru_attach = sctp_attach,
6499	.pru_bind = sctp_bind,
6500	.pru_connect = sctp_connect,
6501	.pru_control = in_control,
6502	.pru_close = sctp_close,
6503	.pru_detach = sctp_close,
6504	.pru_sopoll = sopoll_generic,
6505	.pru_flush = sctp_flush,
6506	.pru_disconnect = sctp_disconnect,
6507	.pru_listen = sctp_listen,
6508	.pru_peeraddr = sctp_peeraddr,
6509	.pru_send = sctp_sendm,
6510	.pru_shutdown = sctp_shutdown,
6511	.pru_sockaddr = sctp_ingetaddr,
6512	.pru_sosend = sctp_sosend,
6513	.pru_soreceive = sctp_soreceive
6514};
6515
6516#endif
6517#endif
6518