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