2 * SPDX-License-Identifier: BSD-3-Clause
4 * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved.
5 * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
6 * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
11 * a) Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
14 * b) Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the distribution.
18 * c) Neither the name of Cisco Systems, Inc. nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
24 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32 * THE POSSIBILITY OF SUCH DAMAGE.
35 #if defined(__FreeBSD__) && !defined(__Userspace__)
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD: head/sys/netinet/sctp_usrreq.c 363275 2020-07-17 15:09:49Z tuexen $");
40 #include <netinet/sctp_os.h>
41 #if defined(__FreeBSD__) && !defined(__Userspace__)
44 #include <netinet/sctp_pcb.h>
45 #include <netinet/sctp_header.h>
46 #include <netinet/sctp_var.h>
48 #include <netinet6/sctp6_var.h>
50 #include <netinet/sctp_sysctl.h>
51 #include <netinet/sctp_output.h>
52 #include <netinet/sctp_uio.h>
53 #include <netinet/sctp_asconf.h>
54 #include <netinet/sctputil.h>
55 #include <netinet/sctp_indata.h>
56 #include <netinet/sctp_timer.h>
57 #include <netinet/sctp_auth.h>
58 #include <netinet/sctp_bsd_addr.h>
59 #if defined(__Userspace__)
60 #include <netinet/sctp_callout.h>
62 #include <netinet/udp.h>
64 #if defined(__FreeBSD__) && !defined(__Userspace__)
65 #include <sys/eventhandler.h>
68 #if defined(HAVE_SCTP_PEELOFF_SOCKOPT)
69 #include <netinet/sctp_peeloff.h>
70 #endif /* HAVE_SCTP_PEELOFF_SOCKOPT */
72 extern const struct sctp_cc_functions sctp_cc_functions[];
73 extern const struct sctp_ss_functions sctp_ss_functions[];
76 #if defined(__Userspace__)
77 sctp_init(uint16_t port,
78 int (*conn_output)(void *addr, void *buffer, size_t length, uint8_t tos, uint8_t set_df),
79 void (*debug_printf)(const char *format, ...), int start_threads)
80 #elif defined(__APPLE__) && (!defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) &&!defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION))
81 sctp_init(struct protosw *pp SCTP_UNUSED, struct domain *dp SCTP_UNUSED)
86 #if !defined(__Userspace__)
92 /* Initialize and modify the sysctled variables */
94 #if defined(__Userspace__)
95 SCTP_BASE_SYSCTL(sctp_udp_tunneling_port) = port;
97 #if defined(__APPLE__) && !defined(__Userspace__)
98 sb_max_adj = (u_long)((u_quad_t) (sb_max) * MCLBYTES / (MSIZE + MCLBYTES));
99 SCTP_BASE_SYSCTL(sctp_sendspace) = sb_max_adj;
101 if ((nmbclusters / 8) > SCTP_ASOC_MAX_CHUNKS_ON_QUEUE)
102 SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue) = (nmbclusters / 8);
104 * Allow a user to take no more than 1/2 the number of clusters or
105 * the SB_MAX, whichever is smaller, for the send window.
107 sb_max_adj = (u_long)((u_quad_t) (SB_MAX) * MCLBYTES / (MSIZE + MCLBYTES));
108 SCTP_BASE_SYSCTL(sctp_sendspace) = min(sb_max_adj,
109 (((uint32_t)nmbclusters / 2) * SCTP_DEFAULT_MAXSEGMENT));
112 * Now for the recv window, should we take the same amount? or
113 * should I do 1/2 the SB_MAX instead in the SB_MAX min above. For
114 * now I will just copy.
116 SCTP_BASE_SYSCTL(sctp_recvspace) = SCTP_BASE_SYSCTL(sctp_sendspace);
118 SCTP_BASE_VAR(first_time) = 0;
119 SCTP_BASE_VAR(sctp_pcb_initialized) = 0;
120 #if defined(__Userspace__)
122 #if defined(INET) || defined(INET6)
123 SCTP_BASE_VAR(userspace_route) = -1;
127 SCTP_BASE_VAR(userspace_rawsctp) = -1;
128 SCTP_BASE_VAR(userspace_udpsctp) = -1;
131 SCTP_BASE_VAR(userspace_rawsctp6) = -1;
132 SCTP_BASE_VAR(userspace_udpsctp6) = -1;
134 SCTP_BASE_VAR(timer_thread_should_exit) = 0;
135 SCTP_BASE_VAR(conn_output) = conn_output;
136 SCTP_BASE_VAR(debug_printf) = debug_printf;
137 SCTP_BASE_VAR(crc32c_offloaded) = 0;
138 SCTP_BASE_VAR(iterator_thread_started) = 0;
139 SCTP_BASE_VAR(timer_thread_started) = 0;
141 #if defined(__Userspace__)
142 sctp_pcb_init(start_threads);
144 sctp_start_timer_thread();
149 #if defined(SCTP_PACKET_LOGGING)
150 SCTP_BASE_VAR(packet_log_writers) = 0;
151 SCTP_BASE_VAR(packet_log_end) = 0;
152 memset(&SCTP_BASE_VAR(packet_log_buffer), 0, SCTP_PACKET_LOG_SIZE);
154 #if defined(__APPLE__) && !defined(__Userspace__)
155 SCTP_BASE_VAR(sctp_main_timer_ticks) = 0;
156 sctp_start_main_timer();
157 timeout(sctp_delayed_startup, NULL, 1);
159 #if defined(__FreeBSD__) && !defined(__Userspace__)
160 SCTP_BASE_VAR(eh_tag) = EVENTHANDLER_REGISTER(rt_addrmsg,
161 sctp_addr_change_event_handler, NULL, EVENTHANDLER_PRI_FIRST);
165 #if defined(__FreeBSD__) && !defined(__Userspace__)
168 sctp_finish(void *unused __unused)
170 EVENTHANDLER_DEREGISTER(rt_addrmsg, SCTP_BASE_VAR(eh_tag));
173 VNET_SYSUNINIT(sctp, SI_SUB_PROTO_DOMAIN, SI_ORDER_FOURTH, sctp_finish, NULL);
179 #if defined(__APPLE__) && !defined(__Userspace__)
180 untimeout(sctp_delayed_startup, NULL);
181 sctp_over_udp_stop();
182 sctp_address_monitor_stop();
183 sctp_stop_main_timer();
185 #if defined(__Userspace__)
186 #if defined(INET) || defined(INET6)
187 recv_thread_destroy();
189 sctp_stop_timer_thread();
192 #if defined(_WIN32) && !defined(__Userspace__)
193 sctp_finish_sysctls();
199 sctp_pathmtu_adjustment(struct sctp_tcb *stcb, uint16_t nxtsz)
201 struct sctp_tmit_chunk *chk;
204 /* Adjust that too */
205 stcb->asoc.smallest_mtu = nxtsz;
206 /* now off to subtract IP_DF flag if needed */
207 overhead = IP_HDR_SIZE + sizeof(struct sctphdr);
208 if (sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.peer_auth_chunks)) {
209 overhead += sctp_get_auth_chunk_len(stcb->asoc.peer_hmac_id);
211 TAILQ_FOREACH(chk, &stcb->asoc.send_queue, sctp_next) {
212 if ((chk->send_size + overhead) > nxtsz) {
213 chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
216 TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
217 if ((chk->send_size + overhead) > nxtsz) {
219 * For this guy we also mark for immediate resend
220 * since we sent to big of chunk
222 chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
223 if (chk->sent < SCTP_DATAGRAM_RESEND) {
224 sctp_flight_size_decrease(chk);
225 sctp_total_flight_decrease(stcb, chk);
226 chk->sent = SCTP_DATAGRAM_RESEND;
227 sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
228 chk->rec.data.doing_fast_retransmit = 0;
229 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) {
230 sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_PMTU,
231 chk->whoTo->flight_size,
233 (uint32_t)(uintptr_t)chk->whoTo,
236 /* Clear any time so NO RTT is being done */
237 if (chk->do_rtt == 1) {
239 chk->whoTo->rto_needed = 1;
247 #if !defined(__Userspace__)
249 sctp_notify(struct sctp_inpcb *inp,
250 struct sctp_tcb *stcb,
251 struct sctp_nets *net,
257 #if defined(__APPLE__) && !defined(__Userspace__)
262 if (icmp_type != ICMP_UNREACH) {
263 /* We only care about unreachable */
264 SCTP_TCB_UNLOCK(stcb);
267 if ((icmp_code == ICMP_UNREACH_NET) ||
268 (icmp_code == ICMP_UNREACH_HOST) ||
269 (icmp_code == ICMP_UNREACH_NET_UNKNOWN) ||
270 (icmp_code == ICMP_UNREACH_HOST_UNKNOWN) ||
271 (icmp_code == ICMP_UNREACH_ISOLATED) ||
272 (icmp_code == ICMP_UNREACH_NET_PROHIB) ||
273 (icmp_code == ICMP_UNREACH_HOST_PROHIB) ||
274 #if defined(__NetBSD__)
275 (icmp_code == ICMP_UNREACH_ADMIN_PROHIBIT)) {
277 (icmp_code == ICMP_UNREACH_FILTER_PROHIB)) {
279 /* Mark the net unreachable. */
280 if (net->dest_state & SCTP_ADDR_REACHABLE) {
281 /* OK, that destination is NOT reachable. */
282 net->dest_state &= ~SCTP_ADDR_REACHABLE;
283 net->dest_state &= ~SCTP_ADDR_PF;
284 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
286 (void *)net, SCTP_SO_NOT_LOCKED);
288 SCTP_TCB_UNLOCK(stcb);
289 } else if ((icmp_code == ICMP_UNREACH_PROTOCOL) ||
290 (icmp_code == ICMP_UNREACH_PORT)) {
291 /* Treat it like an ABORT. */
292 sctp_abort_notification(stcb, 1, 0, NULL, SCTP_SO_NOT_LOCKED);
293 #if defined(__APPLE__) && !defined(__Userspace__)
294 so = SCTP_INP_SO(inp);
295 atomic_add_int(&stcb->asoc.refcnt, 1);
296 SCTP_TCB_UNLOCK(stcb);
297 SCTP_SOCKET_LOCK(so, 1);
299 atomic_subtract_int(&stcb->asoc.refcnt, 1);
301 (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
302 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_2);
303 #if defined(__APPLE__) && !defined(__Userspace__)
304 SCTP_SOCKET_UNLOCK(so, 1);
305 /* SCTP_TCB_UNLOCK(stcb); MT: I think this is not needed.*/
307 /* no need to unlock here, since the TCB is gone */
308 } else if (icmp_code == ICMP_UNREACH_NEEDFRAG) {
309 if (net->dest_state & SCTP_ADDR_NO_PMTUD) {
310 SCTP_TCB_UNLOCK(stcb);
313 /* Find the next (smaller) MTU */
316 * Old type router that does not tell us what the next
318 * Rats we will have to guess (in a educated fashion
321 next_mtu = sctp_get_prev_mtu(ip_len);
323 /* Stop the PMTU timer. */
324 if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
326 sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
327 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_1);
331 /* Update the path MTU. */
333 next_mtu -= sizeof(struct udphdr);
335 if (net->mtu > next_mtu) {
337 #if defined(__FreeBSD__) && !defined(__Userspace__)
339 sctp_hc_set_mtu(&net->ro._l_addr, inp->fibnum, next_mtu + sizeof(struct udphdr));
341 sctp_hc_set_mtu(&net->ro._l_addr, inp->fibnum, next_mtu);
345 /* Update the association MTU */
346 if (stcb->asoc.smallest_mtu > next_mtu) {
347 sctp_pathmtu_adjustment(stcb, next_mtu);
349 /* Finally, start the PMTU timer if it was running before. */
351 sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
353 SCTP_TCB_UNLOCK(stcb);
355 SCTP_TCB_UNLOCK(stcb);
360 #if !defined(__Userspace__)
362 #if defined(__APPLE__) && !defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) && !defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION) && !defined(APPLE_ELCAPITAN)
363 sctp_ctlinput(int cmd, struct sockaddr *sa, void *vip, struct ifnet *ifp SCTP_UNUSED)
365 sctp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
368 #if defined(__FreeBSD__) && !defined(__Userspace__)
374 struct sctp_inpcb *inp;
375 struct sctp_tcb *stcb;
376 struct sctp_nets *net;
377 #if defined(__FreeBSD__) && !defined(__Userspace__)
378 struct sctp_init_chunk *ch;
380 struct sockaddr_in src, dst;
382 if (sa->sa_family != AF_INET ||
383 ((struct sockaddr_in *)sa)->sin_addr.s_addr == INADDR_ANY) {
386 if (PRC_IS_REDIRECT(cmd)) {
388 } else if ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0) {
392 inner_ip = (struct ip *)vip;
393 icmp = (struct icmp *)((caddr_t)inner_ip -
394 (sizeof(struct icmp) - sizeof(struct ip)));
395 #if defined(__FreeBSD__) && !defined(__Userspace__)
396 outer_ip = (struct ip *)((caddr_t)icmp - sizeof(struct ip));
398 sh = (struct sctphdr *)((caddr_t)inner_ip + (inner_ip->ip_hl << 2));
399 memset(&src, 0, sizeof(struct sockaddr_in));
400 src.sin_family = AF_INET;
402 src.sin_len = sizeof(struct sockaddr_in);
404 src.sin_port = sh->src_port;
405 src.sin_addr = inner_ip->ip_src;
406 memset(&dst, 0, sizeof(struct sockaddr_in));
407 dst.sin_family = AF_INET;
409 dst.sin_len = sizeof(struct sockaddr_in);
411 dst.sin_port = sh->dest_port;
412 dst.sin_addr = inner_ip->ip_dst;
414 * 'dst' holds the dest of the packet that failed to be sent.
415 * 'src' holds our local endpoint address. Thus we reverse
416 * the dst and the src in the lookup.
420 stcb = sctp_findassociation_addr_sa((struct sockaddr *)&dst,
421 (struct sockaddr *)&src,
424 if ((stcb != NULL) &&
427 /* Check the verification tag */
428 if (ntohl(sh->v_tag) != 0) {
430 * This must be the verification tag used for
431 * sending out packets. We don't consider
432 * packets reflecting the verification tag.
434 if (ntohl(sh->v_tag) != stcb->asoc.peer_vtag) {
435 SCTP_TCB_UNLOCK(stcb);
439 #if defined(__FreeBSD__) && !defined(__Userspace__)
440 if (ntohs(outer_ip->ip_len) >=
442 8 + (inner_ip->ip_hl << 2) + 20) {
444 * In this case we can check if we
445 * got an INIT chunk and if the
446 * initiate tag matches.
448 ch = (struct sctp_init_chunk *)(sh + 1);
449 if ((ch->ch.chunk_type != SCTP_INITIATION) ||
450 (ntohl(ch->init.initiate_tag) != stcb->asoc.my_vtag)) {
451 SCTP_TCB_UNLOCK(stcb);
455 SCTP_TCB_UNLOCK(stcb);
459 SCTP_TCB_UNLOCK(stcb);
463 sctp_notify(inp, stcb, net,
466 #if defined(__FreeBSD__) && !defined(__Userspace__)
467 ntohs(inner_ip->ip_len),
471 (uint32_t)ntohs(icmp->icmp_nextmtu));
472 #if defined(__Userspace__)
473 if (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) &&
474 (stcb->sctp_socket != NULL)) {
475 struct socket *upcall_socket;
477 upcall_socket = stcb->sctp_socket;
478 SOCK_LOCK(upcall_socket);
479 soref(upcall_socket);
480 SOCK_UNLOCK(upcall_socket);
481 if ((upcall_socket->so_upcall != NULL) &&
482 (upcall_socket->so_error != 0)) {
483 (*upcall_socket->so_upcall)(upcall_socket, upcall_socket->so_upcallarg, M_NOWAIT);
486 SOCK_LOCK(upcall_socket);
487 sorele(upcall_socket);
491 if ((stcb == NULL) && (inp != NULL)) {
492 /* reduce ref-count */
494 SCTP_INP_DECR_REF(inp);
495 SCTP_INP_WUNLOCK(inp);
498 SCTP_TCB_UNLOCK(stcb);
507 #if defined(__FreeBSD__) && !defined(__Userspace__)
509 sctp_getcred(SYSCTL_HANDLER_ARGS)
512 struct sockaddr_in addrs[2];
513 struct sctp_inpcb *inp;
514 struct sctp_nets *net;
515 struct sctp_tcb *stcb;
519 /* FIX, for non-bsd is this right? */
520 vrf_id = SCTP_DEFAULT_VRFID;
522 error = priv_check(req->td, PRIV_NETINET_GETCRED);
527 error = SYSCTL_IN(req, addrs, sizeof(addrs));
531 stcb = sctp_findassociation_addr_sa(sintosa(&addrs[1]),
533 &inp, &net, 1, vrf_id);
534 if (stcb == NULL || inp == NULL || inp->sctp_socket == NULL) {
535 if ((inp != NULL) && (stcb == NULL)) {
536 /* reduce ref-count */
538 SCTP_INP_DECR_REF(inp);
542 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
546 SCTP_TCB_UNLOCK(stcb);
547 /* We use the write lock here, only
548 * since in the error leg we need it.
549 * If we used RLOCK, then we would have
550 * to wlock/decr/unlock/rlock. Which
551 * in theory could create a hole. Better
552 * to use higher wlock.
556 error = cr_canseesocket(req->td->td_ucred, inp->sctp_socket);
558 SCTP_INP_WUNLOCK(inp);
561 cru2x(inp->sctp_socket->so_cred, &xuc);
562 SCTP_INP_WUNLOCK(inp);
563 error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
568 SYSCTL_PROC(_net_inet_sctp, OID_AUTO, getcred,
569 CTLTYPE_OPAQUE | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
570 0, 0, sctp_getcred, "S,ucred",
571 "Get the ucred of a SCTP connection");
576 #if defined(_WIN32) || defined(__Userspace__)
578 #elif defined(__FreeBSD__)
583 sctp_abort(struct socket *so)
585 #if defined(__FreeBSD__) && !defined(__Userspace__)
586 struct epoch_tracker et;
588 struct sctp_inpcb *inp;
591 inp = (struct sctp_inpcb *)so->so_pcb;
593 #if defined(__FreeBSD__) && !defined(__Userspace__)
596 SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
601 #if defined(__FreeBSD__) && !defined(__Userspace__)
605 flags = inp->sctp_flags;
606 #ifdef SCTP_LOG_CLOSING
607 sctp_log_closing(inp, NULL, 17);
609 if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
610 (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
611 #ifdef SCTP_LOG_CLOSING
612 sctp_log_closing(inp, NULL, 16);
614 sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
615 SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
617 SCTP_SB_CLEAR(so->so_snd);
618 /* same for the rcv ones, they are only
619 * here for the accounting/select.
621 SCTP_SB_CLEAR(so->so_rcv);
623 #if defined(__APPLE__) && !defined(__Userspace__)
626 /* Now null out the reference, we are completely detached. */
631 flags = inp->sctp_flags;
632 if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
633 goto sctp_must_try_again;
636 #if defined(__FreeBSD__) && !defined(__Userspace__)
644 #if defined(__Userspace__)
649 #if defined(__Userspace__)
650 sctp_attach(struct socket *so, int proto SCTP_UNUSED, uint32_t vrf_id)
651 #elif defined(__FreeBSD__)
652 sctp_attach(struct socket *so, int proto SCTP_UNUSED, struct thread *p SCTP_UNUSED)
653 #elif defined(_WIN32)
654 sctp_attach(struct socket *so, int proto SCTP_UNUSED, PKTHREAD p SCTP_UNUSED)
656 sctp_attach(struct socket *so, int proto SCTP_UNUSED, struct proc *p SCTP_UNUSED)
659 struct sctp_inpcb *inp;
660 struct inpcb *ip_inp;
662 #if !defined(__Userspace__)
663 uint32_t vrf_id = SCTP_DEFAULT_VRFID;
666 inp = (struct sctp_inpcb *)so->so_pcb;
668 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
671 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
672 error = SCTP_SORESERVE(so, SCTP_BASE_SYSCTL(sctp_sendspace), SCTP_BASE_SYSCTL(sctp_recvspace));
677 error = sctp_inpcb_alloc(so, vrf_id);
681 inp = (struct sctp_inpcb *)so->so_pcb;
683 inp->sctp_flags &= ~SCTP_PCB_FLAGS_BOUND_V6; /* I'm not v6! */
684 ip_inp = &inp->ip_inp.inp;
685 ip_inp->inp_vflag |= INP_IPV4;
686 ip_inp->inp_ip_ttl = MODULE_GLOBAL(ip_defttl);
687 SCTP_INP_WUNLOCK(inp);
691 #if defined(__Userspace__)
693 sctp_bind(struct socket *so, struct sockaddr *addr) {
695 #elif defined(__FreeBSD__)
697 sctp_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
699 #elif defined(__APPLE__)
701 sctp_bind(struct socket *so, struct sockaddr *addr, struct proc *p) {
702 #elif defined(_WIN32)
704 sctp_bind(struct socket *so, struct sockaddr *addr, PKTHREAD p) {
707 sctp_bind(struct socket *so, struct mbuf *nam, struct proc *p)
709 struct sockaddr *addr = nam ? mtod(nam, struct sockaddr *): NULL;
712 struct sctp_inpcb *inp;
714 inp = (struct sctp_inpcb *)so->so_pcb;
716 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
721 if ((addr->sa_family != AF_INET) ||
722 (addr->sa_len != sizeof(struct sockaddr_in))) {
724 if (addr->sa_family != AF_INET) {
726 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
730 return (sctp_inpcb_bind(so, addr, NULL, p));
734 #if defined(__Userspace__)
737 sctpconn_attach(struct socket *so, int proto SCTP_UNUSED, uint32_t vrf_id)
739 struct sctp_inpcb *inp;
740 struct inpcb *ip_inp;
743 inp = (struct sctp_inpcb *)so->so_pcb;
745 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
748 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
749 error = SCTP_SORESERVE(so, SCTP_BASE_SYSCTL(sctp_sendspace), SCTP_BASE_SYSCTL(sctp_recvspace));
754 error = sctp_inpcb_alloc(so, vrf_id);
758 inp = (struct sctp_inpcb *)so->so_pcb;
760 inp->sctp_flags &= ~SCTP_PCB_FLAGS_BOUND_V6;
761 inp->sctp_flags |= SCTP_PCB_FLAGS_BOUND_CONN;
762 ip_inp = &inp->ip_inp.inp;
763 ip_inp->inp_vflag |= INP_CONN;
764 ip_inp->inp_ip_ttl = MODULE_GLOBAL(ip_defttl);
765 SCTP_INP_WUNLOCK(inp);
770 sctpconn_bind(struct socket *so, struct sockaddr *addr)
772 struct sctp_inpcb *inp;
774 inp = (struct sctp_inpcb *)so->so_pcb;
776 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
781 if ((addr->sa_family != AF_CONN) ||
782 (addr->sa_len != sizeof(struct sockaddr_conn))) {
784 if (addr->sa_family != AF_CONN) {
786 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
790 return (sctp_inpcb_bind(so, addr, NULL, NULL));
794 #if defined(__FreeBSD__) || defined(_WIN32) || defined(__Userspace__)
796 sctp_close(struct socket *so)
798 #if defined(__FreeBSD__) && !defined(__Userspace__)
799 struct epoch_tracker et;
801 struct sctp_inpcb *inp;
804 inp = (struct sctp_inpcb *)so->so_pcb;
808 /* Inform all the lower layer assoc that we
811 #if defined(__FreeBSD__) && !defined(__Userspace__)
815 flags = inp->sctp_flags;
816 #ifdef SCTP_LOG_CLOSING
817 sctp_log_closing(inp, NULL, 17);
819 if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
820 (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
821 #if defined(__Userspace__)
822 if (((so->so_options & SCTP_SO_LINGER) && (so->so_linger == 0)) ||
823 (so->so_rcv.sb_cc > 0)) {
825 if (((so->so_options & SO_LINGER) && (so->so_linger == 0)) ||
826 (so->so_rcv.sb_cc > 0)) {
828 #ifdef SCTP_LOG_CLOSING
829 sctp_log_closing(inp, NULL, 13);
831 sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
832 SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
834 #ifdef SCTP_LOG_CLOSING
835 sctp_log_closing(inp, NULL, 14);
837 sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_GRACEFUL_CLOSE,
838 SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
840 /* The socket is now detached, no matter what
841 * the state of the SCTP association.
844 SCTP_SB_CLEAR(so->so_snd);
845 /* same for the rcv ones, they are only
846 * here for the accounting/select.
848 SCTP_SB_CLEAR(so->so_rcv);
850 #if !(defined(__APPLE__) && !defined(__Userspace__))
851 /* Now null out the reference, we are completely detached. */
856 flags = inp->sctp_flags;
857 if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
858 goto sctp_must_try_again;
861 #if defined(__FreeBSD__) && !defined(__Userspace__)
871 sctp_detach(struct socket *so)
873 struct sctp_inpcb *inp;
876 inp = (struct sctp_inpcb *)so->so_pcb;
878 #if defined(__FreeBSD__) && !defined(__Userspace__)
881 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
886 flags = inp->sctp_flags;
887 #ifdef SCTP_LOG_CLOSING
888 sctp_log_closing(inp, NULL, 17);
890 if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
891 (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
892 #if defined(__Userspace__)
893 if (((so->so_options & SCTP_SO_LINGER) && (so->so_linger == 0)) ||
894 (so->so_rcv.sb_cc > 0)) {
896 if (((so->so_options & SO_LINGER) && (so->so_linger == 0)) ||
897 (so->so_rcv.sb_cc > 0)) {
899 #ifdef SCTP_LOG_CLOSING
900 sctp_log_closing(inp, NULL, 13);
902 sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
903 SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
905 #ifdef SCTP_LOG_CLOSING
906 sctp_log_closing(inp, NULL, 13);
908 sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_GRACEFUL_CLOSE,
909 SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
911 /* The socket is now detached, no matter what
912 * the state of the SCTP association.
914 SCTP_SB_CLEAR(so->so_snd);
915 /* same for the rcv ones, they are only
916 * here for the accounting/select.
918 SCTP_SB_CLEAR(so->so_rcv);
919 #if !(defined(__APPLE__) && !defined(__Userspace__))
924 flags = inp->sctp_flags;
925 if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
926 goto sctp_must_try_again;
929 #if defined(__FreeBSD__) && !defined(__Userspace__)
937 #if defined(__Userspace__)
938 /* __Userspace__ is not calling sctp_sendm */
940 #if !(defined(_WIN32) && !defined(__Userspace__))
942 #if defined(__FreeBSD__) && !defined(__Userspace__)
943 sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
944 struct mbuf *control, struct thread *p);
947 sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
948 struct mbuf *control, struct proc *p);
953 #if defined(__FreeBSD__) && !defined(__Userspace__)
954 sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
955 struct mbuf *control, struct thread *p)
958 sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
959 struct mbuf *control, struct proc *p)
962 struct sctp_inpcb *inp;
965 inp = (struct sctp_inpcb *)so->so_pcb;
968 sctp_m_freem(control);
971 SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
975 /* Got to have an to address if we are NOT a connected socket */
976 if ((addr == NULL) &&
977 ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) ||
978 (inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE))) {
980 } else if (addr == NULL) {
981 SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EDESTADDRREQ);
982 error = EDESTADDRREQ;
985 sctp_m_freem(control);
991 if (addr->sa_family != AF_INET) {
992 /* must be a v4 address! */
993 SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EDESTADDRREQ);
996 sctp_m_freem(control);
999 error = EDESTADDRREQ;
1004 /* now what about control */
1007 sctp_m_freem(inp->control);
1008 inp->control = NULL;
1010 inp->control = control;
1012 /* Place the data */
1014 SCTP_BUF_NEXT(inp->pkt_last) = m;
1017 inp->pkt_last = inp->pkt = m;
1020 #if (defined(__FreeBSD__) || defined(__APPLE__)) && !defined(__Userspace__)
1021 /* FreeBSD uses a flag passed */
1022 ((flags & PRUS_MORETOCOME) == 0)
1024 1 /* Open BSD does not have any "more to come"
1029 * note with the current version this code will only be used
1030 * by OpenBSD-- NetBSD, FreeBSD, and MacOS have methods for
1031 * re-defining sosend to use the sctp_sosend. One can
1032 * optionally switch back to this code (by changing back the
1033 * definitions) but this is not advisable. This code is used
1034 * by FreeBSD when sending a file with sendfile() though.
1036 #if defined(__FreeBSD__) && !defined(__Userspace__)
1037 struct epoch_tracker et;
1041 #if defined(__FreeBSD__) && !defined(__Userspace__)
1042 NET_EPOCH_ENTER(et);
1044 ret = sctp_output(inp, inp->pkt, addr, inp->control, p, flags);
1045 #if defined(__FreeBSD__) && !defined(__Userspace__)
1049 inp->control = NULL;
1058 sctp_disconnect(struct socket *so)
1060 struct sctp_inpcb *inp;
1062 inp = (struct sctp_inpcb *)so->so_pcb;
1064 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
1067 SCTP_INP_RLOCK(inp);
1068 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1069 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
1070 if (LIST_EMPTY(&inp->sctp_asoc_list)) {
1072 SCTP_INP_RUNLOCK(inp);
1075 #if defined(__FreeBSD__) && !defined(__Userspace__)
1076 struct epoch_tracker et;
1078 struct sctp_association *asoc;
1079 struct sctp_tcb *stcb;
1081 stcb = LIST_FIRST(&inp->sctp_asoc_list);
1083 SCTP_INP_RUNLOCK(inp);
1084 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1087 SCTP_TCB_LOCK(stcb);
1089 if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
1090 /* We are about to be freed, out of here */
1091 SCTP_TCB_UNLOCK(stcb);
1092 SCTP_INP_RUNLOCK(inp);
1095 #if defined(__FreeBSD__) && !defined(__Userspace__)
1096 NET_EPOCH_ENTER(et);
1098 #if defined(__Userspace__)
1099 if (((so->so_options & SCTP_SO_LINGER) &&
1100 (so->so_linger == 0)) ||
1101 (so->so_rcv.sb_cc > 0)) {
1103 if (((so->so_options & SO_LINGER) &&
1104 (so->so_linger == 0)) ||
1105 (so->so_rcv.sb_cc > 0)) {
1107 if (SCTP_GET_STATE(stcb) != SCTP_STATE_COOKIE_WAIT) {
1108 /* Left with Data unread */
1109 struct mbuf *op_err;
1111 op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
1112 sctp_send_abort_tcb(stcb, op_err, SCTP_SO_LOCKED);
1113 SCTP_STAT_INCR_COUNTER32(sctps_aborted);
1115 SCTP_INP_RUNLOCK(inp);
1116 if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
1117 (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
1118 SCTP_STAT_DECR_GAUGE32(sctps_currestab);
1120 (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
1121 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_3);
1122 /* No unlock tcb assoc is gone */
1123 #if defined(__FreeBSD__) && !defined(__Userspace__)
1128 if (TAILQ_EMPTY(&asoc->send_queue) &&
1129 TAILQ_EMPTY(&asoc->sent_queue) &&
1130 (asoc->stream_queue_cnt == 0)) {
1131 /* there is nothing queued to send, so done */
1132 if ((*asoc->ss_functions.sctp_ss_is_user_msgs_incomplete)(stcb, asoc)) {
1135 if ((SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_SENT) &&
1136 (SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
1137 /* only send SHUTDOWN 1st time thru */
1138 struct sctp_nets *netp;
1140 if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
1141 (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
1142 SCTP_STAT_DECR_GAUGE32(sctps_currestab);
1144 SCTP_SET_STATE(stcb, SCTP_STATE_SHUTDOWN_SENT);
1145 sctp_stop_timers_for_shutdown(stcb);
1146 if (stcb->asoc.alternate) {
1147 netp = stcb->asoc.alternate;
1149 netp = stcb->asoc.primary_destination;
1151 sctp_send_shutdown(stcb,netp);
1152 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
1153 stcb->sctp_ep, stcb, netp);
1154 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
1155 stcb->sctp_ep, stcb, NULL);
1156 sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_LOCKED);
1160 * we still got (or just got) data to send,
1161 * so set SHUTDOWN_PENDING
1164 * XXX sockets draft says that SCTP_EOF
1165 * should be sent with no data. currently,
1166 * we will allow user data to be sent first
1167 * and move to SHUTDOWN-PENDING
1169 SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_SHUTDOWN_PENDING);
1170 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb, NULL);
1171 if ((*asoc->ss_functions.sctp_ss_is_user_msgs_incomplete)(stcb, asoc)) {
1172 SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_PARTIAL_MSG_LEFT);
1174 if (TAILQ_EMPTY(&asoc->send_queue) &&
1175 TAILQ_EMPTY(&asoc->sent_queue) &&
1176 (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
1177 struct mbuf *op_err;
1179 op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
1180 stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_4;
1181 sctp_send_abort_tcb(stcb, op_err, SCTP_SO_LOCKED);
1182 SCTP_STAT_INCR_COUNTER32(sctps_aborted);
1183 if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
1184 (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
1185 SCTP_STAT_DECR_GAUGE32(sctps_currestab);
1187 SCTP_INP_RUNLOCK(inp);
1188 (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
1189 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_5);
1190 #if defined(__FreeBSD__) && !defined(__Userspace__)
1195 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
1198 soisdisconnecting(so);
1199 #if defined(__FreeBSD__) && !defined(__Userspace__)
1202 SCTP_TCB_UNLOCK(stcb);
1203 SCTP_INP_RUNLOCK(inp);
1208 /* UDP model does not support this */
1209 SCTP_INP_RUNLOCK(inp);
1210 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
1211 return (EOPNOTSUPP);
1215 #if defined(__FreeBSD__) || defined(_WIN32) || defined(__Userspace__)
1217 sctp_flush(struct socket *so, int how)
1220 * We will just clear out the values and let
1221 * subsequent close clear out the data, if any.
1222 * Note if the user did a shutdown(SHUT_RD) they
1223 * will not be able to read the data, the socket
1224 * will block that from happening.
1226 struct sctp_inpcb *inp;
1228 inp = (struct sctp_inpcb *)so->so_pcb;
1230 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1233 SCTP_INP_RLOCK(inp);
1234 /* For the 1 to many model this does nothing */
1235 if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
1236 SCTP_INP_RUNLOCK(inp);
1239 SCTP_INP_RUNLOCK(inp);
1240 if ((how == PRU_FLUSH_RD) || (how == PRU_FLUSH_RDWR)) {
1241 /* First make sure the sb will be happy, we don't
1242 * use these except maybe the count
1244 SCTP_INP_WLOCK(inp);
1245 SCTP_INP_READ_LOCK(inp);
1246 inp->sctp_flags |= SCTP_PCB_FLAGS_SOCKET_CANT_READ;
1247 SCTP_INP_READ_UNLOCK(inp);
1248 SCTP_INP_WUNLOCK(inp);
1249 so->so_rcv.sb_cc = 0;
1250 so->so_rcv.sb_mbcnt = 0;
1251 so->so_rcv.sb_mb = NULL;
1253 if ((how == PRU_FLUSH_WR) || (how == PRU_FLUSH_RDWR)) {
1254 /* First make sure the sb will be happy, we don't
1255 * use these except maybe the count
1257 so->so_snd.sb_cc = 0;
1258 so->so_snd.sb_mbcnt = 0;
1259 so->so_snd.sb_mb = NULL;
1267 sctp_shutdown(struct socket *so)
1269 struct sctp_inpcb *inp;
1271 inp = (struct sctp_inpcb *)so->so_pcb;
1273 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1276 SCTP_INP_RLOCK(inp);
1277 /* For UDP model this is a invalid call */
1278 if (!((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1279 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) {
1280 /* Restore the flags that the soshutdown took away. */
1281 #if (defined(__FreeBSD__) || defined(_WIN32)) && !defined(__Userspace__)
1282 SOCKBUF_LOCK(&so->so_rcv);
1283 so->so_rcv.sb_state &= ~SBS_CANTRCVMORE;
1284 SOCKBUF_UNLOCK(&so->so_rcv);
1287 so->so_state &= ~SS_CANTRCVMORE;
1290 /* This proc will wakeup for read and do nothing (I hope) */
1291 SCTP_INP_RUNLOCK(inp);
1292 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
1293 return (EOPNOTSUPP);
1296 * Ok, if we reach here its the TCP model and it is either
1297 * a SHUT_WR or SHUT_RDWR.
1298 * This means we put the shutdown flag against it.
1300 #if defined(__FreeBSD__) && !defined(__Userspace__)
1301 struct epoch_tracker et;
1303 struct sctp_tcb *stcb;
1304 struct sctp_association *asoc;
1305 struct sctp_nets *netp;
1308 (SS_ISCONNECTED|SS_ISCONNECTING|SS_ISDISCONNECTING)) == 0) {
1309 SCTP_INP_RUNLOCK(inp);
1314 stcb = LIST_FIRST(&inp->sctp_asoc_list);
1317 * Ok, we hit the case that the shutdown call was
1318 * made after an abort or something. Nothing to do
1321 SCTP_INP_RUNLOCK(inp);
1324 SCTP_TCB_LOCK(stcb);
1326 if (asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) {
1327 SCTP_TCB_UNLOCK(stcb);
1328 SCTP_INP_RUNLOCK(inp);
1331 if ((SCTP_GET_STATE(stcb) != SCTP_STATE_COOKIE_WAIT) &&
1332 (SCTP_GET_STATE(stcb) != SCTP_STATE_COOKIE_ECHOED) &&
1333 (SCTP_GET_STATE(stcb) != SCTP_STATE_OPEN)) {
1334 /* If we are not in or before ESTABLISHED, there is
1335 * no protocol action required.
1337 SCTP_TCB_UNLOCK(stcb);
1338 SCTP_INP_RUNLOCK(inp);
1341 #if defined(__FreeBSD__) && !defined(__Userspace__)
1342 NET_EPOCH_ENTER(et);
1344 if (stcb->asoc.alternate) {
1345 netp = stcb->asoc.alternate;
1347 netp = stcb->asoc.primary_destination;
1349 if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) &&
1350 TAILQ_EMPTY(&asoc->send_queue) &&
1351 TAILQ_EMPTY(&asoc->sent_queue) &&
1352 (asoc->stream_queue_cnt == 0)) {
1353 if ((*asoc->ss_functions.sctp_ss_is_user_msgs_incomplete)(stcb, asoc)) {
1356 /* there is nothing queued to send, so I'm done... */
1357 SCTP_STAT_DECR_GAUGE32(sctps_currestab);
1358 SCTP_SET_STATE(stcb, SCTP_STATE_SHUTDOWN_SENT);
1359 sctp_stop_timers_for_shutdown(stcb);
1360 sctp_send_shutdown(stcb, netp);
1361 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
1362 stcb->sctp_ep, stcb, netp);
1365 * We still got (or just got) data to send, so set
1368 SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_SHUTDOWN_PENDING);
1369 if ((*asoc->ss_functions.sctp_ss_is_user_msgs_incomplete)(stcb, asoc)) {
1370 SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_PARTIAL_MSG_LEFT);
1372 if (TAILQ_EMPTY(&asoc->send_queue) &&
1373 TAILQ_EMPTY(&asoc->sent_queue) &&
1374 (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
1375 struct mbuf *op_err;
1377 op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
1378 stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6;
1379 SCTP_INP_RUNLOCK(inp);
1380 sctp_abort_an_association(stcb->sctp_ep, stcb,
1381 op_err, SCTP_SO_LOCKED);
1382 #if defined(__FreeBSD__) && !defined(__Userspace__)
1388 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb, NULL);
1389 /* XXX: Why do this in the case where we have still data queued? */
1390 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
1391 SCTP_TCB_UNLOCK(stcb);
1392 SCTP_INP_RUNLOCK(inp);
1393 #if defined(__FreeBSD__) && !defined(__Userspace__)
1401 * copies a "user" presentable address and removes embedded scope, etc.
1402 * returns 0 on success, 1 on error
1405 sctp_fill_user_address(struct sockaddr *dst, struct sockaddr *src)
1408 #if defined(SCTP_EMBEDDED_V6_SCOPE)
1409 struct sockaddr_in6 lsa6;
1411 src = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)src,
1416 memcpy(dst, src, src->sa_len);
1418 switch (src->sa_family) {
1421 memcpy(dst, src, sizeof(struct sockaddr_in));
1426 memcpy(dst, src, sizeof(struct sockaddr_in6));
1429 #if defined(__Userspace__)
1431 memcpy(dst, src, sizeof(struct sockaddr_conn));
1445 sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp,
1446 struct sctp_tcb *stcb,
1448 struct sockaddr *addr,
1451 struct sctp_ifn *sctp_ifn;
1452 struct sctp_ifa *sctp_ifa;
1456 int ipv4_local_scope, ipv4_addr_legal;
1459 int local_scope, site_scope, ipv6_addr_legal;
1461 #if defined(__Userspace__)
1462 int conn_addr_legal;
1464 struct sctp_vrf *vrf;
1466 SCTP_IPI_ADDR_LOCK_ASSERT();
1472 /* Turn on all the appropriate scope */
1473 loopback_scope = stcb->asoc.scope.loopback_scope;
1475 ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope;
1476 ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal;
1479 local_scope = stcb->asoc.scope.local_scope;
1480 site_scope = stcb->asoc.scope.site_scope;
1481 ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal;
1483 #if defined(__Userspace__)
1484 conn_addr_legal = stcb->asoc.scope.conn_addr_legal;
1487 /* Use generic values for endpoints. */
1490 ipv4_local_scope = 1;
1496 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
1498 ipv6_addr_legal = 1;
1501 if (SCTP_IPV6_V6ONLY(inp)) {
1502 ipv4_addr_legal = 0;
1504 ipv4_addr_legal = 1;
1507 #if defined(__Userspace__)
1508 conn_addr_legal = 0;
1512 ipv6_addr_legal = 0;
1514 #if defined(__Userspace__)
1515 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_CONN) {
1516 conn_addr_legal = 1;
1518 ipv4_addr_legal = 0;
1521 conn_addr_legal = 0;
1523 ipv4_addr_legal = 1;
1528 ipv4_addr_legal = 1;
1533 vrf = sctp_find_vrf(vrf_id);
1537 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
1538 LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
1539 if ((loopback_scope == 0) &&
1540 SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
1541 /* Skip loopback if loopback_scope not set */
1544 LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
1547 * For the BOUND-ALL case, the list
1548 * associated with a TCB is Always
1549 * considered a reverse list.. i.e.
1550 * it lists addresses that are NOT
1551 * part of the association. If this
1552 * is one of those we must skip it.
1554 if (sctp_is_addr_restricted(stcb,
1559 switch (sctp_ifa->address.sa.sa_family) {
1562 if (ipv4_addr_legal) {
1563 struct sockaddr_in *sin;
1565 sin = &sctp_ifa->address.sin;
1566 if (sin->sin_addr.s_addr == 0) {
1568 * we skip unspecifed
1573 #if defined(__FreeBSD__) && !defined(__Userspace__)
1574 if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
1575 &sin->sin_addr) != 0) {
1579 if ((ipv4_local_scope == 0) &&
1580 (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) {
1584 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
1585 if (actual + sizeof(struct sockaddr_in6) > limit) {
1588 in6_sin_2_v4mapsin6(sin, (struct sockaddr_in6 *)&addr);
1589 ((struct sockaddr_in6 *)addr)->sin6_port = inp->sctp_lport;
1590 addr = (struct sockaddr *)((caddr_t)addr + sizeof(struct sockaddr_in6));
1591 actual += sizeof(struct sockaddr_in6);
1594 if (actual + sizeof(struct sockaddr_in) > limit) {
1597 memcpy(addr, sin, sizeof(struct sockaddr_in));
1598 ((struct sockaddr_in *)addr)->sin_port = inp->sctp_lport;
1599 addr = (struct sockaddr *)((caddr_t)addr + sizeof(struct sockaddr_in));
1600 actual += sizeof(struct sockaddr_in);
1611 if (ipv6_addr_legal) {
1612 struct sockaddr_in6 *sin6;
1614 #if defined(SCTP_EMBEDDED_V6_SCOPE) && !defined(SCTP_KAME)
1615 struct sockaddr_in6 lsa6;
1617 sin6 = &sctp_ifa->address.sin6;
1618 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
1620 * we skip unspecifed
1625 #if defined(__FreeBSD__) && !defined(__Userspace__)
1626 if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
1627 &sin6->sin6_addr) != 0) {
1631 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
1632 if (local_scope == 0)
1634 #if defined(SCTP_EMBEDDED_V6_SCOPE)
1635 if (sin6->sin6_scope_id == 0) {
1637 if (sa6_recoverscope(sin6) != 0)
1646 if (in6_recoverscope(&lsa6,
1656 #endif /* SCTP_KAME */
1658 #endif /* SCTP_EMBEDDED_V6_SCOPE */
1660 if ((site_scope == 0) &&
1661 (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) {
1664 if (actual + sizeof(struct sockaddr_in6) > limit) {
1667 memcpy(addr, sin6, sizeof(struct sockaddr_in6));
1668 ((struct sockaddr_in6 *)addr)->sin6_port = inp->sctp_lport;
1669 addr = (struct sockaddr *)((caddr_t)addr + sizeof(struct sockaddr_in6));
1670 actual += sizeof(struct sockaddr_in6);
1676 #if defined(__Userspace__)
1678 if (conn_addr_legal) {
1679 if (actual + sizeof(struct sockaddr_conn) > limit) {
1682 memcpy(addr, &sctp_ifa->address.sconn, sizeof(struct sockaddr_conn));
1683 ((struct sockaddr_conn *)addr)->sconn_port = inp->sctp_lport;
1684 addr = (struct sockaddr *)((caddr_t)addr + sizeof(struct sockaddr_conn));
1685 actual += sizeof(struct sockaddr_conn);
1697 struct sctp_laddr *laddr;
1700 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
1702 if (sctp_is_addr_restricted(stcb, laddr->ifa)) {
1707 sa_len = laddr->ifa->address.sa.sa_len;
1709 switch (laddr->ifa->address.sa.sa_family) {
1712 sa_len = sizeof(struct sockaddr_in);
1717 sa_len = sizeof(struct sockaddr_in6);
1720 #if defined(__Userspace__)
1722 sa_len = sizeof(struct sockaddr_conn);
1731 if (actual + sa_len > limit) {
1734 if (sctp_fill_user_address(addr, &laddr->ifa->address.sa))
1736 switch (laddr->ifa->address.sa.sa_family) {
1739 ((struct sockaddr_in *)addr)->sin_port = inp->sctp_lport;
1744 ((struct sockaddr_in6 *)addr)->sin6_port = inp->sctp_lport;
1747 #if defined(__Userspace__)
1749 ((struct sockaddr_conn *)addr)->sconn_port = inp->sctp_lport;
1756 addr = (struct sockaddr *)((caddr_t)addr + sa_len);
1764 sctp_fill_up_addresses(struct sctp_inpcb *inp,
1765 struct sctp_tcb *stcb,
1767 struct sockaddr *addr)
1774 SCTP_IPI_ADDR_RLOCK();
1777 * FIX ME: ?? this WILL report duplicate addresses if they appear
1778 * in more than one VRF.
1780 /* fill up addresses for all VRFs on the endpoint */
1781 for (id = 0; (id < inp->num_vrfs) && (size < limit); id++) {
1782 size += sctp_fill_up_addresses_vrf(inp, stcb, limit, addr,
1783 inp->m_vrf_ids[id]);
1784 addr = (struct sockaddr *)((caddr_t)addr + size);
1787 /* fill up addresses for the endpoint's default vrf */
1788 size = sctp_fill_up_addresses_vrf(inp, stcb, limit, addr,
1791 SCTP_IPI_ADDR_RUNLOCK();
1796 sctp_count_max_addresses_vrf(struct sctp_inpcb *inp, uint32_t vrf_id)
1799 struct sctp_vrf *vrf = NULL;
1802 * In both sub-set bound an bound_all cases we return the MAXIMUM
1803 * number of addresses that you COULD get. In reality the sub-set
1804 * bound may have an exclusion list for a given TCB OR in the
1805 * bound-all case a TCB may NOT include the loopback or other
1806 * addresses as well.
1808 SCTP_IPI_ADDR_LOCK_ASSERT();
1809 vrf = sctp_find_vrf(vrf_id);
1813 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
1814 struct sctp_ifn *sctp_ifn;
1815 struct sctp_ifa *sctp_ifa;
1817 LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
1818 LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
1819 /* Count them if they are the right type */
1820 switch (sctp_ifa->address.sa.sa_family) {
1824 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4))
1825 cnt += sizeof(struct sockaddr_in6);
1827 cnt += sizeof(struct sockaddr_in);
1829 cnt += sizeof(struct sockaddr_in);
1835 cnt += sizeof(struct sockaddr_in6);
1838 #if defined(__Userspace__)
1840 cnt += sizeof(struct sockaddr_conn);
1849 struct sctp_laddr *laddr;
1851 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
1852 switch (laddr->ifa->address.sa.sa_family) {
1856 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4))
1857 cnt += sizeof(struct sockaddr_in6);
1859 cnt += sizeof(struct sockaddr_in);
1861 cnt += sizeof(struct sockaddr_in);
1867 cnt += sizeof(struct sockaddr_in6);
1870 #if defined(__Userspace__)
1872 cnt += sizeof(struct sockaddr_conn);
1884 sctp_count_max_addresses(struct sctp_inpcb *inp)
1891 SCTP_IPI_ADDR_RLOCK();
1894 * FIX ME: ?? this WILL count duplicate addresses if they appear
1895 * in more than one VRF.
1897 /* count addresses for all VRFs on the endpoint */
1898 for (id = 0; id < inp->num_vrfs; id++) {
1899 cnt += sctp_count_max_addresses_vrf(inp, inp->m_vrf_ids[id]);
1902 /* count addresses for the endpoint's default VRF */
1903 cnt = sctp_count_max_addresses_vrf(inp, inp->def_vrf_id);
1905 SCTP_IPI_ADDR_RUNLOCK();
1910 sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
1911 size_t optsize, void *p, int delay)
1914 int creat_lock_on = 0;
1915 struct sctp_tcb *stcb = NULL;
1916 struct sockaddr *sa;
1917 unsigned int num_v6 = 0, num_v4 = 0, *totaddrp, totaddr;
1921 SCTPDBG(SCTP_DEBUG_PCB1, "Connectx called\n");
1923 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
1924 (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
1925 /* We are already connected AND the TCP model */
1926 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
1927 return (EADDRINUSE);
1930 if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
1931 (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
1932 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1936 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
1937 SCTP_INP_RLOCK(inp);
1938 stcb = LIST_FIRST(&inp->sctp_asoc_list);
1939 SCTP_INP_RUNLOCK(inp);
1942 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
1945 SCTP_INP_INCR_REF(inp);
1946 SCTP_ASOC_CREATE_LOCK(inp);
1948 if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
1949 (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
1950 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
1954 totaddrp = (unsigned int *)optval;
1955 totaddr = *totaddrp;
1956 sa = (struct sockaddr *)(totaddrp + 1);
1957 error = sctp_connectx_helper_find(inp, sa, totaddr, &num_v4, &num_v6, (unsigned int)(optsize - sizeof(int)));
1959 /* Already have or am bring up an association */
1960 SCTP_ASOC_CREATE_UNLOCK(inp);
1962 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
1966 if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
1971 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
1973 if (SCTP_IPV6_V6ONLY(inp)) {
1975 * if IPV6_V6ONLY flag, ignore connections destined
1976 * to a v4 addr or v4-mapped addr
1978 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1984 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
1985 SCTP_PCB_FLAGS_UNBOUND) {
1986 /* Bind a ephemeral port */
1987 error = sctp_inpcb_bind(so, NULL, NULL, p);
1993 /* FIX ME: do we want to pass in a vrf on the connect call? */
1994 vrf_id = inp->def_vrf_id;
1997 /* We are GOOD to go */
1998 stcb = sctp_aloc_assoc(inp, sa, &error, 0, vrf_id,
1999 inp->sctp_ep.pre_open_stream_count,
2001 #if defined(__FreeBSD__) && !defined(__Userspace__)
2003 #elif defined(_WIN32) && !defined(__Userspace__)
2008 SCTP_INITIALIZE_AUTH_PARAMS);
2010 /* Gak! no memory */
2013 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
2014 stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
2015 /* Set the connected flag so we can queue data */
2018 SCTP_SET_STATE(stcb, SCTP_STATE_COOKIE_WAIT);
2019 /* move to second address */
2020 switch (sa->sa_family) {
2023 sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in));
2028 sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in6));
2036 sctp_connectx_helper_add(stcb, sa, (totaddr-1), &error);
2037 /* Fill in the return id */
2041 a_id = (sctp_assoc_t *)optval;
2042 *a_id = sctp_get_associd(stcb);
2045 /* doing delayed connection */
2046 stcb->asoc.delayed_connection = 1;
2047 sctp_timer_start(SCTP_TIMER_TYPE_INIT, inp, stcb, stcb->asoc.primary_destination);
2049 (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
2050 sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
2052 SCTP_TCB_UNLOCK(stcb);
2054 if (creat_lock_on) {
2055 SCTP_ASOC_CREATE_UNLOCK(inp);
2057 SCTP_INP_DECR_REF(inp);
2061 #define SCTP_FIND_STCB(inp, stcb, assoc_id) { \
2062 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||\
2063 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { \
2064 SCTP_INP_RLOCK(inp); \
2065 stcb = LIST_FIRST(&inp->sctp_asoc_list); \
2067 SCTP_TCB_LOCK(stcb); \
2069 SCTP_INP_RUNLOCK(inp); \
2070 } else if (assoc_id > SCTP_ALL_ASSOC) { \
2071 stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1); \
2072 if (stcb == NULL) { \
2073 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT); \
2083 #define SCTP_CHECK_AND_CAST(destp, srcp, type, size) {\
2084 if (size < sizeof(type)) { \
2085 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); \
2089 destp = (type *)srcp; \
2093 #if defined(__Userspace__)
2098 sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
2100 struct sctp_inpcb *inp = NULL;
2102 struct sctp_tcb *stcb = NULL;
2104 if (optval == NULL) {
2105 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2109 inp = (struct sctp_inpcb *)so->so_pcb;
2111 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2118 case SCTP_AUTOCLOSE:
2119 case SCTP_EXPLICIT_EOR:
2120 case SCTP_AUTO_ASCONF:
2121 case SCTP_DISABLE_FRAGMENTS:
2122 case SCTP_I_WANT_MAPPED_V4_ADDR:
2123 case SCTP_USE_EXT_RCVINFO:
2124 SCTP_INP_RLOCK(inp);
2126 case SCTP_DISABLE_FRAGMENTS:
2127 val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NO_FRAGMENT);
2129 case SCTP_I_WANT_MAPPED_V4_ADDR:
2130 val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4);
2132 case SCTP_AUTO_ASCONF:
2133 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
2134 /* only valid for bound all sockets */
2135 val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTO_ASCONF);
2137 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2142 case SCTP_EXPLICIT_EOR:
2143 val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR);
2146 val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NODELAY);
2148 case SCTP_USE_EXT_RCVINFO:
2149 val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO);
2151 case SCTP_AUTOCLOSE:
2152 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE))
2153 val = sctp_ticks_to_secs(inp->sctp_ep.auto_close_time);
2159 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
2160 error = ENOPROTOOPT;
2161 } /* end switch (sopt->sopt_name) */
2162 if (*optsize < sizeof(val)) {
2163 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2167 SCTP_INP_RUNLOCK(inp);
2169 /* return the option value */
2170 *(int *)optval = val;
2171 *optsize = sizeof(val);
2174 case SCTP_GET_PACKET_LOG:
2176 #ifdef SCTP_PACKET_LOGGING
2180 SCTP_CHECK_AND_CAST(target, optval, uint8_t, *optsize);
2181 ret = sctp_copy_out_packet_log(target , (int)*optsize);
2184 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
2189 case SCTP_REUSE_PORT:
2193 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
2194 /* Can't do this for a 1-m socket */
2198 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2199 *value = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE);
2200 *optsize = sizeof(uint32_t);
2203 case SCTP_PARTIAL_DELIVERY_POINT:
2207 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2208 *value = inp->partial_delivery_point;
2209 *optsize = sizeof(uint32_t);
2212 case SCTP_FRAGMENT_INTERLEAVE:
2216 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2217 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE)) {
2218 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS)) {
2219 *value = SCTP_FRAG_LEVEL_2;
2221 *value = SCTP_FRAG_LEVEL_1;
2224 *value = SCTP_FRAG_LEVEL_0;
2226 *optsize = sizeof(uint32_t);
2229 case SCTP_INTERLEAVING_SUPPORTED:
2231 struct sctp_assoc_value *av;
2233 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2234 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2237 av->assoc_value = stcb->asoc.idata_supported;
2238 SCTP_TCB_UNLOCK(stcb);
2240 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2241 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2242 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
2243 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
2244 SCTP_INP_RLOCK(inp);
2245 if (inp->idata_supported) {
2246 av->assoc_value = 1;
2248 av->assoc_value = 0;
2250 SCTP_INP_RUNLOCK(inp);
2252 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2257 *optsize = sizeof(struct sctp_assoc_value);
2261 case SCTP_CMT_ON_OFF:
2263 struct sctp_assoc_value *av;
2265 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2266 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2268 av->assoc_value = stcb->asoc.sctp_cmt_on_off;
2269 SCTP_TCB_UNLOCK(stcb);
2271 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2272 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2273 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
2274 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
2275 SCTP_INP_RLOCK(inp);
2276 av->assoc_value = inp->sctp_cmt_on_off;
2277 SCTP_INP_RUNLOCK(inp);
2279 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2284 *optsize = sizeof(struct sctp_assoc_value);
2288 case SCTP_PLUGGABLE_CC:
2290 struct sctp_assoc_value *av;
2292 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2293 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2295 av->assoc_value = stcb->asoc.congestion_control_module;
2296 SCTP_TCB_UNLOCK(stcb);
2298 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2299 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2300 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
2301 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
2302 SCTP_INP_RLOCK(inp);
2303 av->assoc_value = inp->sctp_ep.sctp_default_cc_module;
2304 SCTP_INP_RUNLOCK(inp);
2306 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2311 *optsize = sizeof(struct sctp_assoc_value);
2315 case SCTP_CC_OPTION:
2317 struct sctp_cc_option *cc_opt;
2319 SCTP_CHECK_AND_CAST(cc_opt, optval, struct sctp_cc_option, *optsize);
2320 SCTP_FIND_STCB(inp, stcb, cc_opt->aid_value.assoc_id);
2324 if (stcb->asoc.cc_functions.sctp_cwnd_socket_option == NULL) {
2327 error = (*stcb->asoc.cc_functions.sctp_cwnd_socket_option)(stcb, 0, cc_opt);
2328 *optsize = sizeof(struct sctp_cc_option);
2330 SCTP_TCB_UNLOCK(stcb);
2334 case SCTP_PLUGGABLE_SS:
2336 struct sctp_assoc_value *av;
2338 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2339 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2341 av->assoc_value = stcb->asoc.stream_scheduling_module;
2342 SCTP_TCB_UNLOCK(stcb);
2344 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2345 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2346 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
2347 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
2348 SCTP_INP_RLOCK(inp);
2349 av->assoc_value = inp->sctp_ep.sctp_default_ss_module;
2350 SCTP_INP_RUNLOCK(inp);
2352 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2357 *optsize = sizeof(struct sctp_assoc_value);
2363 struct sctp_stream_value *av;
2365 SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, *optsize);
2366 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2368 if ((av->stream_id >= stcb->asoc.streamoutcnt) ||
2369 (stcb->asoc.ss_functions.sctp_ss_get_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id],
2370 &av->stream_value) < 0)) {
2371 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2374 *optsize = sizeof(struct sctp_stream_value);
2376 SCTP_TCB_UNLOCK(stcb);
2378 /* Can't get stream value without association */
2379 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2384 case SCTP_GET_ADDR_LEN:
2386 struct sctp_assoc_value *av;
2388 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2391 if (av->assoc_value == AF_INET) {
2392 av->assoc_value = sizeof(struct sockaddr_in);
2397 if (av->assoc_value == AF_INET6) {
2398 av->assoc_value = sizeof(struct sockaddr_in6);
2402 #if defined(__Userspace__)
2403 if (av->assoc_value == AF_CONN) {
2404 av->assoc_value = sizeof(struct sockaddr_conn);
2409 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2411 *optsize = sizeof(struct sctp_assoc_value);
2415 case SCTP_GET_ASSOC_NUMBER:
2417 uint32_t *value, cnt;
2419 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2420 SCTP_INP_RLOCK(inp);
2421 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2422 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
2423 /* Can't do this for a 1-1 socket */
2425 SCTP_INP_RUNLOCK(inp);
2429 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
2432 SCTP_INP_RUNLOCK(inp);
2434 *optsize = sizeof(uint32_t);
2437 case SCTP_GET_ASSOC_ID_LIST:
2439 struct sctp_assoc_ids *ids;
2443 SCTP_CHECK_AND_CAST(ids, optval, struct sctp_assoc_ids, *optsize);
2444 SCTP_INP_RLOCK(inp);
2445 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2446 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
2447 /* Can't do this for a 1-1 socket */
2449 SCTP_INP_RUNLOCK(inp);
2453 limit = (*optsize - sizeof(uint32_t)) / sizeof(sctp_assoc_t);
2454 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
2456 ids->gaids_assoc_id[at++] = sctp_get_associd(stcb);
2459 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2464 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2468 SCTP_INP_RUNLOCK(inp);
2470 ids->gaids_number_of_ids = at;
2471 *optsize = ((at * sizeof(sctp_assoc_t)) + sizeof(uint32_t));
2477 struct sctp_assoc_value *av;
2479 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2480 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2483 av->assoc_value = stcb->asoc.context;
2484 SCTP_TCB_UNLOCK(stcb);
2486 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2487 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2488 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
2489 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
2490 SCTP_INP_RLOCK(inp);
2491 av->assoc_value = inp->sctp_context;
2492 SCTP_INP_RUNLOCK(inp);
2494 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2499 *optsize = sizeof(struct sctp_assoc_value);
2505 uint32_t *default_vrfid;
2507 SCTP_CHECK_AND_CAST(default_vrfid, optval, uint32_t, *optsize);
2508 *default_vrfid = inp->def_vrf_id;
2509 *optsize = sizeof(uint32_t);
2512 case SCTP_GET_ASOC_VRF:
2514 struct sctp_assoc_value *id;
2516 SCTP_CHECK_AND_CAST(id, optval, struct sctp_assoc_value, *optsize);
2517 SCTP_FIND_STCB(inp, stcb, id->assoc_id);
2520 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2522 id->assoc_value = stcb->asoc.vrf_id;
2523 SCTP_TCB_UNLOCK(stcb);
2524 *optsize = sizeof(struct sctp_assoc_value);
2528 case SCTP_GET_VRF_IDS:
2534 SCTP_CHECK_AND_CAST(vrf_ids, optval, uint32_t, *optsize);
2535 siz_needed = inp->num_vrfs * sizeof(uint32_t);
2536 if (*optsize < siz_needed) {
2538 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2540 memcpy(vrf_ids, inp->m_vrf_ids, siz_needed);
2541 *optsize = siz_needed;
2544 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
2549 case SCTP_GET_NONCE_VALUES:
2551 struct sctp_get_nonce_values *gnv;
2553 SCTP_CHECK_AND_CAST(gnv, optval, struct sctp_get_nonce_values, *optsize);
2554 SCTP_FIND_STCB(inp, stcb, gnv->gn_assoc_id);
2557 gnv->gn_peers_tag = stcb->asoc.peer_vtag;
2558 gnv->gn_local_tag = stcb->asoc.my_vtag;
2559 SCTP_TCB_UNLOCK(stcb);
2560 *optsize = sizeof(struct sctp_get_nonce_values);
2562 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
2567 case SCTP_DELAYED_SACK:
2569 struct sctp_sack_info *sack;
2571 SCTP_CHECK_AND_CAST(sack, optval, struct sctp_sack_info, *optsize);
2572 SCTP_FIND_STCB(inp, stcb, sack->sack_assoc_id);
2574 sack->sack_delay = stcb->asoc.delayed_ack;
2575 sack->sack_freq = stcb->asoc.sack_freq;
2576 SCTP_TCB_UNLOCK(stcb);
2578 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2579 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2580 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
2581 (sack->sack_assoc_id == SCTP_FUTURE_ASSOC))) {
2582 SCTP_INP_RLOCK(inp);
2583 sack->sack_delay = sctp_ticks_to_msecs(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
2584 sack->sack_freq = inp->sctp_ep.sctp_sack_freq;
2585 SCTP_INP_RUNLOCK(inp);
2587 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2592 *optsize = sizeof(struct sctp_sack_info);
2596 case SCTP_GET_SNDBUF_USE:
2598 struct sctp_sockstat *ss;
2600 SCTP_CHECK_AND_CAST(ss, optval, struct sctp_sockstat, *optsize);
2601 SCTP_FIND_STCB(inp, stcb, ss->ss_assoc_id);
2604 ss->ss_total_sndbuf = stcb->asoc.total_output_queue_size;
2605 ss->ss_total_recv_buf = (stcb->asoc.size_on_reasm_queue +
2606 stcb->asoc.size_on_all_streams);
2607 SCTP_TCB_UNLOCK(stcb);
2608 *optsize = sizeof(struct sctp_sockstat);
2610 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
2615 case SCTP_MAX_BURST:
2617 struct sctp_assoc_value *av;
2619 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2620 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2623 av->assoc_value = stcb->asoc.max_burst;
2624 SCTP_TCB_UNLOCK(stcb);
2626 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2627 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2628 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
2629 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
2630 SCTP_INP_RLOCK(inp);
2631 av->assoc_value = inp->sctp_ep.max_burst;
2632 SCTP_INP_RUNLOCK(inp);
2634 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2639 *optsize = sizeof(struct sctp_assoc_value);
2645 struct sctp_assoc_value *av;
2648 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2649 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2652 av->assoc_value = sctp_get_frag_point(stcb, &stcb->asoc);
2653 SCTP_TCB_UNLOCK(stcb);
2655 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2656 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2657 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
2658 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
2659 SCTP_INP_RLOCK(inp);
2660 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
2661 ovh = SCTP_MED_OVERHEAD;
2663 ovh = SCTP_MED_V4_OVERHEAD;
2665 if (inp->sctp_frag_point >= SCTP_DEFAULT_MAXSEGMENT)
2666 av->assoc_value = 0;
2668 av->assoc_value = inp->sctp_frag_point - ovh;
2669 SCTP_INP_RUNLOCK(inp);
2671 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2676 *optsize = sizeof(struct sctp_assoc_value);
2680 case SCTP_GET_STAT_LOG:
2681 error = sctp_fill_stat_log(optval, optsize);
2685 struct sctp_event_subscribe *events;
2687 SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, *optsize);
2688 memset(events, 0, sizeof(struct sctp_event_subscribe));
2689 SCTP_INP_RLOCK(inp);
2690 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT))
2691 events->sctp_data_io_event = 1;
2693 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT))
2694 events->sctp_association_event = 1;
2696 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVPADDREVNT))
2697 events->sctp_address_event = 1;
2699 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT))
2700 events->sctp_send_failure_event = 1;
2702 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVPEERERR))
2703 events->sctp_peer_error_event = 1;
2705 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT))
2706 events->sctp_shutdown_event = 1;
2708 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT))
2709 events->sctp_partial_delivery_event = 1;
2711 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT))
2712 events->sctp_adaptation_layer_event = 1;
2714 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT))
2715 events->sctp_authentication_event = 1;
2717 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT))
2718 events->sctp_sender_dry_event = 1;
2720 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT))
2721 events->sctp_stream_reset_event = 1;
2722 SCTP_INP_RUNLOCK(inp);
2723 *optsize = sizeof(struct sctp_event_subscribe);
2726 case SCTP_ADAPTATION_LAYER:
2730 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2732 SCTP_INP_RLOCK(inp);
2733 *value = inp->sctp_ep.adaptation_layer_indicator;
2734 SCTP_INP_RUNLOCK(inp);
2735 *optsize = sizeof(uint32_t);
2738 case SCTP_SET_INITIAL_DBG_SEQ:
2742 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2743 SCTP_INP_RLOCK(inp);
2744 *value = inp->sctp_ep.initial_sequence_debug;
2745 SCTP_INP_RUNLOCK(inp);
2746 *optsize = sizeof(uint32_t);
2749 case SCTP_GET_LOCAL_ADDR_SIZE:
2753 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2754 SCTP_INP_RLOCK(inp);
2755 *value = sctp_count_max_addresses(inp);
2756 SCTP_INP_RUNLOCK(inp);
2757 *optsize = sizeof(uint32_t);
2760 case SCTP_GET_REMOTE_ADDR_SIZE:
2764 struct sctp_nets *net;
2766 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2767 /* FIXME MT: change to sctp_assoc_value? */
2768 SCTP_FIND_STCB(inp, stcb, (sctp_assoc_t) *value);
2772 /* Count the sizes */
2773 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
2774 switch (net->ro._l_addr.sa.sa_family) {
2778 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
2779 size += sizeof(struct sockaddr_in6);
2781 size += sizeof(struct sockaddr_in);
2784 size += sizeof(struct sockaddr_in);
2790 size += sizeof(struct sockaddr_in6);
2793 #if defined(__Userspace__)
2795 size += sizeof(struct sockaddr_conn);
2802 SCTP_TCB_UNLOCK(stcb);
2803 *value = (uint32_t) size;
2804 *optsize = sizeof(uint32_t);
2806 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
2811 case SCTP_GET_PEER_ADDRESSES:
2813 * Get the address information, an array is passed in to
2814 * fill up we pack it.
2818 struct sockaddr *addr;
2819 struct sctp_nets *net;
2820 struct sctp_getaddresses *saddr;
2822 SCTP_CHECK_AND_CAST(saddr, optval, struct sctp_getaddresses, *optsize);
2823 SCTP_FIND_STCB(inp, stcb, saddr->sget_assoc_id);
2826 left = *optsize - offsetof(struct sctp_getaddresses, addr);
2827 *optsize = offsetof(struct sctp_getaddresses, addr);
2828 addr = &saddr->addr[0].sa;
2830 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
2831 switch (net->ro._l_addr.sa.sa_family) {
2835 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
2836 cpsz = sizeof(struct sockaddr_in6);
2838 cpsz = sizeof(struct sockaddr_in);
2841 cpsz = sizeof(struct sockaddr_in);
2847 cpsz = sizeof(struct sockaddr_in6);
2850 #if defined(__Userspace__)
2852 cpsz = sizeof(struct sockaddr_conn);
2863 /* not enough room. */
2866 #if defined(INET) && defined(INET6)
2867 if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) &&
2868 (net->ro._l_addr.sa.sa_family == AF_INET)) {
2869 /* Must map the address */
2870 in6_sin_2_v4mapsin6(&net->ro._l_addr.sin,
2871 (struct sockaddr_in6 *)&addr);
2873 memcpy(addr, &net->ro._l_addr, cpsz);
2876 memcpy(addr, &net->ro._l_addr, cpsz);
2878 ((struct sockaddr_in *)addr)->sin_port = stcb->rport;
2880 addr = (struct sockaddr *)((caddr_t)addr + cpsz);
2884 SCTP_TCB_UNLOCK(stcb);
2886 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
2891 case SCTP_GET_LOCAL_ADDRESSES:
2893 size_t limit, actual;
2894 struct sctp_getaddresses *saddr;
2896 SCTP_CHECK_AND_CAST(saddr, optval, struct sctp_getaddresses, *optsize);
2897 SCTP_FIND_STCB(inp, stcb, saddr->sget_assoc_id);
2899 limit = *optsize - offsetof(struct sctp_getaddresses, addr);
2900 actual = sctp_fill_up_addresses(inp, stcb, limit, &saddr->addr[0].sa);
2902 SCTP_TCB_UNLOCK(stcb);
2904 *optsize = offsetof(struct sctp_getaddresses, addr) + actual;
2907 case SCTP_PEER_ADDR_PARAMS:
2909 struct sctp_paddrparams *paddrp;
2910 struct sctp_nets *net;
2911 struct sockaddr *addr;
2912 #if defined(INET) && defined(INET6)
2913 struct sockaddr_in sin_store;
2916 SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, *optsize);
2917 SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
2919 #if defined(INET) && defined(INET6)
2920 if (paddrp->spp_address.ss_family == AF_INET6) {
2921 struct sockaddr_in6 *sin6;
2923 sin6 = (struct sockaddr_in6 *)&paddrp->spp_address;
2924 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
2925 in6_sin6_2_sin(&sin_store, sin6);
2926 addr = (struct sockaddr *)&sin_store;
2928 addr = (struct sockaddr *)&paddrp->spp_address;
2931 addr = (struct sockaddr *)&paddrp->spp_address;
2934 addr = (struct sockaddr *)&paddrp->spp_address;
2937 net = sctp_findnet(stcb, addr);
2939 /* We increment here since sctp_findassociation_ep_addr() wil
2940 * do a decrement if it finds the stcb as long as the locked
2941 * tcb (last argument) is NOT a TCB.. aka NULL.
2944 SCTP_INP_INCR_REF(inp);
2945 stcb = sctp_findassociation_ep_addr(&inp, addr, &net, NULL, NULL);
2947 SCTP_INP_DECR_REF(inp);
2950 if ((stcb != NULL) && (net == NULL)) {
2952 if (addr->sa_family == AF_INET) {
2953 struct sockaddr_in *sin;
2955 sin = (struct sockaddr_in *)addr;
2956 if (sin->sin_addr.s_addr != INADDR_ANY) {
2958 SCTP_TCB_UNLOCK(stcb);
2959 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2965 if (addr->sa_family == AF_INET6) {
2966 struct sockaddr_in6 *sin6;
2968 sin6 = (struct sockaddr_in6 *)addr;
2969 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
2971 SCTP_TCB_UNLOCK(stcb);
2972 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2977 #if defined(__Userspace__)
2978 if (addr->sa_family == AF_CONN) {
2979 struct sockaddr_conn *sconn;
2981 sconn = (struct sockaddr_conn *)addr;
2982 if (sconn->sconn_addr != NULL) {
2984 SCTP_TCB_UNLOCK(stcb);
2985 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2991 error = EAFNOSUPPORT;
2992 SCTP_TCB_UNLOCK(stcb);
2993 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2999 /* Applies to the specific association */
3000 paddrp->spp_flags = 0;
3002 paddrp->spp_hbinterval = net->heart_beat_delay;
3003 paddrp->spp_pathmaxrxt = net->failure_threshold;
3004 paddrp->spp_pathmtu = net->mtu;
3005 switch (net->ro._l_addr.sa.sa_family) {
3008 paddrp->spp_pathmtu -= SCTP_MIN_V4_OVERHEAD;
3013 paddrp->spp_pathmtu -= SCTP_MIN_OVERHEAD;
3016 #if defined(__Userspace__)
3018 paddrp->spp_pathmtu -= sizeof(struct sctphdr);
3024 /* get flags for HB */
3025 if (net->dest_state & SCTP_ADDR_NOHB) {
3026 paddrp->spp_flags |= SPP_HB_DISABLE;
3028 paddrp->spp_flags |= SPP_HB_ENABLE;
3030 /* get flags for PMTU */
3031 if (net->dest_state & SCTP_ADDR_NO_PMTUD) {
3032 paddrp->spp_flags |= SPP_PMTUD_DISABLE;
3034 paddrp->spp_flags |= SPP_PMTUD_ENABLE;
3036 if (net->dscp & 0x01) {
3037 paddrp->spp_dscp = net->dscp & 0xfc;
3038 paddrp->spp_flags |= SPP_DSCP;
3041 if ((net->ro._l_addr.sa.sa_family == AF_INET6) &&
3042 (net->flowlabel & 0x80000000)) {
3043 paddrp->spp_ipv6_flowlabel = net->flowlabel & 0x000fffff;
3044 paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
3049 * No destination so return default
3052 paddrp->spp_pathmaxrxt = stcb->asoc.def_net_failure;
3053 paddrp->spp_pathmtu = stcb->asoc.default_mtu;
3054 if (stcb->asoc.default_dscp & 0x01) {
3055 paddrp->spp_dscp = stcb->asoc.default_dscp & 0xfc;
3056 paddrp->spp_flags |= SPP_DSCP;
3059 if (stcb->asoc.default_flowlabel & 0x80000000) {
3060 paddrp->spp_ipv6_flowlabel = stcb->asoc.default_flowlabel & 0x000fffff;
3061 paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
3064 /* default settings should be these */
3065 if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
3066 paddrp->spp_flags |= SPP_HB_DISABLE;
3068 paddrp->spp_flags |= SPP_HB_ENABLE;
3070 if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD)) {
3071 paddrp->spp_flags |= SPP_PMTUD_DISABLE;
3073 paddrp->spp_flags |= SPP_PMTUD_ENABLE;
3075 paddrp->spp_hbinterval = stcb->asoc.heart_beat_delay;
3077 paddrp->spp_assoc_id = sctp_get_associd(stcb);
3078 SCTP_TCB_UNLOCK(stcb);
3080 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3081 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3082 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3083 (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC))) {
3084 /* Use endpoint defaults */
3085 SCTP_INP_RLOCK(inp);
3086 paddrp->spp_pathmaxrxt = inp->sctp_ep.def_net_failure;
3087 paddrp->spp_hbinterval = sctp_ticks_to_msecs(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]);
3088 paddrp->spp_assoc_id = SCTP_FUTURE_ASSOC;
3089 /* get inp's default */
3090 if (inp->sctp_ep.default_dscp & 0x01) {
3091 paddrp->spp_dscp = inp->sctp_ep.default_dscp & 0xfc;
3092 paddrp->spp_flags |= SPP_DSCP;
3095 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
3096 (inp->sctp_ep.default_flowlabel & 0x80000000)) {
3097 paddrp->spp_ipv6_flowlabel = inp->sctp_ep.default_flowlabel & 0x000fffff;
3098 paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
3101 paddrp->spp_pathmtu = inp->sctp_ep.default_mtu;
3103 if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
3104 paddrp->spp_flags |= SPP_HB_ENABLE;
3106 paddrp->spp_flags |= SPP_HB_DISABLE;
3108 if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD)) {
3109 paddrp->spp_flags |= SPP_PMTUD_ENABLE;
3111 paddrp->spp_flags |= SPP_PMTUD_DISABLE;
3113 SCTP_INP_RUNLOCK(inp);
3115 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3120 *optsize = sizeof(struct sctp_paddrparams);
3124 case SCTP_GET_PEER_ADDR_INFO:
3126 struct sctp_paddrinfo *paddri;
3127 struct sctp_nets *net;
3128 struct sockaddr *addr;
3129 #if defined(INET) && defined(INET6)
3130 struct sockaddr_in sin_store;
3133 SCTP_CHECK_AND_CAST(paddri, optval, struct sctp_paddrinfo, *optsize);
3134 SCTP_FIND_STCB(inp, stcb, paddri->spinfo_assoc_id);
3136 #if defined(INET) && defined(INET6)
3137 if (paddri->spinfo_address.ss_family == AF_INET6) {
3138 struct sockaddr_in6 *sin6;
3140 sin6 = (struct sockaddr_in6 *)&paddri->spinfo_address;
3141 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
3142 in6_sin6_2_sin(&sin_store, sin6);
3143 addr = (struct sockaddr *)&sin_store;
3145 addr = (struct sockaddr *)&paddri->spinfo_address;
3148 addr = (struct sockaddr *)&paddri->spinfo_address;
3151 addr = (struct sockaddr *)&paddri->spinfo_address;
3154 net = sctp_findnet(stcb, addr);
3156 /* We increment here since sctp_findassociation_ep_addr() wil
3157 * do a decrement if it finds the stcb as long as the locked
3158 * tcb (last argument) is NOT a TCB.. aka NULL.
3161 SCTP_INP_INCR_REF(inp);
3162 stcb = sctp_findassociation_ep_addr(&inp, addr, &net, NULL, NULL);
3164 SCTP_INP_DECR_REF(inp);
3168 if ((stcb != NULL) && (net != NULL)) {
3169 if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
3170 /* It's unconfirmed */
3171 paddri->spinfo_state = SCTP_UNCONFIRMED;
3172 } else if (net->dest_state & SCTP_ADDR_REACHABLE) {
3174 paddri->spinfo_state = SCTP_ACTIVE;
3177 paddri->spinfo_state = SCTP_INACTIVE;
3179 paddri->spinfo_cwnd = net->cwnd;
3180 paddri->spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT;
3181 paddri->spinfo_rto = net->RTO;
3182 paddri->spinfo_assoc_id = sctp_get_associd(stcb);
3183 paddri->spinfo_mtu = net->mtu;
3184 switch (addr->sa_family) {
3187 paddri->spinfo_mtu -= SCTP_MIN_V4_OVERHEAD;
3192 paddri->spinfo_mtu -= SCTP_MIN_OVERHEAD;
3195 #if defined(__Userspace__)
3197 paddri->spinfo_mtu -= sizeof(struct sctphdr);
3203 SCTP_TCB_UNLOCK(stcb);
3204 *optsize = sizeof(struct sctp_paddrinfo);
3207 SCTP_TCB_UNLOCK(stcb);
3209 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
3214 case SCTP_PCB_STATUS:
3216 struct sctp_pcbinfo *spcb;
3218 SCTP_CHECK_AND_CAST(spcb, optval, struct sctp_pcbinfo, *optsize);
3219 sctp_fill_pcbinfo(spcb);
3220 *optsize = sizeof(struct sctp_pcbinfo);
3225 struct sctp_nets *net;
3226 struct sctp_status *sstat;
3228 SCTP_CHECK_AND_CAST(sstat, optval, struct sctp_status, *optsize);
3229 SCTP_FIND_STCB(inp, stcb, sstat->sstat_assoc_id);
3232 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3236 sstat->sstat_state = sctp_map_assoc_state(stcb->asoc.state);
3237 sstat->sstat_assoc_id = sctp_get_associd(stcb);
3238 sstat->sstat_rwnd = stcb->asoc.peers_rwnd;
3239 sstat->sstat_unackdata = stcb->asoc.sent_queue_cnt;
3241 * We can't include chunks that have been passed to
3242 * the socket layer. Only things in queue.
3244 sstat->sstat_penddata = (stcb->asoc.cnt_on_reasm_queue +
3245 stcb->asoc.cnt_on_all_streams);
3248 sstat->sstat_instrms = stcb->asoc.streamincnt;
3249 sstat->sstat_outstrms = stcb->asoc.streamoutcnt;
3250 sstat->sstat_fragmentation_point = sctp_get_frag_point(stcb, &stcb->asoc);
3251 net = stcb->asoc.primary_destination;
3254 memcpy(&sstat->sstat_primary.spinfo_address,
3256 ((struct sockaddr *)(&net->ro._l_addr))->sa_len);
3258 switch (stcb->asoc.primary_destination->ro._l_addr.sa.sa_family) {
3261 memcpy(&sstat->sstat_primary.spinfo_address,
3263 sizeof(struct sockaddr_in));
3268 memcpy(&sstat->sstat_primary.spinfo_address,
3270 sizeof(struct sockaddr_in6));
3273 #if defined(__Userspace__)
3275 memcpy(&sstat->sstat_primary.spinfo_address,
3277 sizeof(struct sockaddr_conn));
3284 ((struct sockaddr_in *)&sstat->sstat_primary.spinfo_address)->sin_port = stcb->rport;
3286 * Again the user can get info from sctp_constants.h
3287 * for what the state of the network is.
3289 if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
3290 /* It's unconfirmed */
3291 sstat->sstat_primary.spinfo_state = SCTP_UNCONFIRMED;
3292 } else if (net->dest_state & SCTP_ADDR_REACHABLE) {
3294 sstat->sstat_primary.spinfo_state = SCTP_ACTIVE;
3297 sstat->sstat_primary.spinfo_state = SCTP_INACTIVE;
3299 sstat->sstat_primary.spinfo_cwnd = net->cwnd;
3300 sstat->sstat_primary.spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT;
3301 sstat->sstat_primary.spinfo_rto = net->RTO;
3302 sstat->sstat_primary.spinfo_mtu = net->mtu;
3303 switch (stcb->asoc.primary_destination->ro._l_addr.sa.sa_family) {
3306 sstat->sstat_primary.spinfo_mtu -= SCTP_MIN_V4_OVERHEAD;
3311 sstat->sstat_primary.spinfo_mtu -= SCTP_MIN_OVERHEAD;
3314 #if defined(__Userspace__)
3316 sstat->sstat_primary.spinfo_mtu -= sizeof(struct sctphdr);
3323 memset(&sstat->sstat_primary, 0, sizeof(struct sctp_paddrinfo));
3325 sstat->sstat_primary.spinfo_assoc_id = sctp_get_associd(stcb);
3326 SCTP_TCB_UNLOCK(stcb);
3327 *optsize = sizeof(struct sctp_status);
3332 struct sctp_rtoinfo *srto;
3334 SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, *optsize);
3335 SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
3338 srto->srto_initial = stcb->asoc.initial_rto;
3339 srto->srto_max = stcb->asoc.maxrto;
3340 srto->srto_min = stcb->asoc.minrto;
3341 SCTP_TCB_UNLOCK(stcb);
3343 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3344 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3345 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3346 (srto->srto_assoc_id == SCTP_FUTURE_ASSOC))) {
3347 SCTP_INP_RLOCK(inp);
3348 srto->srto_initial = inp->sctp_ep.initial_rto;
3349 srto->srto_max = inp->sctp_ep.sctp_maxrto;
3350 srto->srto_min = inp->sctp_ep.sctp_minrto;
3351 SCTP_INP_RUNLOCK(inp);
3353 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3358 *optsize = sizeof(struct sctp_rtoinfo);
3364 struct sctp_timeouts *stimo;
3366 SCTP_CHECK_AND_CAST(stimo, optval, struct sctp_timeouts, *optsize);
3367 SCTP_FIND_STCB(inp, stcb, stimo->stimo_assoc_id);
3370 stimo->stimo_init= stcb->asoc.timoinit;
3371 stimo->stimo_data= stcb->asoc.timodata;
3372 stimo->stimo_sack= stcb->asoc.timosack;
3373 stimo->stimo_shutdown= stcb->asoc.timoshutdown;
3374 stimo->stimo_heartbeat= stcb->asoc.timoheartbeat;
3375 stimo->stimo_cookie= stcb->asoc.timocookie;
3376 stimo->stimo_shutdownack= stcb->asoc.timoshutdownack;
3377 SCTP_TCB_UNLOCK(stcb);
3378 *optsize = sizeof(struct sctp_timeouts);
3380 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3385 case SCTP_ASSOCINFO:
3387 struct sctp_assocparams *sasoc;
3389 SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, *optsize);
3390 SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
3393 sasoc->sasoc_cookie_life = sctp_ticks_to_msecs(stcb->asoc.cookie_life);
3394 sasoc->sasoc_asocmaxrxt = stcb->asoc.max_send_times;
3395 sasoc->sasoc_number_peer_destinations = stcb->asoc.numnets;
3396 sasoc->sasoc_peer_rwnd = stcb->asoc.peers_rwnd;
3397 sasoc->sasoc_local_rwnd = stcb->asoc.my_rwnd;
3398 SCTP_TCB_UNLOCK(stcb);
3400 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3401 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3402 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3403 (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC))) {
3404 SCTP_INP_RLOCK(inp);
3405 sasoc->sasoc_cookie_life = sctp_ticks_to_msecs(inp->sctp_ep.def_cookie_life);
3406 sasoc->sasoc_asocmaxrxt = inp->sctp_ep.max_send_times;
3407 sasoc->sasoc_number_peer_destinations = 0;
3408 sasoc->sasoc_peer_rwnd = 0;
3409 sasoc->sasoc_local_rwnd = sbspace(&inp->sctp_socket->so_rcv);
3410 SCTP_INP_RUNLOCK(inp);
3412 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3417 *optsize = sizeof(struct sctp_assocparams);
3421 case SCTP_DEFAULT_SEND_PARAM:
3423 struct sctp_sndrcvinfo *s_info;
3425 SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, *optsize);
3426 SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
3429 memcpy(s_info, &stcb->asoc.def_send, sizeof(stcb->asoc.def_send));
3430 SCTP_TCB_UNLOCK(stcb);
3432 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3433 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3434 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3435 (s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC))) {
3436 SCTP_INP_RLOCK(inp);
3437 memcpy(s_info, &inp->def_send, sizeof(inp->def_send));
3438 SCTP_INP_RUNLOCK(inp);
3440 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3445 *optsize = sizeof(struct sctp_sndrcvinfo);
3451 struct sctp_initmsg *sinit;
3453 SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, *optsize);
3454 SCTP_INP_RLOCK(inp);
3455 sinit->sinit_num_ostreams = inp->sctp_ep.pre_open_stream_count;
3456 sinit->sinit_max_instreams = inp->sctp_ep.max_open_streams_intome;
3457 sinit->sinit_max_attempts = inp->sctp_ep.max_init_times;
3458 sinit->sinit_max_init_timeo = inp->sctp_ep.initial_init_rto_max;
3459 SCTP_INP_RUNLOCK(inp);
3460 *optsize = sizeof(struct sctp_initmsg);
3463 case SCTP_PRIMARY_ADDR:
3464 /* we allow a "get" operation on this */
3466 struct sctp_setprim *ssp;
3468 SCTP_CHECK_AND_CAST(ssp, optval, struct sctp_setprim, *optsize);
3469 SCTP_FIND_STCB(inp, stcb, ssp->ssp_assoc_id);
3472 union sctp_sockstore *addr;
3474 addr = &stcb->asoc.primary_destination->ro._l_addr;
3475 switch (addr->sa.sa_family) {
3479 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
3480 in6_sin_2_v4mapsin6(&addr->sin,
3481 (struct sockaddr_in6 *)&ssp->ssp_addr);
3483 memcpy(&ssp->ssp_addr, &addr->sin, sizeof(struct sockaddr_in));
3486 memcpy(&ssp->ssp_addr, &addr->sin, sizeof(struct sockaddr_in));
3492 memcpy(&ssp->ssp_addr, &addr->sin6, sizeof(struct sockaddr_in6));
3495 #if defined(__Userspace__)
3497 memcpy(&ssp->ssp_addr, &addr->sconn, sizeof(struct sockaddr_conn));
3503 SCTP_TCB_UNLOCK(stcb);
3504 *optsize = sizeof(struct sctp_setprim);
3506 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3511 case SCTP_HMAC_IDENT:
3513 struct sctp_hmacalgo *shmac;
3514 sctp_hmaclist_t *hmaclist;
3518 SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, *optsize);
3520 SCTP_INP_RLOCK(inp);
3521 hmaclist = inp->sctp_ep.local_hmacs;
3522 if (hmaclist == NULL) {
3523 /* no HMACs to return */
3524 *optsize = sizeof(*shmac);
3525 SCTP_INP_RUNLOCK(inp);
3528 /* is there room for all of the hmac ids? */
3529 size = sizeof(*shmac) + (hmaclist->num_algo *
3530 sizeof(shmac->shmac_idents[0]));
3531 if ((size_t)(*optsize) < size) {
3532 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3534 SCTP_INP_RUNLOCK(inp);
3537 /* copy in the list */
3538 shmac->shmac_number_of_idents = hmaclist->num_algo;
3539 for (i = 0; i < hmaclist->num_algo; i++) {
3540 shmac->shmac_idents[i] = hmaclist->hmac[i];
3542 SCTP_INP_RUNLOCK(inp);
3546 case SCTP_AUTH_ACTIVE_KEY:
3548 struct sctp_authkeyid *scact;
3550 SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, *optsize);
3551 SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id);
3554 /* get the active key on the assoc */
3555 scact->scact_keynumber = stcb->asoc.authinfo.active_keyid;
3556 SCTP_TCB_UNLOCK(stcb);
3558 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3559 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3560 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3561 (scact->scact_assoc_id == SCTP_FUTURE_ASSOC))) {
3562 /* get the endpoint active key */
3563 SCTP_INP_RLOCK(inp);
3564 scact->scact_keynumber = inp->sctp_ep.default_keyid;
3565 SCTP_INP_RUNLOCK(inp);
3567 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3572 *optsize = sizeof(struct sctp_authkeyid);
3576 case SCTP_LOCAL_AUTH_CHUNKS:
3578 struct sctp_authchunks *sac;
3579 sctp_auth_chklist_t *chklist = NULL;
3582 SCTP_CHECK_AND_CAST(sac, optval, struct sctp_authchunks, *optsize);
3583 SCTP_FIND_STCB(inp, stcb, sac->gauth_assoc_id);
3586 /* get off the assoc */
3587 chklist = stcb->asoc.local_auth_chunks;
3588 /* is there enough space? */
3589 size = sctp_auth_get_chklist_size(chklist);
3590 if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
3592 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3594 /* copy in the chunks */
3595 (void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
3596 sac->gauth_number_of_chunks = (uint32_t)size;
3597 *optsize = sizeof(struct sctp_authchunks) + size;
3599 SCTP_TCB_UNLOCK(stcb);
3601 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3602 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3603 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3604 (sac->gauth_assoc_id == SCTP_FUTURE_ASSOC))) {
3605 /* get off the endpoint */
3606 SCTP_INP_RLOCK(inp);
3607 chklist = inp->sctp_ep.local_auth_chunks;
3608 /* is there enough space? */
3609 size = sctp_auth_get_chklist_size(chklist);
3610 if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
3612 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3614 /* copy in the chunks */
3615 (void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
3616 sac->gauth_number_of_chunks = (uint32_t)size;
3617 *optsize = sizeof(struct sctp_authchunks) + size;
3619 SCTP_INP_RUNLOCK(inp);
3621 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3627 case SCTP_PEER_AUTH_CHUNKS:
3629 struct sctp_authchunks *sac;
3630 sctp_auth_chklist_t *chklist = NULL;
3633 SCTP_CHECK_AND_CAST(sac, optval, struct sctp_authchunks, *optsize);
3634 SCTP_FIND_STCB(inp, stcb, sac->gauth_assoc_id);
3637 /* get off the assoc */
3638 chklist = stcb->asoc.peer_auth_chunks;
3639 /* is there enough space? */
3640 size = sctp_auth_get_chklist_size(chklist);
3641 if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
3643 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3645 /* copy in the chunks */
3646 (void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
3647 sac->gauth_number_of_chunks = (uint32_t)size;
3648 *optsize = sizeof(struct sctp_authchunks) + size;
3650 SCTP_TCB_UNLOCK(stcb);
3652 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
3657 #if defined(HAVE_SCTP_PEELOFF_SOCKOPT)
3660 struct sctp_peeloff_opt *peeloff;
3662 SCTP_CHECK_AND_CAST(peeloff, optval, struct sctp_peeloff_opt, *optsize);
3663 /* do the peeloff */
3664 error = sctp_peeloff_option(p, peeloff);
3666 *optsize = sizeof(struct sctp_peeloff_opt);
3670 #endif /* HAVE_SCTP_PEELOFF_SOCKOPT */
3673 struct sctp_event *event;
3674 uint32_t event_type;
3676 SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, *optsize);
3677 SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
3679 switch (event->se_type) {
3680 case SCTP_ASSOC_CHANGE:
3681 event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
3683 case SCTP_PEER_ADDR_CHANGE:
3684 event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
3686 case SCTP_REMOTE_ERROR:
3687 event_type = SCTP_PCB_FLAGS_RECVPEERERR;
3689 case SCTP_SEND_FAILED:
3690 event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
3692 case SCTP_SHUTDOWN_EVENT:
3693 event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
3695 case SCTP_ADAPTATION_INDICATION:
3696 event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
3698 case SCTP_PARTIAL_DELIVERY_EVENT:
3699 event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
3701 case SCTP_AUTHENTICATION_EVENT:
3702 event_type = SCTP_PCB_FLAGS_AUTHEVNT;
3704 case SCTP_STREAM_RESET_EVENT:
3705 event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
3707 case SCTP_SENDER_DRY_EVENT:
3708 event_type = SCTP_PCB_FLAGS_DRYEVNT;
3710 case SCTP_NOTIFICATIONS_STOPPED_EVENT:
3712 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
3715 case SCTP_ASSOC_RESET_EVENT:
3716 event_type = SCTP_PCB_FLAGS_ASSOC_RESETEVNT;
3718 case SCTP_STREAM_CHANGE_EVENT:
3719 event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT;
3721 case SCTP_SEND_FAILED_EVENT:
3722 event_type = SCTP_PCB_FLAGS_RECVNSENDFAILEVNT;
3726 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3730 if (event_type > 0) {
3732 event->se_on = sctp_stcb_is_feature_on(inp, stcb, event_type);
3734 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3735 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3736 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3737 (event->se_assoc_id == SCTP_FUTURE_ASSOC))) {
3738 SCTP_INP_RLOCK(inp);
3739 event->se_on = sctp_is_feature_on(inp, event_type);
3740 SCTP_INP_RUNLOCK(inp);
3742 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3748 SCTP_TCB_UNLOCK(stcb);
3751 *optsize = sizeof(struct sctp_event);
3755 case SCTP_RECVRCVINFO:
3759 if (*optsize < sizeof(int)) {
3760 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3763 SCTP_INP_RLOCK(inp);
3764 onoff = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
3765 SCTP_INP_RUNLOCK(inp);
3768 /* return the option value */
3769 *(int *)optval = onoff;
3770 *optsize = sizeof(int);
3774 case SCTP_RECVNXTINFO:
3778 if (*optsize < sizeof(int)) {
3779 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3782 SCTP_INP_RLOCK(inp);
3783 onoff = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
3784 SCTP_INP_RUNLOCK(inp);
3787 /* return the option value */
3788 *(int *)optval = onoff;
3789 *optsize = sizeof(int);
3793 case SCTP_DEFAULT_SNDINFO:
3795 struct sctp_sndinfo *info;
3797 SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, *optsize);
3798 SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
3801 info->snd_sid = stcb->asoc.def_send.sinfo_stream;
3802 info->snd_flags = stcb->asoc.def_send.sinfo_flags;
3803 info->snd_flags &= 0xfff0;
3804 info->snd_ppid = stcb->asoc.def_send.sinfo_ppid;
3805 info->snd_context = stcb->asoc.def_send.sinfo_context;
3806 SCTP_TCB_UNLOCK(stcb);
3808 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3809 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3810 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3811 (info->snd_assoc_id == SCTP_FUTURE_ASSOC))) {
3812 SCTP_INP_RLOCK(inp);
3813 info->snd_sid = inp->def_send.sinfo_stream;
3814 info->snd_flags = inp->def_send.sinfo_flags;
3815 info->snd_flags &= 0xfff0;
3816 info->snd_ppid = inp->def_send.sinfo_ppid;
3817 info->snd_context = inp->def_send.sinfo_context;
3818 SCTP_INP_RUNLOCK(inp);
3820 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3825 *optsize = sizeof(struct sctp_sndinfo);
3829 case SCTP_DEFAULT_PRINFO:
3831 struct sctp_default_prinfo *info;
3833 SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, *optsize);
3834 SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
3837 info->pr_policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
3838 info->pr_value = stcb->asoc.def_send.sinfo_timetolive;
3839 SCTP_TCB_UNLOCK(stcb);
3841 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3842 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3843 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3844 (info->pr_assoc_id == SCTP_FUTURE_ASSOC))) {
3845 SCTP_INP_RLOCK(inp);
3846 info->pr_policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
3847 info->pr_value = inp->def_send.sinfo_timetolive;
3848 SCTP_INP_RUNLOCK(inp);
3850 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3855 *optsize = sizeof(struct sctp_default_prinfo);
3859 case SCTP_PEER_ADDR_THLDS:
3861 struct sctp_paddrthlds *thlds;
3862 struct sctp_nets *net;
3863 struct sockaddr *addr;
3864 #if defined(INET) && defined(INET6)
3865 struct sockaddr_in sin_store;
3868 SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, *optsize);
3869 SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
3871 #if defined(INET) && defined(INET6)
3872 if (thlds->spt_address.ss_family == AF_INET6) {
3873 struct sockaddr_in6 *sin6;
3875 sin6 = (struct sockaddr_in6 *)&thlds->spt_address;
3876 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
3877 in6_sin6_2_sin(&sin_store, sin6);
3878 addr = (struct sockaddr *)&sin_store;
3880 addr = (struct sockaddr *)&thlds->spt_address;
3883 addr = (struct sockaddr *)&thlds->spt_address;
3886 addr = (struct sockaddr *)&thlds->spt_address;
3889 net = sctp_findnet(stcb, addr);
3891 /* We increment here since sctp_findassociation_ep_addr() wil
3892 * do a decrement if it finds the stcb as long as the locked
3893 * tcb (last argument) is NOT a TCB.. aka NULL.
3896 SCTP_INP_INCR_REF(inp);
3897 stcb = sctp_findassociation_ep_addr(&inp, addr, &net, NULL, NULL);
3899 SCTP_INP_DECR_REF(inp);
3902 if ((stcb != NULL) && (net == NULL)) {
3904 if (addr->sa_family == AF_INET) {
3905 struct sockaddr_in *sin;
3907 sin = (struct sockaddr_in *)addr;
3908 if (sin->sin_addr.s_addr != INADDR_ANY) {
3910 SCTP_TCB_UNLOCK(stcb);
3911 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3917 if (addr->sa_family == AF_INET6) {
3918 struct sockaddr_in6 *sin6;
3920 sin6 = (struct sockaddr_in6 *)addr;
3921 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
3923 SCTP_TCB_UNLOCK(stcb);
3924 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3929 #if defined(__Userspace__)
3930 if (addr->sa_family == AF_CONN) {
3931 struct sockaddr_conn *sconn;
3933 sconn = (struct sockaddr_conn *)addr;
3934 if (sconn->sconn_addr != NULL) {
3936 SCTP_TCB_UNLOCK(stcb);
3937 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3943 error = EAFNOSUPPORT;
3944 SCTP_TCB_UNLOCK(stcb);
3945 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3952 thlds->spt_pathmaxrxt = net->failure_threshold;
3953 thlds->spt_pathpfthld = net->pf_threshold;
3954 thlds->spt_pathcpthld = 0xffff;
3956 thlds->spt_pathmaxrxt = stcb->asoc.def_net_failure;
3957 thlds->spt_pathpfthld = stcb->asoc.def_net_pf_threshold;
3958 thlds->spt_pathcpthld = 0xffff;
3960 thlds->spt_assoc_id = sctp_get_associd(stcb);
3961 SCTP_TCB_UNLOCK(stcb);
3963 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3964 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3965 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3966 (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC))) {
3967 /* Use endpoint defaults */
3968 SCTP_INP_RLOCK(inp);
3969 thlds->spt_pathmaxrxt = inp->sctp_ep.def_net_failure;
3970 thlds->spt_pathpfthld = inp->sctp_ep.def_net_pf_threshold;
3971 thlds->spt_pathcpthld = 0xffff;
3972 SCTP_INP_RUNLOCK(inp);
3974 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3979 *optsize = sizeof(struct sctp_paddrthlds);
3983 case SCTP_REMOTE_UDP_ENCAPS_PORT:
3985 struct sctp_udpencaps *encaps;
3986 struct sctp_nets *net;
3987 struct sockaddr *addr;
3988 #if defined(INET) && defined(INET6)
3989 struct sockaddr_in sin_store;
3992 SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, *optsize);
3993 SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
3995 #if defined(INET) && defined(INET6)
3996 if (encaps->sue_address.ss_family == AF_INET6) {
3997 struct sockaddr_in6 *sin6;
3999 sin6 = (struct sockaddr_in6 *)&encaps->sue_address;
4000 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
4001 in6_sin6_2_sin(&sin_store, sin6);
4002 addr = (struct sockaddr *)&sin_store;
4004 addr = (struct sockaddr *)&encaps->sue_address;
4007 addr = (struct sockaddr *)&encaps->sue_address;
4010 addr = (struct sockaddr *)&encaps->sue_address;
4013 net = sctp_findnet(stcb, addr);
4015 /* We increment here since sctp_findassociation_ep_addr() wil
4016 * do a decrement if it finds the stcb as long as the locked
4017 * tcb (last argument) is NOT a TCB.. aka NULL.
4020 SCTP_INP_INCR_REF(inp);
4021 stcb = sctp_findassociation_ep_addr(&inp, addr, &net, NULL, NULL);
4023 SCTP_INP_DECR_REF(inp);
4026 if ((stcb != NULL) && (net == NULL)) {
4028 if (addr->sa_family == AF_INET) {
4029 struct sockaddr_in *sin;
4031 sin = (struct sockaddr_in *)addr;
4032 if (sin->sin_addr.s_addr != INADDR_ANY) {
4034 SCTP_TCB_UNLOCK(stcb);
4035 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
4041 if (addr->sa_family == AF_INET6) {
4042 struct sockaddr_in6 *sin6;
4044 sin6 = (struct sockaddr_in6 *)addr;
4045 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
4047 SCTP_TCB_UNLOCK(stcb);
4048 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
4053 #if defined(__Userspace__)
4054 if (addr->sa_family == AF_CONN) {
4055 struct sockaddr_conn *sconn;
4057 sconn = (struct sockaddr_conn *)addr;
4058 if (sconn->sconn_addr != NULL) {
4060 SCTP_TCB_UNLOCK(stcb);
4061 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
4067 error = EAFNOSUPPORT;
4068 SCTP_TCB_UNLOCK(stcb);
4069 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
4076 encaps->sue_port = net->port;
4078 encaps->sue_port = stcb->asoc.port;
4080 SCTP_TCB_UNLOCK(stcb);
4082 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4083 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4084 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4085 (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC))) {
4086 SCTP_INP_RLOCK(inp);
4087 encaps->sue_port = inp->sctp_ep.port;
4088 SCTP_INP_RUNLOCK(inp);
4090 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4095 *optsize = sizeof(struct sctp_udpencaps);
4099 case SCTP_ECN_SUPPORTED:
4101 struct sctp_assoc_value *av;
4103 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
4104 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4107 av->assoc_value = stcb->asoc.ecn_supported;
4108 SCTP_TCB_UNLOCK(stcb);
4110 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4111 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4112 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4113 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
4114 SCTP_INP_RLOCK(inp);
4115 av->assoc_value = inp->ecn_supported;
4116 SCTP_INP_RUNLOCK(inp);
4118 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4123 *optsize = sizeof(struct sctp_assoc_value);
4127 case SCTP_PR_SUPPORTED:
4129 struct sctp_assoc_value *av;
4131 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
4132 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4135 av->assoc_value = stcb->asoc.prsctp_supported;
4136 SCTP_TCB_UNLOCK(stcb);
4138 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4139 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4140 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4141 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
4142 SCTP_INP_RLOCK(inp);
4143 av->assoc_value = inp->prsctp_supported;
4144 SCTP_INP_RUNLOCK(inp);
4146 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4151 *optsize = sizeof(struct sctp_assoc_value);
4155 case SCTP_AUTH_SUPPORTED:
4157 struct sctp_assoc_value *av;
4159 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
4160 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4163 av->assoc_value = stcb->asoc.auth_supported;
4164 SCTP_TCB_UNLOCK(stcb);
4166 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4167 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4168 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4169 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
4170 SCTP_INP_RLOCK(inp);
4171 av->assoc_value = inp->auth_supported;
4172 SCTP_INP_RUNLOCK(inp);
4174 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4179 *optsize = sizeof(struct sctp_assoc_value);
4183 case SCTP_ASCONF_SUPPORTED:
4185 struct sctp_assoc_value *av;
4187 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
4188 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4191 av->assoc_value = stcb->asoc.asconf_supported;
4192 SCTP_TCB_UNLOCK(stcb);
4194 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4195 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4196 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4197 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
4198 SCTP_INP_RLOCK(inp);
4199 av->assoc_value = inp->asconf_supported;
4200 SCTP_INP_RUNLOCK(inp);
4202 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4207 *optsize = sizeof(struct sctp_assoc_value);
4211 case SCTP_RECONFIG_SUPPORTED:
4213 struct sctp_assoc_value *av;
4215 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
4216 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4219 av->assoc_value = stcb->asoc.reconfig_supported;
4220 SCTP_TCB_UNLOCK(stcb);
4222 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4223 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4224 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4225 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
4226 SCTP_INP_RLOCK(inp);
4227 av->assoc_value = inp->reconfig_supported;
4228 SCTP_INP_RUNLOCK(inp);
4230 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4235 *optsize = sizeof(struct sctp_assoc_value);
4239 case SCTP_NRSACK_SUPPORTED:
4241 struct sctp_assoc_value *av;
4243 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
4244 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4247 av->assoc_value = stcb->asoc.nrsack_supported;
4248 SCTP_TCB_UNLOCK(stcb);
4250 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4251 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4252 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4253 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
4254 SCTP_INP_RLOCK(inp);
4255 av->assoc_value = inp->nrsack_supported;
4256 SCTP_INP_RUNLOCK(inp);
4258 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4263 *optsize = sizeof(struct sctp_assoc_value);
4267 case SCTP_PKTDROP_SUPPORTED:
4269 struct sctp_assoc_value *av;
4271 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
4272 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4275 av->assoc_value = stcb->asoc.pktdrop_supported;
4276 SCTP_TCB_UNLOCK(stcb);
4278 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4279 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4280 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4281 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
4282 SCTP_INP_RLOCK(inp);
4283 av->assoc_value = inp->pktdrop_supported;
4284 SCTP_INP_RUNLOCK(inp);
4286 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4291 *optsize = sizeof(struct sctp_assoc_value);
4295 case SCTP_ENABLE_STREAM_RESET:
4297 struct sctp_assoc_value *av;
4299 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
4300 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4303 av->assoc_value = (uint32_t)stcb->asoc.local_strreset_support;
4304 SCTP_TCB_UNLOCK(stcb);
4306 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4307 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4308 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4309 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
4310 SCTP_INP_RLOCK(inp);
4311 av->assoc_value = (uint32_t)inp->local_strreset_support;
4312 SCTP_INP_RUNLOCK(inp);
4314 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4319 *optsize = sizeof(struct sctp_assoc_value);
4323 case SCTP_PR_STREAM_STATUS:
4325 struct sctp_prstatus *sprstat;
4329 SCTP_CHECK_AND_CAST(sprstat, optval, struct sctp_prstatus, *optsize);
4330 SCTP_FIND_STCB(inp, stcb, sprstat->sprstat_assoc_id);
4332 sid = sprstat->sprstat_sid;
4333 policy = sprstat->sprstat_policy;
4334 #if defined(SCTP_DETAILED_STR_STATS)
4335 if ((stcb != NULL) &&
4336 (sid < stcb->asoc.streamoutcnt) &&
4337 (policy != SCTP_PR_SCTP_NONE) &&
4338 ((policy <= SCTP_PR_SCTP_MAX) ||
4339 (policy == SCTP_PR_SCTP_ALL))) {
4340 if (policy == SCTP_PR_SCTP_ALL) {
4341 sprstat->sprstat_abandoned_unsent = stcb->asoc.strmout[sid].abandoned_unsent[0];
4342 sprstat->sprstat_abandoned_sent = stcb->asoc.strmout[sid].abandoned_sent[0];
4344 sprstat->sprstat_abandoned_unsent = stcb->asoc.strmout[sid].abandoned_unsent[policy];
4345 sprstat->sprstat_abandoned_sent = stcb->asoc.strmout[sid].abandoned_sent[policy];
4348 if ((stcb != NULL) &&
4349 (sid < stcb->asoc.streamoutcnt) &&
4350 (policy == SCTP_PR_SCTP_ALL)) {
4351 sprstat->sprstat_abandoned_unsent = stcb->asoc.strmout[sid].abandoned_unsent[0];
4352 sprstat->sprstat_abandoned_sent = stcb->asoc.strmout[sid].abandoned_sent[0];
4355 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4359 SCTP_TCB_UNLOCK(stcb);
4362 *optsize = sizeof(struct sctp_prstatus);
4366 case SCTP_PR_ASSOC_STATUS:
4368 struct sctp_prstatus *sprstat;
4371 SCTP_CHECK_AND_CAST(sprstat, optval, struct sctp_prstatus, *optsize);
4372 SCTP_FIND_STCB(inp, stcb, sprstat->sprstat_assoc_id);
4374 policy = sprstat->sprstat_policy;
4375 if ((stcb != NULL) &&
4376 (policy != SCTP_PR_SCTP_NONE) &&
4377 ((policy <= SCTP_PR_SCTP_MAX) ||
4378 (policy == SCTP_PR_SCTP_ALL))) {
4379 if (policy == SCTP_PR_SCTP_ALL) {
4380 sprstat->sprstat_abandoned_unsent = stcb->asoc.abandoned_unsent[0];
4381 sprstat->sprstat_abandoned_sent = stcb->asoc.abandoned_sent[0];
4383 sprstat->sprstat_abandoned_unsent = stcb->asoc.abandoned_unsent[policy];
4384 sprstat->sprstat_abandoned_sent = stcb->asoc.abandoned_sent[policy];
4387 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4391 SCTP_TCB_UNLOCK(stcb);
4394 *optsize = sizeof(struct sctp_prstatus);
4400 struct sctp_assoc_value *av;
4402 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
4403 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4406 av->assoc_value = stcb->asoc.max_cwnd;
4407 SCTP_TCB_UNLOCK(stcb);
4409 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4410 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4411 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4412 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
4413 SCTP_INP_RLOCK(inp);
4414 av->assoc_value = inp->max_cwnd;
4415 SCTP_INP_RUNLOCK(inp);
4417 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4422 *optsize = sizeof(struct sctp_assoc_value);
4427 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
4428 error = ENOPROTOOPT;
4430 } /* end switch (sopt->sopt_name) */
4437 #if defined(__Userspace__)
4442 sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
4447 struct sctp_tcb *stcb = NULL;
4448 struct sctp_inpcb *inp = NULL;
4451 if (optval == NULL) {
4452 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4455 inp = (struct sctp_inpcb *)so->so_pcb;
4457 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4460 vrf_id = inp->def_vrf_id;
4465 case SCTP_AUTOCLOSE:
4466 case SCTP_AUTO_ASCONF:
4467 case SCTP_EXPLICIT_EOR:
4468 case SCTP_DISABLE_FRAGMENTS:
4469 case SCTP_USE_EXT_RCVINFO:
4470 case SCTP_I_WANT_MAPPED_V4_ADDR:
4471 /* copy in the option value */
4472 SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
4477 case SCTP_DISABLE_FRAGMENTS:
4478 set_opt = SCTP_PCB_FLAGS_NO_FRAGMENT;
4480 case SCTP_AUTO_ASCONF:
4482 * NOTE: we don't really support this flag
4484 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
4485 /* only valid for bound all sockets */
4486 if ((SCTP_BASE_SYSCTL(sctp_auto_asconf) == 0) &&
4488 /* forbidden by admin */
4489 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EPERM);
4492 set_opt = SCTP_PCB_FLAGS_AUTO_ASCONF;
4494 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4498 case SCTP_EXPLICIT_EOR:
4499 set_opt = SCTP_PCB_FLAGS_EXPLICIT_EOR;
4501 case SCTP_USE_EXT_RCVINFO:
4502 set_opt = SCTP_PCB_FLAGS_EXT_RCVINFO;
4504 case SCTP_I_WANT_MAPPED_V4_ADDR:
4505 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
4506 set_opt = SCTP_PCB_FLAGS_NEEDS_MAPPED_V4;
4508 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4513 set_opt = SCTP_PCB_FLAGS_NODELAY;
4515 case SCTP_AUTOCLOSE:
4516 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4517 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
4518 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4521 set_opt = SCTP_PCB_FLAGS_AUTOCLOSE;
4523 * The value is in ticks. Note this does not effect
4524 * old associations, only new ones.
4526 inp->sctp_ep.auto_close_time = sctp_secs_to_ticks(*mopt);
4529 SCTP_INP_WLOCK(inp);
4531 sctp_feature_on(inp, set_opt);
4533 sctp_feature_off(inp, set_opt);
4535 SCTP_INP_WUNLOCK(inp);
4537 case SCTP_REUSE_PORT:
4539 SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
4540 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) {
4541 /* Can't set it after we are bound */
4545 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
4546 /* Can't do this for a 1-m socket */
4551 sctp_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE);
4553 sctp_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE);
4556 case SCTP_PARTIAL_DELIVERY_POINT:
4560 SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
4561 if (*value > SCTP_SB_LIMIT_RCV(so)) {
4562 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4566 inp->partial_delivery_point = *value;
4569 case SCTP_FRAGMENT_INTERLEAVE:
4570 /* not yet until we re-write sctp_recvmsg() */
4574 SCTP_CHECK_AND_CAST(level, optval, uint32_t, optsize);
4575 if (*level == SCTP_FRAG_LEVEL_2) {
4576 sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
4577 sctp_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
4578 } else if (*level == SCTP_FRAG_LEVEL_1) {
4579 sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
4580 sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
4581 } else if (*level == SCTP_FRAG_LEVEL_0) {
4582 sctp_feature_off(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
4583 sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
4586 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4591 case SCTP_INTERLEAVING_SUPPORTED:
4593 struct sctp_assoc_value *av;
4595 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4596 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4599 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4601 SCTP_TCB_UNLOCK(stcb);
4603 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4604 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4605 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4606 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
4607 SCTP_INP_WLOCK(inp);
4608 if (av->assoc_value == 0) {
4609 inp->idata_supported = 0;
4611 if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE)) &&
4612 (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS))) {
4613 inp->idata_supported = 1;
4615 /* Must have Frag interleave and stream interleave on */
4616 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4620 SCTP_INP_WUNLOCK(inp);
4622 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4628 case SCTP_CMT_ON_OFF:
4629 if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
4630 struct sctp_assoc_value *av;
4632 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4633 if (av->assoc_value > SCTP_CMT_MAX) {
4634 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4638 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4640 stcb->asoc.sctp_cmt_on_off = av->assoc_value;
4641 SCTP_TCB_UNLOCK(stcb);
4643 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4644 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4645 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4646 ((av->assoc_id == SCTP_FUTURE_ASSOC) ||
4647 (av->assoc_id == SCTP_ALL_ASSOC)))) {
4648 SCTP_INP_WLOCK(inp);
4649 inp->sctp_cmt_on_off = av->assoc_value;
4650 SCTP_INP_WUNLOCK(inp);
4652 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4653 ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4654 (av->assoc_id == SCTP_ALL_ASSOC))) {
4655 SCTP_INP_RLOCK(inp);
4656 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4657 SCTP_TCB_LOCK(stcb);
4658 stcb->asoc.sctp_cmt_on_off = av->assoc_value;
4659 SCTP_TCB_UNLOCK(stcb);
4661 SCTP_INP_RUNLOCK(inp);
4665 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
4666 error = ENOPROTOOPT;
4669 case SCTP_PLUGGABLE_CC:
4671 struct sctp_assoc_value *av;
4672 struct sctp_nets *net;
4674 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4675 if ((av->assoc_value != SCTP_CC_RFC2581) &&
4676 (av->assoc_value != SCTP_CC_HSTCP) &&
4677 (av->assoc_value != SCTP_CC_HTCP) &&
4678 (av->assoc_value != SCTP_CC_RTCC)) {
4679 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4683 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4685 stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
4686 stcb->asoc.congestion_control_module = av->assoc_value;
4687 if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
4688 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4689 stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
4692 SCTP_TCB_UNLOCK(stcb);
4694 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4695 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4696 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4697 ((av->assoc_id == SCTP_FUTURE_ASSOC) ||
4698 (av->assoc_id == SCTP_ALL_ASSOC)))) {
4699 SCTP_INP_WLOCK(inp);
4700 inp->sctp_ep.sctp_default_cc_module = av->assoc_value;
4701 SCTP_INP_WUNLOCK(inp);
4703 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4704 ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4705 (av->assoc_id == SCTP_ALL_ASSOC))) {
4706 SCTP_INP_RLOCK(inp);
4707 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4708 SCTP_TCB_LOCK(stcb);
4709 stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
4710 stcb->asoc.congestion_control_module = av->assoc_value;
4711 if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
4712 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4713 stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
4716 SCTP_TCB_UNLOCK(stcb);
4718 SCTP_INP_RUNLOCK(inp);
4723 case SCTP_CC_OPTION:
4725 struct sctp_cc_option *cc_opt;
4727 SCTP_CHECK_AND_CAST(cc_opt, optval, struct sctp_cc_option, optsize);
4728 SCTP_FIND_STCB(inp, stcb, cc_opt->aid_value.assoc_id);
4730 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4731 (cc_opt->aid_value.assoc_id == SCTP_CURRENT_ASSOC)) {
4732 SCTP_INP_RLOCK(inp);
4733 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4734 SCTP_TCB_LOCK(stcb);
4735 if (stcb->asoc.cc_functions.sctp_cwnd_socket_option) {
4736 (*stcb->asoc.cc_functions.sctp_cwnd_socket_option)(stcb, 1, cc_opt);
4738 SCTP_TCB_UNLOCK(stcb);
4740 SCTP_INP_RUNLOCK(inp);
4745 if (stcb->asoc.cc_functions.sctp_cwnd_socket_option == NULL) {
4748 error = (*stcb->asoc.cc_functions.sctp_cwnd_socket_option)(stcb, 1,
4751 SCTP_TCB_UNLOCK(stcb);
4755 case SCTP_PLUGGABLE_SS:
4757 struct sctp_assoc_value *av;
4759 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4760 if ((av->assoc_value != SCTP_SS_DEFAULT) &&
4761 (av->assoc_value != SCTP_SS_ROUND_ROBIN) &&
4762 (av->assoc_value != SCTP_SS_ROUND_ROBIN_PACKET) &&
4763 (av->assoc_value != SCTP_SS_PRIORITY) &&
4764 (av->assoc_value != SCTP_SS_FAIR_BANDWITH) &&
4765 (av->assoc_value != SCTP_SS_FIRST_COME)) {
4766 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4770 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4772 SCTP_TCB_SEND_LOCK(stcb);
4773 stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1);
4774 stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
4775 stcb->asoc.stream_scheduling_module = av->assoc_value;
4776 stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
4777 SCTP_TCB_SEND_UNLOCK(stcb);
4778 SCTP_TCB_UNLOCK(stcb);
4780 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4781 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4782 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4783 ((av->assoc_id == SCTP_FUTURE_ASSOC) ||
4784 (av->assoc_id == SCTP_ALL_ASSOC)))) {
4785 SCTP_INP_WLOCK(inp);
4786 inp->sctp_ep.sctp_default_ss_module = av->assoc_value;
4787 SCTP_INP_WUNLOCK(inp);
4789 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4790 ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4791 (av->assoc_id == SCTP_ALL_ASSOC))) {
4792 SCTP_INP_RLOCK(inp);
4793 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4794 SCTP_TCB_LOCK(stcb);
4795 SCTP_TCB_SEND_LOCK(stcb);
4796 stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1);
4797 stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
4798 stcb->asoc.stream_scheduling_module = av->assoc_value;
4799 stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
4800 SCTP_TCB_SEND_UNLOCK(stcb);
4801 SCTP_TCB_UNLOCK(stcb);
4803 SCTP_INP_RUNLOCK(inp);
4810 struct sctp_stream_value *av;
4812 SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, optsize);
4813 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4815 if ((av->stream_id >= stcb->asoc.streamoutcnt) ||
4816 (stcb->asoc.ss_functions.sctp_ss_set_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id],
4817 av->stream_value) < 0)) {
4818 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4821 SCTP_TCB_UNLOCK(stcb);
4823 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4824 (av->assoc_id == SCTP_CURRENT_ASSOC)) {
4825 SCTP_INP_RLOCK(inp);
4826 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4827 SCTP_TCB_LOCK(stcb);
4828 if (av->stream_id < stcb->asoc.streamoutcnt) {
4829 stcb->asoc.ss_functions.sctp_ss_set_value(stcb,
4831 &stcb->asoc.strmout[av->stream_id],
4834 SCTP_TCB_UNLOCK(stcb);
4836 SCTP_INP_RUNLOCK(inp);
4838 /* Can't set stream value without association */
4839 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4845 case SCTP_CLR_STAT_LOG:
4846 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4851 struct sctp_assoc_value *av;
4853 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4854 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4857 stcb->asoc.context = av->assoc_value;
4858 SCTP_TCB_UNLOCK(stcb);
4860 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4861 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4862 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4863 ((av->assoc_id == SCTP_FUTURE_ASSOC) ||
4864 (av->assoc_id == SCTP_ALL_ASSOC)))) {
4865 SCTP_INP_WLOCK(inp);
4866 inp->sctp_context = av->assoc_value;
4867 SCTP_INP_WUNLOCK(inp);
4869 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4870 ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4871 (av->assoc_id == SCTP_ALL_ASSOC))) {
4872 SCTP_INP_RLOCK(inp);
4873 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4874 SCTP_TCB_LOCK(stcb);
4875 stcb->asoc.context = av->assoc_value;
4876 SCTP_TCB_UNLOCK(stcb);
4878 SCTP_INP_RUNLOCK(inp);
4885 uint32_t *default_vrfid;
4889 SCTP_CHECK_AND_CAST(default_vrfid, optval, uint32_t, optsize);
4890 if (*default_vrfid > SCTP_MAX_VRF_ID) {
4891 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4896 for (i = 0; i < inp->num_vrfs; i++) {
4897 /* The VRF must be in the VRF list */
4898 if (*default_vrfid == inp->m_vrf_ids[i]) {
4899 SCTP_INP_WLOCK(inp);
4900 inp->def_vrf_id = *default_vrfid;
4901 SCTP_INP_WUNLOCK(inp);
4905 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4908 inp->def_vrf_id = *default_vrfid;
4915 case SCTP_DEL_VRF_ID:
4918 uint32_t *del_vrfid;
4921 SCTP_CHECK_AND_CAST(del_vrfid, optval, uint32_t, optsize);
4922 if (*del_vrfid > SCTP_MAX_VRF_ID) {
4923 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4927 if (inp->num_vrfs == 1) {
4928 /* Can't delete last one */
4929 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4933 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) {
4934 /* Can't add more once you are bound */
4935 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4939 SCTP_INP_WLOCK(inp);
4940 for (i = 0; i < inp->num_vrfs; i++) {
4941 if (*del_vrfid == inp->m_vrf_ids[i]) {
4947 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4951 if (i != (inp->num_vrfs - 1)) {
4952 /* Take bottom one and move to this slot */
4953 inp->m_vrf_ids[i] = inp->m_vrf_ids[(inp->num_vrfs-1)];
4955 if (*del_vrfid == inp->def_vrf_id) {
4956 /* Take the first one as the new default */
4957 inp->def_vrf_id = inp->m_vrf_ids[0];
4959 /* Drop the number by one killing last one */
4962 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4967 case SCTP_ADD_VRF_ID:
4970 uint32_t *add_vrfid;
4973 SCTP_CHECK_AND_CAST(add_vrfid, optval, uint32_t, optsize);
4974 if (*add_vrfid > SCTP_MAX_VRF_ID) {
4975 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4979 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) {
4980 /* Can't add more once you are bound */
4981 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4985 SCTP_INP_WLOCK(inp);
4986 /* Verify its not already here */
4987 for (i = 0; i < inp->num_vrfs; i++) {
4988 if (*add_vrfid == inp->m_vrf_ids[i]) {
4989 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4991 SCTP_INP_WUNLOCK(inp);
4995 if ((inp->num_vrfs + 1) > inp->vrf_size) {
4996 /* need to grow array */
4998 SCTP_MALLOC(tarray, uint32_t *,
4999 (sizeof(uint32_t) * (inp->vrf_size + SCTP_DEFAULT_VRF_SIZE)),
5001 if (tarray == NULL) {
5002 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
5004 SCTP_INP_WUNLOCK(inp);
5007 memcpy(tarray, inp->m_vrf_ids, (sizeof(uint32_t) * inp->vrf_size));
5008 SCTP_FREE(inp->m_vrf_ids, SCTP_M_MVRF);
5009 inp->m_vrf_ids = tarray;
5010 inp->vrf_size += SCTP_DEFAULT_VRF_SIZE;
5012 inp->m_vrf_ids[inp->num_vrfs] = *add_vrfid;
5014 SCTP_INP_WUNLOCK(inp);
5016 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
5021 case SCTP_DELAYED_SACK:
5023 struct sctp_sack_info *sack;
5025 SCTP_CHECK_AND_CAST(sack, optval, struct sctp_sack_info, optsize);
5026 SCTP_FIND_STCB(inp, stcb, sack->sack_assoc_id);
5027 if (sack->sack_delay) {
5028 if (sack->sack_delay > SCTP_MAX_SACK_DELAY) {
5031 SCTP_TCB_UNLOCK(stcb);
5037 if (sack->sack_delay) {
5038 stcb->asoc.delayed_ack = sack->sack_delay;
5040 if (sack->sack_freq) {
5041 stcb->asoc.sack_freq = sack->sack_freq;
5043 SCTP_TCB_UNLOCK(stcb);
5045 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5046 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5047 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5048 ((sack->sack_assoc_id == SCTP_FUTURE_ASSOC) ||
5049 (sack->sack_assoc_id == SCTP_ALL_ASSOC)))) {
5050 SCTP_INP_WLOCK(inp);
5051 if (sack->sack_delay) {
5052 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV] = sctp_msecs_to_ticks(sack->sack_delay);
5054 if (sack->sack_freq) {
5055 inp->sctp_ep.sctp_sack_freq = sack->sack_freq;
5057 SCTP_INP_WUNLOCK(inp);
5059 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5060 ((sack->sack_assoc_id == SCTP_CURRENT_ASSOC) ||
5061 (sack->sack_assoc_id == SCTP_ALL_ASSOC))) {
5062 SCTP_INP_RLOCK(inp);
5063 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5064 SCTP_TCB_LOCK(stcb);
5065 if (sack->sack_delay) {
5066 stcb->asoc.delayed_ack = sack->sack_delay;
5068 if (sack->sack_freq) {
5069 stcb->asoc.sack_freq = sack->sack_freq;
5071 SCTP_TCB_UNLOCK(stcb);
5073 SCTP_INP_RUNLOCK(inp);
5078 case SCTP_AUTH_CHUNK:
5080 struct sctp_authchunk *sauth;
5082 SCTP_CHECK_AND_CAST(sauth, optval, struct sctp_authchunk, optsize);
5084 SCTP_INP_WLOCK(inp);
5085 if (sctp_auth_add_chunk(sauth->sauth_chunk, inp->sctp_ep.local_auth_chunks)) {
5086 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5089 inp->auth_supported = 1;
5091 SCTP_INP_WUNLOCK(inp);
5096 struct sctp_authkey *sca;
5097 struct sctp_keyhead *shared_keys;
5098 sctp_sharedkey_t *shared_key;
5099 sctp_key_t *key = NULL;
5102 SCTP_CHECK_AND_CAST(sca, optval, struct sctp_authkey, optsize);
5103 if (sca->sca_keylength == 0) {
5104 size = optsize - sizeof(struct sctp_authkey);
5106 if (sca->sca_keylength + sizeof(struct sctp_authkey) <= optsize) {
5107 size = sca->sca_keylength;
5109 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5114 SCTP_FIND_STCB(inp, stcb, sca->sca_assoc_id);
5117 shared_keys = &stcb->asoc.shared_keys;
5118 /* clear the cached keys for this key id */
5119 sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
5121 * create the new shared key and
5125 key = sctp_set_key(sca->sca_key, (uint32_t) size);
5127 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
5129 SCTP_TCB_UNLOCK(stcb);
5133 shared_key = sctp_alloc_sharedkey();
5134 if (shared_key == NULL) {
5136 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
5138 SCTP_TCB_UNLOCK(stcb);
5141 shared_key->key = key;
5142 shared_key->keyid = sca->sca_keynumber;
5143 error = sctp_insert_sharedkey(shared_keys, shared_key);
5144 SCTP_TCB_UNLOCK(stcb);
5146 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5147 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5148 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5149 ((sca->sca_assoc_id == SCTP_FUTURE_ASSOC) ||
5150 (sca->sca_assoc_id == SCTP_ALL_ASSOC)))) {
5151 SCTP_INP_WLOCK(inp);
5152 shared_keys = &inp->sctp_ep.shared_keys;
5154 * clear the cached keys on all assocs for
5157 sctp_clear_cachedkeys_ep(inp, sca->sca_keynumber);
5159 * create the new shared key and
5163 key = sctp_set_key(sca->sca_key, (uint32_t) size);
5165 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
5167 SCTP_INP_WUNLOCK(inp);
5171 shared_key = sctp_alloc_sharedkey();
5172 if (shared_key == NULL) {
5174 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
5176 SCTP_INP_WUNLOCK(inp);
5179 shared_key->key = key;
5180 shared_key->keyid = sca->sca_keynumber;
5181 error = sctp_insert_sharedkey(shared_keys, shared_key);
5182 SCTP_INP_WUNLOCK(inp);
5184 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5185 ((sca->sca_assoc_id == SCTP_CURRENT_ASSOC) ||
5186 (sca->sca_assoc_id == SCTP_ALL_ASSOC))) {
5187 SCTP_INP_RLOCK(inp);
5188 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5189 SCTP_TCB_LOCK(stcb);
5190 shared_keys = &stcb->asoc.shared_keys;
5191 /* clear the cached keys for this key id */
5192 sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
5194 * create the new shared key and
5198 key = sctp_set_key(sca->sca_key, (uint32_t) size);
5200 SCTP_TCB_UNLOCK(stcb);
5204 shared_key = sctp_alloc_sharedkey();
5205 if (shared_key == NULL) {
5207 SCTP_TCB_UNLOCK(stcb);
5210 shared_key->key = key;
5211 shared_key->keyid = sca->sca_keynumber;
5212 error = sctp_insert_sharedkey(shared_keys, shared_key);
5213 SCTP_TCB_UNLOCK(stcb);
5215 SCTP_INP_RUNLOCK(inp);
5220 case SCTP_HMAC_IDENT:
5222 struct sctp_hmacalgo *shmac;
5223 sctp_hmaclist_t *hmaclist;
5227 SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, optsize);
5228 if ((optsize < sizeof(struct sctp_hmacalgo) + shmac->shmac_number_of_idents * sizeof(uint16_t)) ||
5229 (shmac->shmac_number_of_idents > 0xffff)) {
5230 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5235 hmaclist = sctp_alloc_hmaclist((uint16_t)shmac->shmac_number_of_idents);
5236 if (hmaclist == NULL) {
5237 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
5241 for (i = 0; i < shmac->shmac_number_of_idents; i++) {
5242 hmacid = shmac->shmac_idents[i];
5243 if (sctp_auth_add_hmacid(hmaclist, hmacid)) {
5244 /* invalid HMACs were found */;
5245 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5247 sctp_free_hmaclist(hmaclist);
5248 goto sctp_set_hmac_done;
5251 for (i = 0; i < hmaclist->num_algo; i++) {
5252 if (hmaclist->hmac[i] == SCTP_AUTH_HMAC_ID_SHA1) {
5253 /* already in list */
5257 if (i == hmaclist->num_algo) {
5258 /* not found in list */
5259 sctp_free_hmaclist(hmaclist);
5260 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5264 /* set it on the endpoint */
5265 SCTP_INP_WLOCK(inp);
5266 if (inp->sctp_ep.local_hmacs)
5267 sctp_free_hmaclist(inp->sctp_ep.local_hmacs);
5268 inp->sctp_ep.local_hmacs = hmaclist;
5269 SCTP_INP_WUNLOCK(inp);
5273 case SCTP_AUTH_ACTIVE_KEY:
5275 struct sctp_authkeyid *scact;
5277 SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, optsize);
5278 SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id);
5280 /* set the active key on the right place */
5282 /* set the active key on the assoc */
5283 if (sctp_auth_setactivekey(stcb,
5284 scact->scact_keynumber)) {
5285 SCTP_LTRACE_ERR_RET(inp, NULL, NULL,
5286 SCTP_FROM_SCTP_USRREQ,
5290 SCTP_TCB_UNLOCK(stcb);
5292 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5293 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5294 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5295 ((scact->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
5296 (scact->scact_assoc_id == SCTP_ALL_ASSOC)))) {
5297 SCTP_INP_WLOCK(inp);
5298 if (sctp_auth_setactivekey_ep(inp, scact->scact_keynumber)) {
5299 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5302 SCTP_INP_WUNLOCK(inp);
5304 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5305 ((scact->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
5306 (scact->scact_assoc_id == SCTP_ALL_ASSOC))) {
5307 SCTP_INP_RLOCK(inp);
5308 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5309 SCTP_TCB_LOCK(stcb);
5310 sctp_auth_setactivekey(stcb, scact->scact_keynumber);
5311 SCTP_TCB_UNLOCK(stcb);
5313 SCTP_INP_RUNLOCK(inp);
5318 case SCTP_AUTH_DELETE_KEY:
5320 struct sctp_authkeyid *scdel;
5322 SCTP_CHECK_AND_CAST(scdel, optval, struct sctp_authkeyid, optsize);
5323 SCTP_FIND_STCB(inp, stcb, scdel->scact_assoc_id);
5325 /* delete the key from the right place */
5327 if (sctp_delete_sharedkey(stcb, scdel->scact_keynumber)) {
5328 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5331 SCTP_TCB_UNLOCK(stcb);
5333 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5334 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5335 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5336 ((scdel->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
5337 (scdel->scact_assoc_id == SCTP_ALL_ASSOC)))) {
5338 SCTP_INP_WLOCK(inp);
5339 if (sctp_delete_sharedkey_ep(inp, scdel->scact_keynumber)) {
5340 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5343 SCTP_INP_WUNLOCK(inp);
5345 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5346 ((scdel->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
5347 (scdel->scact_assoc_id == SCTP_ALL_ASSOC))) {
5348 SCTP_INP_RLOCK(inp);
5349 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5350 SCTP_TCB_LOCK(stcb);
5351 sctp_delete_sharedkey(stcb, scdel->scact_keynumber);
5352 SCTP_TCB_UNLOCK(stcb);
5354 SCTP_INP_RUNLOCK(inp);
5359 case SCTP_AUTH_DEACTIVATE_KEY:
5361 struct sctp_authkeyid *keyid;
5363 SCTP_CHECK_AND_CAST(keyid, optval, struct sctp_authkeyid, optsize);
5364 SCTP_FIND_STCB(inp, stcb, keyid->scact_assoc_id);
5366 /* deactivate the key from the right place */
5368 if (sctp_deact_sharedkey(stcb, keyid->scact_keynumber)) {
5369 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5372 SCTP_TCB_UNLOCK(stcb);
5374 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5375 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5376 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5377 ((keyid->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
5378 (keyid->scact_assoc_id == SCTP_ALL_ASSOC)))) {
5379 SCTP_INP_WLOCK(inp);
5380 if (sctp_deact_sharedkey_ep(inp, keyid->scact_keynumber)) {
5381 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5384 SCTP_INP_WUNLOCK(inp);
5386 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5387 ((keyid->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
5388 (keyid->scact_assoc_id == SCTP_ALL_ASSOC))) {
5389 SCTP_INP_RLOCK(inp);
5390 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5391 SCTP_TCB_LOCK(stcb);
5392 sctp_deact_sharedkey(stcb, keyid->scact_keynumber);
5393 SCTP_TCB_UNLOCK(stcb);
5395 SCTP_INP_RUNLOCK(inp);
5400 case SCTP_ENABLE_STREAM_RESET:
5402 struct sctp_assoc_value *av;
5404 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
5405 if (av->assoc_value & (~SCTP_ENABLE_VALUE_MASK)) {
5406 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5410 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
5412 stcb->asoc.local_strreset_support = (uint8_t)av->assoc_value;
5413 SCTP_TCB_UNLOCK(stcb);
5415 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5416 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5417 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5418 ((av->assoc_id == SCTP_FUTURE_ASSOC) ||
5419 (av->assoc_id == SCTP_ALL_ASSOC)))) {
5420 SCTP_INP_WLOCK(inp);
5421 inp->local_strreset_support = (uint8_t)av->assoc_value;
5422 SCTP_INP_WUNLOCK(inp);
5424 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5425 ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
5426 (av->assoc_id == SCTP_ALL_ASSOC))) {
5427 SCTP_INP_RLOCK(inp);
5428 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5429 SCTP_TCB_LOCK(stcb);
5430 stcb->asoc.local_strreset_support = (uint8_t)av->assoc_value;
5431 SCTP_TCB_UNLOCK(stcb);
5433 SCTP_INP_RUNLOCK(inp);
5439 case SCTP_RESET_STREAMS:
5441 struct sctp_reset_streams *strrst;
5442 int i, send_out = 0;
5445 SCTP_CHECK_AND_CAST(strrst, optval, struct sctp_reset_streams, optsize);
5446 SCTP_FIND_STCB(inp, stcb, strrst->srs_assoc_id);
5448 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
5452 if (stcb->asoc.reconfig_supported == 0) {
5454 * Peer does not support the chunk type.
5456 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
5458 SCTP_TCB_UNLOCK(stcb);
5461 if (SCTP_GET_STATE(stcb) != SCTP_STATE_OPEN) {
5462 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5464 SCTP_TCB_UNLOCK(stcb);
5467 if (sizeof(struct sctp_reset_streams) +
5468 strrst->srs_number_streams * sizeof(uint16_t) > optsize) {
5470 SCTP_TCB_UNLOCK(stcb);
5473 if (strrst->srs_flags & SCTP_STREAM_RESET_INCOMING) {
5475 if (stcb->asoc.stream_reset_outstanding) {
5476 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
5478 SCTP_TCB_UNLOCK(stcb);
5482 if (strrst->srs_flags & SCTP_STREAM_RESET_OUTGOING) {
5485 if ((strrst->srs_number_streams > SCTP_MAX_STREAMS_AT_ONCE_RESET) && send_in) {
5486 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
5488 SCTP_TCB_UNLOCK(stcb);
5491 if ((send_in == 0) && (send_out == 0)) {
5492 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5494 SCTP_TCB_UNLOCK(stcb);
5497 for (i = 0; i < strrst->srs_number_streams; i++) {
5499 (strrst->srs_stream_list[i] >= stcb->asoc.streamincnt)) {
5500 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5505 (strrst->srs_stream_list[i] >= stcb->asoc.streamoutcnt)) {
5506 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5512 SCTP_TCB_UNLOCK(stcb);
5518 if (strrst->srs_number_streams) {
5519 for (i = 0, cnt = 0; i < strrst->srs_number_streams; i++) {
5520 strm = strrst->srs_stream_list[i];
5521 if (stcb->asoc.strmout[strm].state == SCTP_STREAM_OPEN) {
5522 stcb->asoc.strmout[strm].state = SCTP_STREAM_RESET_PENDING;
5528 for (i = 0, cnt = 0; i < stcb->asoc.streamoutcnt; i++) {
5529 if (stcb->asoc.strmout[i].state == SCTP_STREAM_OPEN) {
5530 stcb->asoc.strmout[i].state = SCTP_STREAM_RESET_PENDING;
5537 error = sctp_send_str_reset_req(stcb, strrst->srs_number_streams,
5538 strrst->srs_stream_list,
5539 send_in, 0, 0, 0, 0, 0);
5541 error = sctp_send_stream_reset_out_if_possible(stcb, SCTP_SO_LOCKED);
5544 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
5547 * For outgoing streams don't report any problems in
5548 * sending the request to the application.
5549 * XXX: Double check resetting incoming streams.
5553 SCTP_TCB_UNLOCK(stcb);
5556 case SCTP_ADD_STREAMS:
5558 struct sctp_add_streams *stradd;
5559 uint8_t addstream = 0;
5560 uint16_t add_o_strmcnt = 0;
5561 uint16_t add_i_strmcnt = 0;
5563 SCTP_CHECK_AND_CAST(stradd, optval, struct sctp_add_streams, optsize);
5564 SCTP_FIND_STCB(inp, stcb, stradd->sas_assoc_id);
5566 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
5570 if (stcb->asoc.reconfig_supported == 0) {
5572 * Peer does not support the chunk type.
5574 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
5576 SCTP_TCB_UNLOCK(stcb);
5579 if (SCTP_GET_STATE(stcb) != SCTP_STATE_OPEN) {
5580 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5582 SCTP_TCB_UNLOCK(stcb);
5585 if (stcb->asoc.stream_reset_outstanding) {
5586 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
5588 SCTP_TCB_UNLOCK(stcb);
5591 if ((stradd->sas_outstrms == 0) &&
5592 (stradd->sas_instrms == 0)) {
5596 if (stradd->sas_outstrms) {
5598 /* We allocate here */
5599 add_o_strmcnt = stradd->sas_outstrms;
5600 if ((((int)add_o_strmcnt) + ((int)stcb->asoc.streamoutcnt)) > 0x0000ffff) {
5601 /* You can't have more than 64k */
5606 if (stradd->sas_instrms) {
5610 /* We allocate inside sctp_send_str_reset_req() */
5611 add_i_strmcnt = stradd->sas_instrms;
5612 cnt = add_i_strmcnt;
5613 cnt += stcb->asoc.streamincnt;
5614 if (cnt > 0x0000ffff) {
5615 /* You can't have more than 64k */
5619 if (cnt > (int)stcb->asoc.max_inbound_streams) {
5620 /* More than you are allowed */
5625 error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, addstream, add_o_strmcnt, add_i_strmcnt, 0);
5626 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
5628 SCTP_TCB_UNLOCK(stcb);
5631 case SCTP_RESET_ASSOC:
5636 SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
5637 SCTP_FIND_STCB(inp, stcb, (sctp_assoc_t) *value);
5639 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
5643 if (stcb->asoc.reconfig_supported == 0) {
5645 * Peer does not support the chunk type.
5647 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
5649 SCTP_TCB_UNLOCK(stcb);
5652 if (SCTP_GET_STATE(stcb) != SCTP_STATE_OPEN) {
5653 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5655 SCTP_TCB_UNLOCK(stcb);
5658 if (stcb->asoc.stream_reset_outstanding) {
5659 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
5661 SCTP_TCB_UNLOCK(stcb);
5664 /* Is there any data pending in the send or sent queues? */
5665 if (!TAILQ_EMPTY(&stcb->asoc.send_queue) ||
5666 !TAILQ_EMPTY(&stcb->asoc.sent_queue)) {
5669 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
5670 SCTP_TCB_UNLOCK(stcb);
5673 /* Do any streams have data queued? */
5674 for ( i = 0; i< stcb->asoc.streamoutcnt; i++) {
5675 if (!TAILQ_EMPTY(&stcb->asoc.strmout[i].outqueue)) {
5679 error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 1, 0, 0, 0, 0);
5680 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
5681 SCTP_TCB_UNLOCK(stcb);
5684 case SCTP_CONNECT_X:
5685 if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
5686 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5690 error = sctp_do_connect_x(so, inp, optval, optsize, p, 0);
5692 case SCTP_CONNECT_X_DELAYED:
5693 if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
5694 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5698 error = sctp_do_connect_x(so, inp, optval, optsize, p, 1);
5700 case SCTP_CONNECT_X_COMPLETE:
5702 struct sockaddr *sa;
5704 /* FIXME MT: check correct? */
5705 SCTP_CHECK_AND_CAST(sa, optval, struct sockaddr, optsize);
5708 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
5709 SCTP_INP_RLOCK(inp);
5710 stcb = LIST_FIRST(&inp->sctp_asoc_list);
5712 SCTP_TCB_LOCK(stcb);
5714 SCTP_INP_RUNLOCK(inp);
5716 /* We increment here since sctp_findassociation_ep_addr() wil
5717 * do a decrement if it finds the stcb as long as the locked
5718 * tcb (last argument) is NOT a TCB.. aka NULL.
5720 SCTP_INP_INCR_REF(inp);
5721 stcb = sctp_findassociation_ep_addr(&inp, sa, NULL, NULL, NULL);
5723 SCTP_INP_DECR_REF(inp);
5728 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
5732 if (stcb->asoc.delayed_connection == 1) {
5733 stcb->asoc.delayed_connection = 0;
5734 (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
5735 sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb,
5736 stcb->asoc.primary_destination,
5737 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_8);
5738 sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
5741 * already expired or did not use delayed
5744 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
5747 SCTP_TCB_UNLOCK(stcb);
5750 case SCTP_MAX_BURST:
5752 struct sctp_assoc_value *av;
5754 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
5755 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
5758 stcb->asoc.max_burst = av->assoc_value;
5759 SCTP_TCB_UNLOCK(stcb);
5761 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5762 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5763 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5764 ((av->assoc_id == SCTP_FUTURE_ASSOC) ||
5765 (av->assoc_id == SCTP_ALL_ASSOC)))) {
5766 SCTP_INP_WLOCK(inp);
5767 inp->sctp_ep.max_burst = av->assoc_value;
5768 SCTP_INP_WUNLOCK(inp);
5770 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5771 ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
5772 (av->assoc_id == SCTP_ALL_ASSOC))) {
5773 SCTP_INP_RLOCK(inp);
5774 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5775 SCTP_TCB_LOCK(stcb);
5776 stcb->asoc.max_burst = av->assoc_value;
5777 SCTP_TCB_UNLOCK(stcb);
5779 SCTP_INP_RUNLOCK(inp);
5786 struct sctp_assoc_value *av;
5789 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
5790 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
5792 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
5793 ovh = SCTP_MED_OVERHEAD;
5795 ovh = SCTP_MED_V4_OVERHEAD;
5798 if (av->assoc_value) {
5799 stcb->asoc.sctp_frag_point = (av->assoc_value + ovh);
5801 stcb->asoc.sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
5803 SCTP_TCB_UNLOCK(stcb);
5805 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5806 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5807 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5808 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
5809 SCTP_INP_WLOCK(inp);
5810 /* FIXME MT: I think this is not in tune with the API ID */
5811 if (av->assoc_value) {
5812 inp->sctp_frag_point = (av->assoc_value + ovh);
5814 inp->sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
5816 SCTP_INP_WUNLOCK(inp);
5818 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5826 struct sctp_event_subscribe *events;
5828 SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, optsize);
5830 SCTP_INP_WLOCK(inp);
5831 if (events->sctp_data_io_event) {
5832 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
5834 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
5837 if (events->sctp_association_event) {
5838 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
5840 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
5843 if (events->sctp_address_event) {
5844 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
5846 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
5849 if (events->sctp_send_failure_event) {
5850 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
5852 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
5855 if (events->sctp_peer_error_event) {
5856 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPEERERR);
5858 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPEERERR);
5861 if (events->sctp_shutdown_event) {
5862 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
5864 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
5867 if (events->sctp_partial_delivery_event) {
5868 sctp_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
5870 sctp_feature_off(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
5873 if (events->sctp_adaptation_layer_event) {
5874 sctp_feature_on(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
5876 sctp_feature_off(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
5879 if (events->sctp_authentication_event) {
5880 sctp_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT);
5882 sctp_feature_off(inp, SCTP_PCB_FLAGS_AUTHEVNT);
5885 if (events->sctp_sender_dry_event) {
5886 sctp_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT);
5888 sctp_feature_off(inp, SCTP_PCB_FLAGS_DRYEVNT);
5891 if (events->sctp_stream_reset_event) {
5892 sctp_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
5894 sctp_feature_off(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
5896 SCTP_INP_WUNLOCK(inp);
5898 SCTP_INP_RLOCK(inp);
5899 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5900 SCTP_TCB_LOCK(stcb);
5901 if (events->sctp_association_event) {
5902 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
5904 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
5906 if (events->sctp_address_event) {
5907 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
5909 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
5911 if (events->sctp_send_failure_event) {
5912 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
5914 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
5916 if (events->sctp_peer_error_event) {
5917 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
5919 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
5921 if (events->sctp_shutdown_event) {
5922 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
5924 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
5926 if (events->sctp_partial_delivery_event) {
5927 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
5929 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
5931 if (events->sctp_adaptation_layer_event) {
5932 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
5934 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
5936 if (events->sctp_authentication_event) {
5937 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
5939 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
5941 if (events->sctp_sender_dry_event) {
5942 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
5944 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
5946 if (events->sctp_stream_reset_event) {
5947 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
5949 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
5951 SCTP_TCB_UNLOCK(stcb);
5953 /* Send up the sender dry event only for 1-to-1 style sockets. */
5954 if (events->sctp_sender_dry_event) {
5955 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5956 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
5957 stcb = LIST_FIRST(&inp->sctp_asoc_list);
5959 SCTP_TCB_LOCK(stcb);
5960 if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
5961 TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
5962 (stcb->asoc.stream_queue_cnt == 0)) {
5963 sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_LOCKED);
5965 SCTP_TCB_UNLOCK(stcb);
5969 SCTP_INP_RUNLOCK(inp);
5972 case SCTP_ADAPTATION_LAYER:
5974 struct sctp_setadaptation *adap_bits;
5976 SCTP_CHECK_AND_CAST(adap_bits, optval, struct sctp_setadaptation, optsize);
5977 SCTP_INP_WLOCK(inp);
5978 inp->sctp_ep.adaptation_layer_indicator = adap_bits->ssb_adaptation_ind;
5979 inp->sctp_ep.adaptation_layer_indicator_provided = 1;
5980 SCTP_INP_WUNLOCK(inp);
5984 case SCTP_SET_INITIAL_DBG_SEQ:
5988 SCTP_CHECK_AND_CAST(vvv, optval, uint32_t, optsize);
5989 SCTP_INP_WLOCK(inp);
5990 inp->sctp_ep.initial_sequence_debug = *vvv;
5991 SCTP_INP_WUNLOCK(inp);
5995 case SCTP_DEFAULT_SEND_PARAM:
5997 struct sctp_sndrcvinfo *s_info;
5999 SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, optsize);
6000 SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
6003 if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
6004 memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
6006 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6009 SCTP_TCB_UNLOCK(stcb);
6011 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6012 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6013 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6014 ((s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC) ||
6015 (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)))) {
6016 SCTP_INP_WLOCK(inp);
6017 memcpy(&inp->def_send, s_info, min(optsize, sizeof(inp->def_send)));
6018 SCTP_INP_WUNLOCK(inp);
6020 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6021 ((s_info->sinfo_assoc_id == SCTP_CURRENT_ASSOC) ||
6022 (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC))) {
6023 SCTP_INP_RLOCK(inp);
6024 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
6025 SCTP_TCB_LOCK(stcb);
6026 if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
6027 memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
6029 SCTP_TCB_UNLOCK(stcb);
6031 SCTP_INP_RUNLOCK(inp);
6036 case SCTP_PEER_ADDR_PARAMS:
6038 struct sctp_paddrparams *paddrp;
6039 struct sctp_nets *net;
6040 struct sockaddr *addr;
6041 #if defined(INET) && defined(INET6)
6042 struct sockaddr_in sin_store;
6045 SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, optsize);
6046 SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
6048 #if defined(INET) && defined(INET6)
6049 if (paddrp->spp_address.ss_family == AF_INET6) {
6050 struct sockaddr_in6 *sin6;
6052 sin6 = (struct sockaddr_in6 *)&paddrp->spp_address;
6053 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
6054 in6_sin6_2_sin(&sin_store, sin6);
6055 addr = (struct sockaddr *)&sin_store;
6057 addr = (struct sockaddr *)&paddrp->spp_address;
6060 addr = (struct sockaddr *)&paddrp->spp_address;
6063 addr = (struct sockaddr *)&paddrp->spp_address;
6066 net = sctp_findnet(stcb, addr);
6068 /* We increment here since sctp_findassociation_ep_addr() wil
6069 * do a decrement if it finds the stcb as long as the locked
6070 * tcb (last argument) is NOT a TCB.. aka NULL.
6073 SCTP_INP_INCR_REF(inp);
6074 stcb = sctp_findassociation_ep_addr(&inp, addr,
6077 SCTP_INP_DECR_REF(inp);
6080 if ((stcb != NULL) && (net == NULL)) {
6082 if (addr->sa_family == AF_INET) {
6084 struct sockaddr_in *sin;
6085 sin = (struct sockaddr_in *)addr;
6086 if (sin->sin_addr.s_addr != INADDR_ANY) {
6087 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6088 SCTP_TCB_UNLOCK(stcb);
6095 if (addr->sa_family == AF_INET6) {
6096 struct sockaddr_in6 *sin6;
6098 sin6 = (struct sockaddr_in6 *)addr;
6099 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
6100 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6101 SCTP_TCB_UNLOCK(stcb);
6107 #if defined(__Userspace__)
6108 if (addr->sa_family == AF_CONN) {
6109 struct sockaddr_conn *sconn;
6111 sconn = (struct sockaddr_conn *)addr;
6112 if (sconn->sconn_addr != NULL) {
6113 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6114 SCTP_TCB_UNLOCK(stcb);
6121 error = EAFNOSUPPORT;
6122 SCTP_TCB_UNLOCK(stcb);
6123 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6128 if ((paddrp->spp_flags & SPP_HB_ENABLE) && (paddrp->spp_flags & SPP_HB_DISABLE)) {
6130 SCTP_TCB_UNLOCK(stcb);
6131 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6135 if ((paddrp->spp_flags & SPP_PMTUD_ENABLE) && (paddrp->spp_flags & SPP_PMTUD_DISABLE)) {
6137 SCTP_TCB_UNLOCK(stcb);
6138 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6141 if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) &&
6142 ((paddrp->spp_pathmtu < SCTP_SMALLEST_PMTU) ||
6143 (paddrp->spp_pathmtu > SCTP_LARGEST_PMTU))) {
6145 SCTP_TCB_UNLOCK(stcb);
6146 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6151 /************************TCB SPECIFIC SET ******************/
6153 /************************NET SPECIFIC SET ******************/
6154 if (paddrp->spp_flags & SPP_HB_DISABLE) {
6155 if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
6156 !(net->dest_state & SCTP_ADDR_NOHB)) {
6157 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
6158 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_9);
6160 net->dest_state |= SCTP_ADDR_NOHB;
6162 if (paddrp->spp_flags & SPP_HB_ENABLE) {
6163 if (paddrp->spp_hbinterval) {
6164 net->heart_beat_delay = paddrp->spp_hbinterval;
6165 } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
6166 net->heart_beat_delay = 0;
6168 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
6169 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
6170 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
6171 net->dest_state &= ~SCTP_ADDR_NOHB;
6173 if (paddrp->spp_flags & SPP_HB_DEMAND) {
6174 if (SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) {
6175 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
6176 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED);
6177 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
6180 if (paddrp->spp_flags & SPP_PMTUD_DISABLE) {
6181 if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
6182 sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
6183 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_11);
6185 net->dest_state |= SCTP_ADDR_NO_PMTUD;
6186 net->mtu = paddrp->spp_pathmtu;
6187 switch (net->ro._l_addr.sa.sa_family) {
6190 net->mtu += SCTP_MIN_V4_OVERHEAD;
6195 net->mtu += SCTP_MIN_OVERHEAD;
6198 #if defined(__Userspace__)
6200 net->mtu += sizeof(struct sctphdr);
6206 if (net->mtu < stcb->asoc.smallest_mtu) {
6207 sctp_pathmtu_adjustment(stcb, net->mtu);
6210 if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
6211 if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
6212 sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
6214 net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
6216 if (paddrp->spp_pathmaxrxt) {
6217 if (net->dest_state & SCTP_ADDR_PF) {
6218 if (net->error_count > paddrp->spp_pathmaxrxt) {
6219 net->dest_state &= ~SCTP_ADDR_PF;
6222 if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
6223 (net->error_count > net->pf_threshold)) {
6224 net->dest_state |= SCTP_ADDR_PF;
6225 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
6226 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT,
6227 stcb->sctp_ep, stcb, net,
6228 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_12);
6229 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
6232 if (net->dest_state & SCTP_ADDR_REACHABLE) {
6233 if (net->error_count > paddrp->spp_pathmaxrxt) {
6234 net->dest_state &= ~SCTP_ADDR_REACHABLE;
6235 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
6238 if (net->error_count <= paddrp->spp_pathmaxrxt) {
6239 net->dest_state |= SCTP_ADDR_REACHABLE;
6240 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
6243 net->failure_threshold = paddrp->spp_pathmaxrxt;
6245 if (paddrp->spp_flags & SPP_DSCP) {
6246 net->dscp = paddrp->spp_dscp & 0xfc;
6250 if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
6251 if (net->ro._l_addr.sa.sa_family == AF_INET6) {
6252 net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
6253 net->flowlabel |= 0x80000000;
6258 /************************ASSOC ONLY -- NO NET SPECIFIC SET ******************/
6259 if (paddrp->spp_pathmaxrxt != 0) {
6260 stcb->asoc.def_net_failure = paddrp->spp_pathmaxrxt;
6261 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6262 if (net->dest_state & SCTP_ADDR_PF) {
6263 if (net->error_count > paddrp->spp_pathmaxrxt) {
6264 net->dest_state &= ~SCTP_ADDR_PF;
6267 if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
6268 (net->error_count > net->pf_threshold)) {
6269 net->dest_state |= SCTP_ADDR_PF;
6270 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
6271 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT,
6272 stcb->sctp_ep, stcb, net,
6273 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_13);
6274 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
6277 if (net->dest_state & SCTP_ADDR_REACHABLE) {
6278 if (net->error_count > paddrp->spp_pathmaxrxt) {
6279 net->dest_state &= ~SCTP_ADDR_REACHABLE;
6280 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
6283 if (net->error_count <= paddrp->spp_pathmaxrxt) {
6284 net->dest_state |= SCTP_ADDR_REACHABLE;
6285 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
6288 net->failure_threshold = paddrp->spp_pathmaxrxt;
6292 if (paddrp->spp_flags & SPP_HB_ENABLE) {
6293 if (paddrp->spp_hbinterval != 0) {
6294 stcb->asoc.heart_beat_delay = paddrp->spp_hbinterval;
6295 } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
6296 stcb->asoc.heart_beat_delay = 0;
6298 /* Turn back on the timer */
6299 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6300 if (paddrp->spp_hbinterval != 0) {
6301 net->heart_beat_delay = paddrp->spp_hbinterval;
6302 } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
6303 net->heart_beat_delay = 0;
6305 if (net->dest_state & SCTP_ADDR_NOHB) {
6306 net->dest_state &= ~SCTP_ADDR_NOHB;
6308 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
6309 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_14);
6310 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
6312 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
6314 if (paddrp->spp_flags & SPP_HB_DISABLE) {
6315 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6316 if (!(net->dest_state & SCTP_ADDR_NOHB)) {
6317 net->dest_state |= SCTP_ADDR_NOHB;
6318 if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED)) {
6319 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT,
6321 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_15);
6325 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
6327 if (paddrp->spp_flags & SPP_PMTUD_DISABLE) {
6328 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6329 if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
6330 sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
6331 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_16);
6333 net->dest_state |= SCTP_ADDR_NO_PMTUD;
6334 net->mtu = paddrp->spp_pathmtu;
6335 switch (net->ro._l_addr.sa.sa_family) {
6338 net->mtu += SCTP_MIN_V4_OVERHEAD;
6343 net->mtu += SCTP_MIN_OVERHEAD;
6346 #if defined(__Userspace__)
6348 net->mtu += sizeof(struct sctphdr);
6354 if (net->mtu < stcb->asoc.smallest_mtu) {
6355 sctp_pathmtu_adjustment(stcb, net->mtu);
6358 stcb->asoc.default_mtu = paddrp->spp_pathmtu;
6359 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
6361 if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
6362 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6363 if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
6364 sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
6366 net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
6368 stcb->asoc.default_mtu = 0;
6369 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
6371 if (paddrp->spp_flags & SPP_DSCP) {
6372 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6373 net->dscp = paddrp->spp_dscp & 0xfc;
6376 stcb->asoc.default_dscp = paddrp->spp_dscp & 0xfc;
6377 stcb->asoc.default_dscp |= 0x01;
6380 if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
6381 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6382 if (net->ro._l_addr.sa.sa_family == AF_INET6) {
6383 net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
6384 net->flowlabel |= 0x80000000;
6387 stcb->asoc.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
6388 stcb->asoc.default_flowlabel |= 0x80000000;
6392 SCTP_TCB_UNLOCK(stcb);
6394 /************************NO TCB, SET TO default stuff ******************/
6395 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6396 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6397 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6398 (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC))) {
6399 SCTP_INP_WLOCK(inp);
6401 * For the TOS/FLOWLABEL stuff you set it
6402 * with the options on the socket
6404 if (paddrp->spp_pathmaxrxt != 0) {
6405 inp->sctp_ep.def_net_failure = paddrp->spp_pathmaxrxt;
6408 if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO)
6409 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
6410 else if (paddrp->spp_hbinterval != 0) {
6411 if (paddrp->spp_hbinterval > SCTP_MAX_HB_INTERVAL)
6412 paddrp->spp_hbinterval= SCTP_MAX_HB_INTERVAL;
6413 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = sctp_msecs_to_ticks(paddrp->spp_hbinterval);
6416 if (paddrp->spp_flags & SPP_HB_ENABLE) {
6417 if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
6418 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
6419 } else if (paddrp->spp_hbinterval) {
6420 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = sctp_msecs_to_ticks(paddrp->spp_hbinterval);
6422 sctp_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
6423 } else if (paddrp->spp_flags & SPP_HB_DISABLE) {
6424 sctp_feature_on(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
6426 if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
6427 inp->sctp_ep.default_mtu = 0;
6428 sctp_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
6429 } else if (paddrp->spp_flags & SPP_PMTUD_DISABLE) {
6430 inp->sctp_ep.default_mtu = paddrp->spp_pathmtu;
6431 sctp_feature_on(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
6433 if (paddrp->spp_flags & SPP_DSCP) {
6434 inp->sctp_ep.default_dscp = paddrp->spp_dscp & 0xfc;
6435 inp->sctp_ep.default_dscp |= 0x01;
6438 if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
6439 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
6440 inp->sctp_ep.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
6441 inp->sctp_ep.default_flowlabel |= 0x80000000;
6445 SCTP_INP_WUNLOCK(inp);
6447 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6455 struct sctp_rtoinfo *srto;
6456 uint32_t new_init, new_min, new_max;
6458 SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, optsize);
6459 SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
6462 if (srto->srto_initial)
6463 new_init = srto->srto_initial;
6465 new_init = stcb->asoc.initial_rto;
6467 new_max = srto->srto_max;
6469 new_max = stcb->asoc.maxrto;
6471 new_min = srto->srto_min;
6473 new_min = stcb->asoc.minrto;
6474 if ((new_min <= new_init) && (new_init <= new_max)) {
6475 stcb->asoc.initial_rto = new_init;
6476 stcb->asoc.maxrto = new_max;
6477 stcb->asoc.minrto = new_min;
6479 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6482 SCTP_TCB_UNLOCK(stcb);
6484 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6485 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6486 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6487 (srto->srto_assoc_id == SCTP_FUTURE_ASSOC))) {
6488 SCTP_INP_WLOCK(inp);
6489 if (srto->srto_initial)
6490 new_init = srto->srto_initial;
6492 new_init = inp->sctp_ep.initial_rto;
6494 new_max = srto->srto_max;
6496 new_max = inp->sctp_ep.sctp_maxrto;
6498 new_min = srto->srto_min;
6500 new_min = inp->sctp_ep.sctp_minrto;
6501 if ((new_min <= new_init) && (new_init <= new_max)) {
6502 inp->sctp_ep.initial_rto = new_init;
6503 inp->sctp_ep.sctp_maxrto = new_max;
6504 inp->sctp_ep.sctp_minrto = new_min;
6506 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6509 SCTP_INP_WUNLOCK(inp);
6511 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6517 case SCTP_ASSOCINFO:
6519 struct sctp_assocparams *sasoc;
6521 SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, optsize);
6522 SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
6523 if (sasoc->sasoc_cookie_life) {
6524 /* boundary check the cookie life */
6525 if (sasoc->sasoc_cookie_life < 1000)
6526 sasoc->sasoc_cookie_life = 1000;
6527 if (sasoc->sasoc_cookie_life > SCTP_MAX_COOKIE_LIFE) {
6528 sasoc->sasoc_cookie_life = SCTP_MAX_COOKIE_LIFE;
6532 if (sasoc->sasoc_asocmaxrxt)
6533 stcb->asoc.max_send_times = sasoc->sasoc_asocmaxrxt;
6534 if (sasoc->sasoc_cookie_life) {
6535 stcb->asoc.cookie_life = sctp_msecs_to_ticks(sasoc->sasoc_cookie_life);
6537 SCTP_TCB_UNLOCK(stcb);
6539 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6540 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6541 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6542 (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC))) {
6543 SCTP_INP_WLOCK(inp);
6544 if (sasoc->sasoc_asocmaxrxt)
6545 inp->sctp_ep.max_send_times = sasoc->sasoc_asocmaxrxt;
6546 if (sasoc->sasoc_cookie_life) {
6547 inp->sctp_ep.def_cookie_life = sctp_msecs_to_ticks(sasoc->sasoc_cookie_life);
6549 SCTP_INP_WUNLOCK(inp);
6551 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6559 struct sctp_initmsg *sinit;
6561 SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, optsize);
6562 SCTP_INP_WLOCK(inp);
6563 if (sinit->sinit_num_ostreams)
6564 inp->sctp_ep.pre_open_stream_count = sinit->sinit_num_ostreams;
6566 if (sinit->sinit_max_instreams)
6567 inp->sctp_ep.max_open_streams_intome = sinit->sinit_max_instreams;
6569 if (sinit->sinit_max_attempts)
6570 inp->sctp_ep.max_init_times = sinit->sinit_max_attempts;
6572 if (sinit->sinit_max_init_timeo)
6573 inp->sctp_ep.initial_init_rto_max = sinit->sinit_max_init_timeo;
6574 SCTP_INP_WUNLOCK(inp);
6577 case SCTP_PRIMARY_ADDR:
6579 struct sctp_setprim *spa;
6580 struct sctp_nets *net;
6581 struct sockaddr *addr;
6582 #if defined(INET) && defined(INET6)
6583 struct sockaddr_in sin_store;
6586 SCTP_CHECK_AND_CAST(spa, optval, struct sctp_setprim, optsize);
6587 SCTP_FIND_STCB(inp, stcb, spa->ssp_assoc_id);
6589 #if defined(INET) && defined(INET6)
6590 if (spa->ssp_addr.ss_family == AF_INET6) {
6591 struct sockaddr_in6 *sin6;
6593 sin6 = (struct sockaddr_in6 *)&spa->ssp_addr;
6594 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
6595 in6_sin6_2_sin(&sin_store, sin6);
6596 addr = (struct sockaddr *)&sin_store;
6598 addr = (struct sockaddr *)&spa->ssp_addr;
6601 addr = (struct sockaddr *)&spa->ssp_addr;
6604 addr = (struct sockaddr *)&spa->ssp_addr;
6607 net = sctp_findnet(stcb, addr);
6609 /* We increment here since sctp_findassociation_ep_addr() wil
6610 * do a decrement if it finds the stcb as long as the locked
6611 * tcb (last argument) is NOT a TCB.. aka NULL.
6614 SCTP_INP_INCR_REF(inp);
6615 stcb = sctp_findassociation_ep_addr(&inp, addr,
6618 SCTP_INP_DECR_REF(inp);
6622 if ((stcb != NULL) && (net != NULL)) {
6623 if (net != stcb->asoc.primary_destination) {
6624 if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED)) {
6625 /* Ok we need to set it */
6626 if (sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net) == 0) {
6627 if ((stcb->asoc.alternate) &&
6628 (!(net->dest_state & SCTP_ADDR_PF)) &&
6629 (net->dest_state & SCTP_ADDR_REACHABLE)) {
6630 sctp_free_remote_addr(stcb->asoc.alternate);
6631 stcb->asoc.alternate = NULL;
6634 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6638 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6643 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6647 SCTP_TCB_UNLOCK(stcb);
6651 case SCTP_SET_DYNAMIC_PRIMARY:
6653 union sctp_sockstore *ss;
6657 #if !defined(_WIN32) && !defined(__Userspace__)
6658 #if defined(__APPLE__)
6661 #if defined(__FreeBSD__)
6662 error = priv_check(curthread,
6663 PRIV_NETINET_RESERVEDPORT);
6664 #elif defined(__APPLE__)
6665 proc = (struct proc *)p;
6667 error = suser(proc->p_ucred, &proc->p_acflag);
6672 error = suser(p, 0);
6678 SCTP_CHECK_AND_CAST(ss, optval, union sctp_sockstore, optsize);
6679 /* SUPER USER CHECK? */
6681 for (i = 0; i < inp->num_vrfs; i++) {
6682 if (vrf_id == inp->m_vrf_ids[i]) {
6688 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6693 error = sctp_dynamic_set_primary(&ss->sa, vrf_id);
6696 case SCTP_SET_PEER_PRIMARY_ADDR:
6698 struct sctp_setpeerprim *sspp;
6699 struct sockaddr *addr;
6700 #if defined(INET) && defined(INET6)
6701 struct sockaddr_in sin_store;
6704 SCTP_CHECK_AND_CAST(sspp, optval, struct sctp_setpeerprim, optsize);
6705 SCTP_FIND_STCB(inp, stcb, sspp->sspp_assoc_id);
6707 struct sctp_ifa *ifa;
6709 #if defined(INET) && defined(INET6)
6710 if (sspp->sspp_addr.ss_family == AF_INET6) {
6711 struct sockaddr_in6 *sin6;
6713 sin6 = (struct sockaddr_in6 *)&sspp->sspp_addr;
6714 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
6715 in6_sin6_2_sin(&sin_store, sin6);
6716 addr = (struct sockaddr *)&sin_store;
6718 addr = (struct sockaddr *)&sspp->sspp_addr;
6721 addr = (struct sockaddr *)&sspp->sspp_addr;
6724 addr = (struct sockaddr *)&sspp->sspp_addr;
6726 ifa = sctp_find_ifa_by_addr(addr, stcb->asoc.vrf_id, SCTP_ADDR_NOT_LOCKED);
6728 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6732 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
6733 /* Must validate the ifa found is in our ep */
6734 struct sctp_laddr *laddr;
6737 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
6738 if (laddr->ifa == NULL) {
6739 SCTPDBG(SCTP_DEBUG_OUTPUT1, "%s: NULL ifa\n",
6743 if ((sctp_is_addr_restricted(stcb, laddr->ifa)) &&
6744 (!sctp_is_addr_pending(stcb, laddr->ifa))) {
6747 if (laddr->ifa == ifa) {
6753 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6757 #if defined(__FreeBSD__) && !defined(__Userspace__)
6759 switch (addr->sa_family) {
6763 struct sockaddr_in *sin;
6765 sin = (struct sockaddr_in *)addr;
6766 if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
6767 &sin->sin_addr) != 0) {
6768 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6778 struct sockaddr_in6 *sin6;
6780 sin6 = (struct sockaddr_in6 *)addr;
6781 if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
6782 &sin6->sin6_addr) != 0) {
6783 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6791 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6797 if (sctp_set_primary_ip_address_sa(stcb, addr) != 0) {
6798 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6801 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED);
6803 SCTP_TCB_UNLOCK(stcb);
6805 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6810 case SCTP_BINDX_ADD_ADDR:
6812 struct sockaddr *sa;
6813 #if defined(__FreeBSD__) && !defined(__Userspace__)
6816 td = (struct thread *)p;
6818 SCTP_CHECK_AND_CAST(sa, optval, struct sockaddr, optsize);
6820 if (sa->sa_family == AF_INET) {
6821 if (optsize < sizeof(struct sockaddr_in)) {
6822 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6826 #if defined(__FreeBSD__) && !defined(__Userspace__)
6828 (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)sa)->sin_addr)))) {
6829 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
6836 if (sa->sa_family == AF_INET6) {
6837 if (optsize < sizeof(struct sockaddr_in6)) {
6838 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6842 #if defined(__FreeBSD__) && !defined(__Userspace__)
6844 (error = prison_local_ip6(td->td_ucred,
6845 &(((struct sockaddr_in6 *)sa)->sin6_addr),
6846 (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
6847 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
6854 error = EAFNOSUPPORT;
6857 sctp_bindx_add_address(so, inp, sa, vrf_id, &error, p);
6860 case SCTP_BINDX_REM_ADDR:
6862 struct sockaddr *sa;
6863 #if defined(__FreeBSD__) && !defined(__Userspace__)
6865 td = (struct thread *)p;
6868 SCTP_CHECK_AND_CAST(sa, optval, struct sockaddr, optsize);
6870 if (sa->sa_family == AF_INET) {
6871 if (optsize < sizeof(struct sockaddr_in)) {
6872 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6876 #if defined(__FreeBSD__) && !defined(__Userspace__)
6878 (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)sa)->sin_addr)))) {
6879 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
6886 if (sa->sa_family == AF_INET6) {
6887 if (optsize < sizeof(struct sockaddr_in6)) {
6888 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6892 #if defined(__FreeBSD__) && !defined(__Userspace__)
6894 (error = prison_local_ip6(td->td_ucred,
6895 &(((struct sockaddr_in6 *)sa)->sin6_addr),
6896 (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
6897 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
6904 error = EAFNOSUPPORT;
6907 sctp_bindx_delete_address(inp, sa, vrf_id, &error);
6910 #if defined(__APPLE__) && !defined(__Userspace__)
6911 case SCTP_LISTEN_FIX:
6912 /* only applies to one-to-many sockets */
6913 if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
6914 /* make sure the ACCEPTCONN flag is OFF */
6915 so->so_options &= ~SO_ACCEPTCONN;
6917 /* otherwise, not allowed */
6918 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6925 struct sctp_event *event;
6926 uint32_t event_type;
6928 SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, optsize);
6929 SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
6930 switch (event->se_type) {
6931 case SCTP_ASSOC_CHANGE:
6932 event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
6934 case SCTP_PEER_ADDR_CHANGE:
6935 event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
6937 case SCTP_REMOTE_ERROR:
6938 event_type = SCTP_PCB_FLAGS_RECVPEERERR;
6940 case SCTP_SEND_FAILED:
6941 event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
6943 case SCTP_SHUTDOWN_EVENT:
6944 event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
6946 case SCTP_ADAPTATION_INDICATION:
6947 event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
6949 case SCTP_PARTIAL_DELIVERY_EVENT:
6950 event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
6952 case SCTP_AUTHENTICATION_EVENT:
6953 event_type = SCTP_PCB_FLAGS_AUTHEVNT;
6955 case SCTP_STREAM_RESET_EVENT:
6956 event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
6958 case SCTP_SENDER_DRY_EVENT:
6959 event_type = SCTP_PCB_FLAGS_DRYEVNT;
6961 case SCTP_NOTIFICATIONS_STOPPED_EVENT:
6963 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
6966 case SCTP_ASSOC_RESET_EVENT:
6967 event_type = SCTP_PCB_FLAGS_ASSOC_RESETEVNT;
6969 case SCTP_STREAM_CHANGE_EVENT:
6970 event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT;
6972 case SCTP_SEND_FAILED_EVENT:
6973 event_type = SCTP_PCB_FLAGS_RECVNSENDFAILEVNT;
6977 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6981 if (event_type > 0) {
6984 sctp_stcb_feature_on(inp, stcb, event_type);
6985 if (event_type == SCTP_PCB_FLAGS_DRYEVNT) {
6986 if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
6987 TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
6988 (stcb->asoc.stream_queue_cnt == 0)) {
6989 sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_LOCKED);
6993 sctp_stcb_feature_off(inp, stcb, event_type);
6995 SCTP_TCB_UNLOCK(stcb);
6998 * We don't want to send up a storm of events,
6999 * so return an error for sender dry events
7001 if ((event_type == SCTP_PCB_FLAGS_DRYEVNT) &&
7002 (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7003 ((event->se_assoc_id == SCTP_ALL_ASSOC) ||
7004 (event->se_assoc_id == SCTP_CURRENT_ASSOC))) {
7005 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
7009 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
7010 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
7011 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7012 ((event->se_assoc_id == SCTP_FUTURE_ASSOC) ||
7013 (event->se_assoc_id == SCTP_ALL_ASSOC)))) {
7014 SCTP_INP_WLOCK(inp);
7016 sctp_feature_on(inp, event_type);
7018 sctp_feature_off(inp, event_type);
7020 SCTP_INP_WUNLOCK(inp);
7022 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7023 ((event->se_assoc_id == SCTP_CURRENT_ASSOC) ||
7024 (event->se_assoc_id == SCTP_ALL_ASSOC))) {
7025 SCTP_INP_RLOCK(inp);
7026 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
7027 SCTP_TCB_LOCK(stcb);
7029 sctp_stcb_feature_on(inp, stcb, event_type);
7031 sctp_stcb_feature_off(inp, stcb, event_type);
7033 SCTP_TCB_UNLOCK(stcb);
7035 SCTP_INP_RUNLOCK(inp);
7040 SCTP_TCB_UNLOCK(stcb);
7045 case SCTP_RECVRCVINFO:
7049 SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
7050 SCTP_INP_WLOCK(inp);
7052 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
7054 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
7056 SCTP_INP_WUNLOCK(inp);
7059 case SCTP_RECVNXTINFO:
7063 SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
7064 SCTP_INP_WLOCK(inp);
7066 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
7068 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
7070 SCTP_INP_WUNLOCK(inp);
7073 case SCTP_DEFAULT_SNDINFO:
7075 struct sctp_sndinfo *info;
7078 SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, optsize);
7079 SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
7082 if (info->snd_sid < stcb->asoc.streamoutcnt) {
7083 stcb->asoc.def_send.sinfo_stream = info->snd_sid;
7084 policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
7085 stcb->asoc.def_send.sinfo_flags = info->snd_flags;
7086 stcb->asoc.def_send.sinfo_flags |= policy;
7087 stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
7088 stcb->asoc.def_send.sinfo_context = info->snd_context;
7090 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7093 SCTP_TCB_UNLOCK(stcb);
7095 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
7096 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
7097 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7098 ((info->snd_assoc_id == SCTP_FUTURE_ASSOC) ||
7099 (info->snd_assoc_id == SCTP_ALL_ASSOC)))) {
7100 SCTP_INP_WLOCK(inp);
7101 inp->def_send.sinfo_stream = info->snd_sid;
7102 policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
7103 inp->def_send.sinfo_flags = info->snd_flags;
7104 inp->def_send.sinfo_flags |= policy;
7105 inp->def_send.sinfo_ppid = info->snd_ppid;
7106 inp->def_send.sinfo_context = info->snd_context;
7107 SCTP_INP_WUNLOCK(inp);
7109 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7110 ((info->snd_assoc_id == SCTP_CURRENT_ASSOC) ||
7111 (info->snd_assoc_id == SCTP_ALL_ASSOC))) {
7112 SCTP_INP_RLOCK(inp);
7113 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
7114 SCTP_TCB_LOCK(stcb);
7115 if (info->snd_sid < stcb->asoc.streamoutcnt) {
7116 stcb->asoc.def_send.sinfo_stream = info->snd_sid;
7117 policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
7118 stcb->asoc.def_send.sinfo_flags = info->snd_flags;
7119 stcb->asoc.def_send.sinfo_flags |= policy;
7120 stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
7121 stcb->asoc.def_send.sinfo_context = info->snd_context;
7123 SCTP_TCB_UNLOCK(stcb);
7125 SCTP_INP_RUNLOCK(inp);
7130 case SCTP_DEFAULT_PRINFO:
7132 struct sctp_default_prinfo *info;
7134 SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, optsize);
7135 SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
7137 if (info->pr_policy > SCTP_PR_SCTP_MAX) {
7139 SCTP_TCB_UNLOCK(stcb);
7141 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7146 stcb->asoc.def_send.sinfo_flags &= 0xfff0;
7147 stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
7148 stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
7149 SCTP_TCB_UNLOCK(stcb);
7151 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
7152 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
7153 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7154 ((info->pr_assoc_id == SCTP_FUTURE_ASSOC) ||
7155 (info->pr_assoc_id == SCTP_ALL_ASSOC)))) {
7156 SCTP_INP_WLOCK(inp);
7157 inp->def_send.sinfo_flags &= 0xfff0;
7158 inp->def_send.sinfo_flags |= info->pr_policy;
7159 inp->def_send.sinfo_timetolive = info->pr_value;
7160 SCTP_INP_WUNLOCK(inp);
7162 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7163 ((info->pr_assoc_id == SCTP_CURRENT_ASSOC) ||
7164 (info->pr_assoc_id == SCTP_ALL_ASSOC))) {
7165 SCTP_INP_RLOCK(inp);
7166 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
7167 SCTP_TCB_LOCK(stcb);
7168 stcb->asoc.def_send.sinfo_flags &= 0xfff0;
7169 stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
7170 stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
7171 SCTP_TCB_UNLOCK(stcb);
7173 SCTP_INP_RUNLOCK(inp);
7178 case SCTP_PEER_ADDR_THLDS:
7179 /* Applies to the specific association */
7181 struct sctp_paddrthlds *thlds;
7182 struct sctp_nets *net;
7183 struct sockaddr *addr;
7184 #if defined(INET) && defined(INET6)
7185 struct sockaddr_in sin_store;
7188 SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, optsize);
7189 SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
7191 #if defined(INET) && defined(INET6)
7192 if (thlds->spt_address.ss_family == AF_INET6) {
7193 struct sockaddr_in6 *sin6;
7195 sin6 = (struct sockaddr_in6 *)&thlds->spt_address;
7196 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
7197 in6_sin6_2_sin(&sin_store, sin6);
7198 addr = (struct sockaddr *)&sin_store;
7200 addr = (struct sockaddr *)&thlds->spt_address;
7203 addr = (struct sockaddr *)&thlds->spt_address;
7206 addr = (struct sockaddr *)&thlds->spt_address;
7209 net = sctp_findnet(stcb, addr);
7211 /* We increment here since sctp_findassociation_ep_addr() wil
7212 * do a decrement if it finds the stcb as long as the locked
7213 * tcb (last argument) is NOT a TCB.. aka NULL.
7216 SCTP_INP_INCR_REF(inp);
7217 stcb = sctp_findassociation_ep_addr(&inp, addr,
7220 SCTP_INP_DECR_REF(inp);
7223 if ((stcb != NULL) && (net == NULL)) {
7225 if (addr->sa_family == AF_INET) {
7227 struct sockaddr_in *sin;
7228 sin = (struct sockaddr_in *)addr;
7229 if (sin->sin_addr.s_addr != INADDR_ANY) {
7230 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7231 SCTP_TCB_UNLOCK(stcb);
7238 if (addr->sa_family == AF_INET6) {
7239 struct sockaddr_in6 *sin6;
7241 sin6 = (struct sockaddr_in6 *)addr;
7242 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
7243 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7244 SCTP_TCB_UNLOCK(stcb);
7250 #if defined(__Userspace__)
7251 if (addr->sa_family == AF_CONN) {
7252 struct sockaddr_conn *sconn;
7254 sconn = (struct sockaddr_conn *)addr;
7255 if (sconn->sconn_addr != NULL) {
7256 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7257 SCTP_TCB_UNLOCK(stcb);
7264 error = EAFNOSUPPORT;
7265 SCTP_TCB_UNLOCK(stcb);
7266 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
7270 if (thlds->spt_pathcpthld != 0xffff) {
7272 SCTP_TCB_UNLOCK(stcb);
7275 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
7280 net->failure_threshold = thlds->spt_pathmaxrxt;
7281 net->pf_threshold = thlds->spt_pathpfthld;
7282 if (net->dest_state & SCTP_ADDR_PF) {
7283 if ((net->error_count > net->failure_threshold) ||
7284 (net->error_count <= net->pf_threshold)) {
7285 net->dest_state &= ~SCTP_ADDR_PF;
7288 if ((net->error_count > net->pf_threshold) &&
7289 (net->error_count <= net->failure_threshold)) {
7290 net->dest_state |= SCTP_ADDR_PF;
7291 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
7292 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT,
7293 stcb->sctp_ep, stcb, net,
7294 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_17);
7295 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
7298 if (net->dest_state & SCTP_ADDR_REACHABLE) {
7299 if (net->error_count > net->failure_threshold) {
7300 net->dest_state &= ~SCTP_ADDR_REACHABLE;
7301 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
7304 if (net->error_count <= net->failure_threshold) {
7305 net->dest_state |= SCTP_ADDR_REACHABLE;
7306 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
7310 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
7311 net->failure_threshold = thlds->spt_pathmaxrxt;
7312 net->pf_threshold = thlds->spt_pathpfthld;
7313 if (net->dest_state & SCTP_ADDR_PF) {
7314 if ((net->error_count > net->failure_threshold) ||
7315 (net->error_count <= net->pf_threshold)) {
7316 net->dest_state &= ~SCTP_ADDR_PF;
7319 if ((net->error_count > net->pf_threshold) &&
7320 (net->error_count <= net->failure_threshold)) {
7321 net->dest_state |= SCTP_ADDR_PF;
7322 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
7323 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT,
7324 stcb->sctp_ep, stcb, net,
7325 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_18);
7326 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
7329 if (net->dest_state & SCTP_ADDR_REACHABLE) {
7330 if (net->error_count > net->failure_threshold) {
7331 net->dest_state &= ~SCTP_ADDR_REACHABLE;
7332 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
7335 if (net->error_count <= net->failure_threshold) {
7336 net->dest_state |= SCTP_ADDR_REACHABLE;
7337 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
7341 stcb->asoc.def_net_failure = thlds->spt_pathmaxrxt;
7342 stcb->asoc.def_net_pf_threshold = thlds->spt_pathpfthld;
7344 SCTP_TCB_UNLOCK(stcb);
7346 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
7347 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
7348 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7349 (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC))) {
7350 SCTP_INP_WLOCK(inp);
7351 inp->sctp_ep.def_net_failure = thlds->spt_pathmaxrxt;
7352 inp->sctp_ep.def_net_pf_threshold = thlds->spt_pathpfthld;
7353 SCTP_INP_WUNLOCK(inp);
7355 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7361 case SCTP_REMOTE_UDP_ENCAPS_PORT:
7363 struct sctp_udpencaps *encaps;
7364 struct sctp_nets *net;
7365 struct sockaddr *addr;
7366 #if defined(INET) && defined(INET6)
7367 struct sockaddr_in sin_store;
7370 SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, optsize);
7371 SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
7373 #if defined(INET) && defined(INET6)
7374 if (encaps->sue_address.ss_family == AF_INET6) {
7375 struct sockaddr_in6 *sin6;
7377 sin6 = (struct sockaddr_in6 *)&encaps->sue_address;
7378 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
7379 in6_sin6_2_sin(&sin_store, sin6);
7380 addr = (struct sockaddr *)&sin_store;
7382 addr = (struct sockaddr *)&encaps->sue_address;
7385 addr = (struct sockaddr *)&encaps->sue_address;
7388 addr = (struct sockaddr *)&encaps->sue_address;
7391 net = sctp_findnet(stcb, addr);
7393 /* We increment here since sctp_findassociation_ep_addr() wil
7394 * do a decrement if it finds the stcb as long as the locked
7395 * tcb (last argument) is NOT a TCB.. aka NULL.
7398 SCTP_INP_INCR_REF(inp);
7399 stcb = sctp_findassociation_ep_addr(&inp, addr, &net, NULL, NULL);
7401 SCTP_INP_DECR_REF(inp);
7404 if ((stcb != NULL) && (net == NULL)) {
7406 if (addr->sa_family == AF_INET) {
7408 struct sockaddr_in *sin;
7409 sin = (struct sockaddr_in *)addr;
7410 if (sin->sin_addr.s_addr != INADDR_ANY) {
7411 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7412 SCTP_TCB_UNLOCK(stcb);
7419 if (addr->sa_family == AF_INET6) {
7420 struct sockaddr_in6 *sin6;
7422 sin6 = (struct sockaddr_in6 *)addr;
7423 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
7424 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7425 SCTP_TCB_UNLOCK(stcb);
7431 #if defined(__Userspace__)
7432 if (addr->sa_family == AF_CONN) {
7433 struct sockaddr_conn *sconn;
7435 sconn = (struct sockaddr_conn *)addr;
7436 if (sconn->sconn_addr != NULL) {
7437 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7438 SCTP_TCB_UNLOCK(stcb);
7445 error = EAFNOSUPPORT;
7446 SCTP_TCB_UNLOCK(stcb);
7447 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
7454 net->port = encaps->sue_port;
7456 stcb->asoc.port = encaps->sue_port;
7458 SCTP_TCB_UNLOCK(stcb);
7460 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
7461 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
7462 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7463 (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC))) {
7464 SCTP_INP_WLOCK(inp);
7465 inp->sctp_ep.port = encaps->sue_port;
7466 SCTP_INP_WUNLOCK(inp);
7468 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7474 case SCTP_ECN_SUPPORTED:
7476 struct sctp_assoc_value *av;
7478 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
7479 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
7482 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7484 SCTP_TCB_UNLOCK(stcb);
7486 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
7487 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
7488 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7489 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
7490 SCTP_INP_WLOCK(inp);
7491 if (av->assoc_value == 0) {
7492 inp->ecn_supported = 0;
7494 inp->ecn_supported = 1;
7496 SCTP_INP_WUNLOCK(inp);
7498 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7504 case SCTP_PR_SUPPORTED:
7506 struct sctp_assoc_value *av;
7508 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
7509 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
7512 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7514 SCTP_TCB_UNLOCK(stcb);
7516 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
7517 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
7518 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7519 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
7520 SCTP_INP_WLOCK(inp);
7521 if (av->assoc_value == 0) {
7522 inp->prsctp_supported = 0;
7524 inp->prsctp_supported = 1;
7526 SCTP_INP_WUNLOCK(inp);
7528 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7534 case SCTP_AUTH_SUPPORTED:
7536 struct sctp_assoc_value *av;
7538 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
7539 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
7542 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7544 SCTP_TCB_UNLOCK(stcb);
7546 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
7547 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
7548 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7549 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
7550 if ((av->assoc_value == 0) &&
7551 (inp->asconf_supported == 1)) {
7552 /* AUTH is required for ASCONF */
7553 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7556 SCTP_INP_WLOCK(inp);
7557 if (av->assoc_value == 0) {
7558 inp->auth_supported = 0;
7560 inp->auth_supported = 1;
7562 SCTP_INP_WUNLOCK(inp);
7565 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7571 case SCTP_ASCONF_SUPPORTED:
7573 struct sctp_assoc_value *av;
7575 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
7576 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
7579 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7581 SCTP_TCB_UNLOCK(stcb);
7583 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
7584 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
7585 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7586 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
7587 if ((av->assoc_value != 0) &&
7588 (inp->auth_supported == 0)) {
7589 /* AUTH is required for ASCONF */
7590 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7593 SCTP_INP_WLOCK(inp);
7594 if (av->assoc_value == 0) {
7595 inp->asconf_supported = 0;
7596 sctp_auth_delete_chunk(SCTP_ASCONF,
7597 inp->sctp_ep.local_auth_chunks);
7598 sctp_auth_delete_chunk(SCTP_ASCONF_ACK,
7599 inp->sctp_ep.local_auth_chunks);
7601 inp->asconf_supported = 1;
7602 sctp_auth_add_chunk(SCTP_ASCONF,
7603 inp->sctp_ep.local_auth_chunks);
7604 sctp_auth_add_chunk(SCTP_ASCONF_ACK,
7605 inp->sctp_ep.local_auth_chunks);
7607 SCTP_INP_WUNLOCK(inp);
7610 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7616 case SCTP_RECONFIG_SUPPORTED:
7618 struct sctp_assoc_value *av;
7620 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
7621 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
7624 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7626 SCTP_TCB_UNLOCK(stcb);
7628 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
7629 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
7630 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7631 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
7632 SCTP_INP_WLOCK(inp);
7633 if (av->assoc_value == 0) {
7634 inp->reconfig_supported = 0;
7636 inp->reconfig_supported = 1;
7638 SCTP_INP_WUNLOCK(inp);
7640 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7646 case SCTP_NRSACK_SUPPORTED:
7648 struct sctp_assoc_value *av;
7650 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
7651 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
7654 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7656 SCTP_TCB_UNLOCK(stcb);
7658 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
7659 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
7660 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7661 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
7662 SCTP_INP_WLOCK(inp);
7663 if (av->assoc_value == 0) {
7664 inp->nrsack_supported = 0;
7666 inp->nrsack_supported = 1;
7668 SCTP_INP_WUNLOCK(inp);
7670 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7676 case SCTP_PKTDROP_SUPPORTED:
7678 struct sctp_assoc_value *av;
7680 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
7681 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
7684 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7686 SCTP_TCB_UNLOCK(stcb);
7688 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
7689 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
7690 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7691 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
7692 SCTP_INP_WLOCK(inp);
7693 if (av->assoc_value == 0) {
7694 inp->pktdrop_supported = 0;
7696 inp->pktdrop_supported = 1;
7698 SCTP_INP_WUNLOCK(inp);
7700 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7708 struct sctp_assoc_value *av;
7709 struct sctp_nets *net;
7711 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
7712 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
7715 stcb->asoc.max_cwnd = av->assoc_value;
7716 if (stcb->asoc.max_cwnd > 0) {
7717 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
7718 if ((net->cwnd > stcb->asoc.max_cwnd) &&
7719 (net->cwnd > (net->mtu - sizeof(struct sctphdr)))) {
7720 net->cwnd = stcb->asoc.max_cwnd;
7721 if (net->cwnd < (net->mtu - sizeof(struct sctphdr))) {
7722 net->cwnd = net->mtu - sizeof(struct sctphdr);
7727 SCTP_TCB_UNLOCK(stcb);
7729 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
7730 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
7731 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7732 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
7733 SCTP_INP_WLOCK(inp);
7734 inp->max_cwnd = av->assoc_value;
7735 SCTP_INP_WUNLOCK(inp);
7737 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7744 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
7745 error = ENOPROTOOPT;
7747 } /* end switch (opt) */
7751 #if !defined(__Userspace__)
7753 sctp_ctloutput(struct socket *so, struct sockopt *sopt)
7755 #if defined(__FreeBSD__)
7756 struct epoch_tracker et;
7757 struct sctp_inpcb *inp;
7759 void *optval = NULL;
7764 #if defined(__FreeBSD__)
7765 if ((sopt->sopt_level == SOL_SOCKET) &&
7766 (sopt->sopt_name == SO_SETFIB)) {
7767 inp = (struct sctp_inpcb *)so->so_pcb;
7769 SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS);
7772 SCTP_INP_WLOCK(inp);
7773 inp->fibnum = so->so_fibnum;
7774 SCTP_INP_WUNLOCK(inp);
7778 if (sopt->sopt_level != IPPROTO_SCTP) {
7779 /* wrong proto level... send back up to IP */
7781 if (INP_CHECK_SOCKAF(so, AF_INET6))
7782 error = ip6_ctloutput(so, sopt);
7784 #if defined(INET) && defined(INET6)
7788 error = ip_ctloutput(so, sopt);
7792 optsize = sopt->sopt_valsize;
7793 if (optsize > SCTP_SOCKET_OPTION_LIMIT) {
7794 SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS);
7798 SCTP_MALLOC(optval, void *, optsize, SCTP_M_SOCKOPT);
7799 if (optval == NULL) {
7800 SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS);
7803 error = sooptcopyin(sopt, optval, optsize, optsize);
7805 SCTP_FREE(optval, SCTP_M_SOCKOPT);
7809 #if defined(__FreeBSD__) || defined(_WIN32)
7810 p = (void *)sopt->sopt_td;
7812 p = (void *)sopt->sopt_p;
7814 if (sopt->sopt_dir == SOPT_SET) {
7815 #if defined(__FreeBSD__)
7816 NET_EPOCH_ENTER(et);
7818 error = sctp_setopt(so, sopt->sopt_name, optval, optsize, p);
7819 #if defined(__FreeBSD__)
7822 } else if (sopt->sopt_dir == SOPT_GET) {
7823 error = sctp_getopt(so, sopt->sopt_name, optval, &optsize, p);
7825 SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7828 if ((error == 0) && (optval != NULL)) {
7829 error = sooptcopyout(sopt, optval, optsize);
7830 SCTP_FREE(optval, SCTP_M_SOCKOPT);
7831 } else if (optval != NULL) {
7832 SCTP_FREE(optval, SCTP_M_SOCKOPT);
7840 #if defined(__Userspace__)
7842 sctp_connect(struct socket *so, struct sockaddr *addr)
7845 #elif defined(__FreeBSD__)
7847 sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
7849 #elif defined(__APPLE__)
7851 sctp_connect(struct socket *so, struct sockaddr *addr, struct proc *p)
7853 #elif defined(_WIN32)
7855 sctp_connect(struct socket *so, struct sockaddr *addr, PKTHREAD p)
7859 sctp_connect(struct socket *so, struct mbuf *nam, struct proc *p)
7861 struct sockaddr *addr = mtod(nam, struct sockaddr *);
7864 #if defined(__FreeBSD__) && !defined(__Userspace__)
7865 struct epoch_tracker et;
7871 int create_lock_on = 0;
7873 struct sctp_inpcb *inp;
7874 struct sctp_tcb *stcb = NULL;
7876 inp = (struct sctp_inpcb *)so->so_pcb;
7878 /* I made the same as TCP since we are not setup? */
7879 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7880 return (ECONNRESET);
7883 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7887 #if defined(__Userspace__)
7888 /* TODO __Userspace__ falls into this code for IPv6 stuff at the moment... */
7890 #if !defined(_WIN32) && !defined(__linux__)
7891 switch (addr->sa_family) {
7895 #if defined(__FreeBSD__) && !defined(__Userspace__)
7896 struct sockaddr_in6 *sin6;
7899 if (addr->sa_len != sizeof(struct sockaddr_in6)) {
7900 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7903 #if defined(__FreeBSD__) && !defined(__Userspace__)
7904 sin6 = (struct sockaddr_in6 *)addr;
7905 if (p != NULL && (error = prison_remote_ip6(p->td_ucred, &sin6->sin6_addr)) != 0) {
7906 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
7916 #if defined(__FreeBSD__) && !defined(__Userspace__)
7917 struct sockaddr_in *sin;
7920 #if !defined(_WIN32)
7921 if (addr->sa_len != sizeof(struct sockaddr_in)) {
7922 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7926 #if defined(__FreeBSD__) && !defined(__Userspace__)
7927 sin = (struct sockaddr_in *)addr;
7928 if (p != NULL && (error = prison_remote_ip4(p->td_ucred, &sin->sin_addr)) != 0) {
7929 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
7937 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
7938 return (EAFNOSUPPORT);
7941 SCTP_INP_INCR_REF(inp);
7942 SCTP_ASOC_CREATE_LOCK(inp);
7944 #if defined(__FreeBSD__) && !defined(__Userspace__)
7945 NET_EPOCH_ENTER(et);
7948 if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
7949 (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
7950 /* Should I really unlock ? */
7951 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
7956 if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
7957 (addr->sa_family == AF_INET6)) {
7958 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7963 #if defined(__Userspace__)
7964 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_CONN) &&
7965 (addr->sa_family != AF_CONN)) {
7966 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7971 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
7972 SCTP_PCB_FLAGS_UNBOUND) {
7973 /* Bind a ephemeral port */
7974 error = sctp_inpcb_bind(so, NULL, NULL, p);
7979 /* Now do we connect? */
7980 if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
7981 (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
7982 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7986 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
7987 (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
7988 /* We are already connected AND the TCP model */
7989 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
7993 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
7994 SCTP_INP_RLOCK(inp);
7995 stcb = LIST_FIRST(&inp->sctp_asoc_list);
7996 SCTP_INP_RUNLOCK(inp);
7998 /* We increment here since sctp_findassociation_ep_addr() will
7999 * do a decrement if it finds the stcb as long as the locked
8000 * tcb (last argument) is NOT a TCB.. aka NULL.
8002 SCTP_INP_INCR_REF(inp);
8003 stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
8005 SCTP_INP_DECR_REF(inp);
8007 SCTP_TCB_UNLOCK(stcb);
8011 /* Already have or am bring up an association */
8012 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
8017 vrf_id = inp->def_vrf_id;
8019 for (i = 0; i < inp->num_vrfs; i++) {
8020 if (vrf_id == inp->m_vrf_ids[i]) {
8026 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8031 /* We are GOOD to go */
8032 stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id,
8033 inp->sctp_ep.pre_open_stream_count,
8034 inp->sctp_ep.port, p,
8035 SCTP_INITIALIZE_AUTH_PARAMS);
8037 /* Gak! no memory */
8040 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
8041 stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
8042 /* Set the connected flag so we can queue data */
8045 SCTP_SET_STATE(stcb, SCTP_STATE_COOKIE_WAIT);
8046 (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
8048 sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
8049 SCTP_TCB_UNLOCK(stcb);
8051 #if defined(__FreeBSD__) && !defined(__Userspace__)
8054 if (create_lock_on) {
8055 SCTP_ASOC_CREATE_UNLOCK(inp);
8057 SCTP_INP_DECR_REF(inp);
8062 #if defined(__Userspace__)
8064 sctpconn_connect(struct socket *so, struct sockaddr *addr)
8071 int create_lock_on = 0;
8073 struct sctp_inpcb *inp;
8074 struct sctp_tcb *stcb = NULL;
8076 inp = (struct sctp_inpcb *)so->so_pcb;
8078 /* I made the same as TCP since we are not setup? */
8079 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8080 return (ECONNRESET);
8083 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8086 switch (addr->sa_family) {
8090 if (addr->sa_len != sizeof(struct sockaddr_in)) {
8091 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8100 if (addr->sa_len != sizeof(struct sockaddr_in6)) {
8101 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8109 if (addr->sa_len != sizeof(struct sockaddr_conn)) {
8110 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8116 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
8117 return (EAFNOSUPPORT);
8119 SCTP_INP_INCR_REF(inp);
8120 SCTP_ASOC_CREATE_LOCK(inp);
8124 if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
8125 (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
8126 /* Should I really unlock ? */
8127 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
8132 if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
8133 (addr->sa_family == AF_INET6)) {
8134 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8139 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == SCTP_PCB_FLAGS_UNBOUND) {
8140 /* Bind a ephemeral port */
8141 error = sctp_inpcb_bind(so, NULL, NULL, p);
8146 /* Now do we connect? */
8147 if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
8148 (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
8149 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8153 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
8154 (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
8155 /* We are already connected AND the TCP model */
8156 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
8160 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
8161 SCTP_INP_RLOCK(inp);
8162 stcb = LIST_FIRST(&inp->sctp_asoc_list);
8163 SCTP_INP_RUNLOCK(inp);
8165 /* We increment here since sctp_findassociation_ep_addr() will
8166 * do a decrement if it finds the stcb as long as the locked
8167 * tcb (last argument) is NOT a TCB.. aka NULL.
8169 SCTP_INP_INCR_REF(inp);
8170 stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
8172 SCTP_INP_DECR_REF(inp);
8174 SCTP_TCB_UNLOCK(stcb);
8178 /* Already have or am bring up an association */
8179 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
8184 vrf_id = inp->def_vrf_id;
8186 for (i = 0; i < inp->num_vrfs; i++) {
8187 if (vrf_id == inp->m_vrf_ids[i]) {
8193 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8198 /* We are GOOD to go */
8199 stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id,
8200 inp->sctp_ep.pre_open_stream_count,
8201 inp->sctp_ep.port, p,
8202 SCTP_INITIALIZE_AUTH_PARAMS);
8204 /* Gak! no memory */
8207 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
8208 stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
8209 /* Set the connected flag so we can queue data */
8212 SCTP_SET_STATE(stcb, SCTP_STATE_COOKIE_WAIT);
8213 (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
8215 sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
8216 SCTP_TCB_UNLOCK(stcb);
8218 if (create_lock_on) {
8219 SCTP_ASOC_CREATE_UNLOCK(inp);
8222 SCTP_INP_DECR_REF(inp);
8227 #if defined(__Userspace__)
8228 sctp_listen(struct socket *so, int backlog, struct proc *p)
8229 #elif defined(__FreeBSD__)
8230 sctp_listen(struct socket *so, int backlog, struct thread *p)
8231 #elif defined(_WIN32)
8232 sctp_listen(struct socket *so, int backlog, PKTHREAD p)
8234 sctp_listen(struct socket *so, struct proc *p)
8238 * Note this module depends on the protocol processing being called
8239 * AFTER any socket level flags and backlog are applied to the
8240 * socket. The traditional way that the socket flags are applied is
8241 * AFTER protocol processing. We have made a change to the
8242 * sys/kern/uipc_socket.c module to reverse this but this MUST be in
8243 * place if the socket API for SCTP is to work properly.
8247 struct sctp_inpcb *inp;
8249 inp = (struct sctp_inpcb *)so->so_pcb;
8251 /* I made the same as TCP since we are not setup? */
8252 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8253 return (ECONNRESET);
8255 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) {
8256 /* See if we have a listener */
8257 struct sctp_inpcb *tinp;
8258 union sctp_sockstore store;
8260 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
8262 struct sctp_laddr *laddr;
8264 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
8265 memcpy(&store, &laddr->ifa->address, sizeof(store));
8266 switch (store.sa.sa_family) {
8269 store.sin.sin_port = inp->sctp_lport;
8274 store.sin6.sin6_port = inp->sctp_lport;
8277 #if defined(__Userspace__)
8279 store.sconn.sconn_port = inp->sctp_lport;
8285 tinp = sctp_pcb_findep(&store.sa, 0, 0, inp->def_vrf_id);
8286 if (tinp && (tinp != inp) &&
8287 ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
8288 ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
8289 (SCTP_IS_LISTENING(tinp))) {
8290 /* we have a listener already and its not this inp. */
8291 SCTP_INP_DECR_REF(tinp);
8292 return (EADDRINUSE);
8294 SCTP_INP_DECR_REF(tinp);
8298 /* Setup a local addr bound all */
8299 memset(&store, 0, sizeof(store));
8301 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
8302 store.sa.sa_family = AF_INET6;
8304 store.sa.sa_len = sizeof(struct sockaddr_in6);
8308 #if defined(__Userspace__)
8309 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_CONN) {
8310 store.sa.sa_family = AF_CONN;
8312 store.sa.sa_len = sizeof(struct sockaddr_conn);
8317 #if defined(__Userspace__)
8318 if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
8319 ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_CONN) == 0)) {
8321 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
8323 store.sa.sa_family = AF_INET;
8325 store.sa.sa_len = sizeof(struct sockaddr_in);
8329 switch (store.sa.sa_family) {
8332 store.sin.sin_port = inp->sctp_lport;
8337 store.sin6.sin6_port = inp->sctp_lport;
8340 #if defined(__Userspace__)
8342 store.sconn.sconn_port = inp->sctp_lport;
8348 tinp = sctp_pcb_findep(&store.sa, 0, 0, inp->def_vrf_id);
8349 if (tinp && (tinp != inp) &&
8350 ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
8351 ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
8352 (SCTP_IS_LISTENING(tinp))) {
8353 /* we have a listener already and its not this inp. */
8354 SCTP_INP_DECR_REF(tinp);
8355 return (EADDRINUSE);
8357 SCTP_INP_DECR_REF(tinp);
8361 SCTP_INP_RLOCK(inp);
8362 #ifdef SCTP_LOCK_LOGGING
8363 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) {
8364 sctp_log_lock(inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_SOCK);
8367 #if defined(__FreeBSD__) || defined(__Userspace__)
8369 error = solisten_proto_check(so);
8372 SCTP_INP_RUNLOCK(inp);
8376 if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) &&
8377 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
8379 * - We are in the tcp pool with this guy.
8380 * - Someone else is in the main inp slot.
8381 * - We must move this guy (the listener) to the main slot
8382 * - We must then move the guy that was listener to the TCP Pool.
8384 if (sctp_swap_inpcb_for_listen(inp)) {
8385 SCTP_INP_RUNLOCK(inp);
8386 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
8387 return (EADDRINUSE);
8391 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
8392 (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
8393 /* We are already connected AND the TCP model */
8394 SCTP_INP_RUNLOCK(inp);
8395 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
8396 return (EADDRINUSE);
8398 SCTP_INP_RUNLOCK(inp);
8399 if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
8400 /* We must do a bind. */
8401 if ((error = sctp_inpcb_bind(so, NULL, NULL, p))) {
8402 /* bind error, probably perm */
8406 SCTP_INP_WLOCK(inp);
8407 #if defined(__FreeBSD__) && !defined(__Userspace__)
8408 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) == 0) {
8410 solisten_proto(so, backlog);
8413 #elif defined(_WIN32) || defined(__Userspace__)
8415 solisten_proto(so, backlog);
8417 #if !(defined(__FreeBSD__) && !defined(__Userspace__))
8418 if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
8419 /* remove the ACCEPTCONN flag for one-to-many sockets */
8420 #if defined(__Userspace__)
8421 so->so_options &= ~SCTP_SO_ACCEPTCONN;
8423 so->so_options &= ~SO_ACCEPTCONN;
8428 #if defined(__FreeBSD__) || defined(_WIN32) || defined(__Userspace__)
8430 inp->sctp_flags |= SCTP_PCB_FLAGS_ACCEPTING;
8432 inp->sctp_flags &= ~SCTP_PCB_FLAGS_ACCEPTING;
8435 inp->sctp_flags |= SCTP_PCB_FLAGS_ACCEPTING;
8437 SCTP_INP_WUNLOCK(inp);
8441 static int sctp_defered_wakeup_cnt = 0;
8444 sctp_accept(struct socket *so, struct sockaddr **addr)
8446 struct sctp_tcb *stcb;
8447 struct sctp_inpcb *inp;
8448 union sctp_sockstore store;
8450 #if defined(SCTP_KAME) && defined(SCTP_EMBEDDED_V6_SCOPE)
8454 inp = (struct sctp_inpcb *)so->so_pcb;
8457 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8458 return (ECONNRESET);
8460 SCTP_INP_WLOCK(inp);
8461 if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
8462 SCTP_INP_WUNLOCK(inp);
8463 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
8464 return (EOPNOTSUPP);
8466 if (so->so_state & SS_ISDISCONNECTED) {
8467 SCTP_INP_WUNLOCK(inp);
8468 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ECONNABORTED);
8469 return (ECONNABORTED);
8471 stcb = LIST_FIRST(&inp->sctp_asoc_list);
8473 SCTP_INP_WUNLOCK(inp);
8474 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8475 return (ECONNRESET);
8477 SCTP_TCB_LOCK(stcb);
8478 store = stcb->asoc.primary_destination->ro._l_addr;
8479 SCTP_CLEAR_SUBSTATE(stcb, SCTP_STATE_IN_ACCEPT_QUEUE);
8480 /* Wake any delayed sleep action */
8481 if (inp->sctp_flags & SCTP_PCB_FLAGS_DONT_WAKE) {
8482 inp->sctp_flags &= ~SCTP_PCB_FLAGS_DONT_WAKE;
8483 if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEOUTPUT) {
8484 inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEOUTPUT;
8485 SOCKBUF_LOCK(&inp->sctp_socket->so_snd);
8486 if (sowriteable(inp->sctp_socket)) {
8487 #if defined(__Userspace__)
8488 /*__Userspace__ calling sowwakup_locked because of SOCKBUF_LOCK above. */
8490 #if defined(__FreeBSD__) || defined(_WIN32) || defined(__Userspace__)
8491 sowwakeup_locked(inp->sctp_socket);
8493 #if defined(__APPLE__)
8494 /* socket is locked */
8496 sowwakeup(inp->sctp_socket);
8499 SOCKBUF_UNLOCK(&inp->sctp_socket->so_snd);
8502 if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEINPUT) {
8503 inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEINPUT;
8504 SOCKBUF_LOCK(&inp->sctp_socket->so_rcv);
8505 if (soreadable(inp->sctp_socket)) {
8506 sctp_defered_wakeup_cnt++;
8507 #if defined(__Userspace__)
8508 /*__Userspace__ calling sorwakup_locked because of SOCKBUF_LOCK above */
8510 #if defined(__FreeBSD__) || defined(_WIN32) || defined(__Userspace__)
8511 sorwakeup_locked(inp->sctp_socket);
8513 #if defined(__APPLE__)
8514 /* socket is locked */
8516 sorwakeup(inp->sctp_socket);
8519 SOCKBUF_UNLOCK(&inp->sctp_socket->so_rcv);
8523 SCTP_INP_WUNLOCK(inp);
8524 if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
8525 sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
8526 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_19);
8528 SCTP_TCB_UNLOCK(stcb);
8530 switch (store.sa.sa_family) {
8534 struct sockaddr_in *sin;
8536 SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
8539 sin->sin_family = AF_INET;
8541 sin->sin_len = sizeof(*sin);
8543 sin->sin_port = store.sin.sin_port;
8544 sin->sin_addr = store.sin.sin_addr;
8545 *addr = (struct sockaddr *)sin;
8552 struct sockaddr_in6 *sin6;
8554 SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
8557 sin6->sin6_family = AF_INET6;
8558 #ifdef HAVE_SIN6_LEN
8559 sin6->sin6_len = sizeof(*sin6);
8561 sin6->sin6_port = store.sin6.sin6_port;
8562 sin6->sin6_addr = store.sin6.sin6_addr;
8563 #if defined(SCTP_EMBEDDED_V6_SCOPE)
8565 if ((error = sa6_recoverscope(sin6)) != 0) {
8566 SCTP_FREE_SONAME(sin6);
8570 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
8572 * sin6->sin6_scope_id =
8573 * ntohs(sin6->sin6_addr.s6_addr16[1]);
8575 in6_recoverscope(sin6, &sin6->sin6_addr, NULL); /* skip ifp check */
8577 sin6->sin6_scope_id = 0; /* XXX */
8578 #endif /* SCTP_KAME */
8579 #endif /* SCTP_EMBEDDED_V6_SCOPE */
8580 *addr = (struct sockaddr *)sin6;
8584 #if defined(__Userspace__)
8587 struct sockaddr_conn *sconn;
8589 SCTP_MALLOC_SONAME(sconn, struct sockaddr_conn *, sizeof(struct sockaddr_conn));
8590 if (sconn == NULL) {
8593 sconn->sconn_family = AF_CONN;
8594 #ifdef HAVE_SCONN_LEN
8595 sconn->sconn_len = sizeof(struct sockaddr_conn);
8597 sconn->sconn_port = store.sconn.sconn_port;
8598 sconn->sconn_addr = store.sconn.sconn_addr;
8599 *addr = (struct sockaddr *)sconn;
8612 #if !defined(__Userspace__)
8613 sctp_ingetaddr(struct socket *so, struct sockaddr **addr)
8615 struct sockaddr_in *sin;
8617 sctp_ingetaddr(struct socket *so, struct mbuf *nam)
8619 struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
8622 struct sctp_inpcb *inp;
8623 struct sctp_ifa *sctp_ifa;
8626 * Do the malloc first in case it blocks.
8628 #if !defined(__Userspace__)
8629 SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
8633 SCTP_BUF_LEN(nam) = sizeof(*sin);
8634 memset(sin, 0, sizeof(*sin));
8636 sin->sin_family = AF_INET;
8638 sin->sin_len = sizeof(*sin);
8640 inp = (struct sctp_inpcb *)so->so_pcb;
8642 #if !defined(__Userspace__)
8643 SCTP_FREE_SONAME(sin);
8645 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8646 return (ECONNRESET);
8648 SCTP_INP_RLOCK(inp);
8649 sin->sin_port = inp->sctp_lport;
8650 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
8651 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
8652 struct sctp_tcb *stcb;
8653 struct sockaddr_in *sin_a;
8654 struct sctp_nets *net;
8657 stcb = LIST_FIRST(&inp->sctp_asoc_list);
8663 SCTP_TCB_LOCK(stcb);
8664 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
8665 sin_a = (struct sockaddr_in *)&net->ro._l_addr;
8667 /* this will make coverity happy */
8670 if (sin_a->sin_family == AF_INET) {
8675 if ((!fnd) || (sin_a == NULL)) {
8677 SCTP_TCB_UNLOCK(stcb);
8681 vrf_id = inp->def_vrf_id;
8682 sctp_ifa = sctp_source_address_selection(inp,
8684 (sctp_route_t *)&net->ro,
8687 sin->sin_addr = sctp_ifa->address.sin.sin_addr;
8688 sctp_free_ifa(sctp_ifa);
8690 SCTP_TCB_UNLOCK(stcb);
8692 /* For the bound all case you get back 0 */
8694 sin->sin_addr.s_addr = 0;
8698 /* Take the first IPv4 address in the list */
8699 struct sctp_laddr *laddr;
8702 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
8703 if (laddr->ifa->address.sa.sa_family == AF_INET) {
8704 struct sockaddr_in *sin_a;
8706 sin_a = &laddr->ifa->address.sin;
8707 sin->sin_addr = sin_a->sin_addr;
8713 #if !defined(__Userspace__)
8714 SCTP_FREE_SONAME(sin);
8716 SCTP_INP_RUNLOCK(inp);
8717 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
8721 SCTP_INP_RUNLOCK(inp);
8722 #if !defined(__Userspace__)
8723 (*addr) = (struct sockaddr *)sin;
8729 #if !defined(__Userspace__)
8730 sctp_peeraddr(struct socket *so, struct sockaddr **addr)
8732 struct sockaddr_in *sin;
8734 sctp_peeraddr(struct socket *so, struct mbuf *nam)
8736 struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
8740 struct sockaddr_in *sin_a;
8741 struct sctp_inpcb *inp;
8742 struct sctp_tcb *stcb;
8743 struct sctp_nets *net;
8745 /* Do the malloc first in case it blocks. */
8746 #if !defined(__Userspace__)
8747 SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
8751 SCTP_BUF_LEN(nam) = sizeof(*sin);
8752 memset(sin, 0, sizeof(*sin));
8754 sin->sin_family = AF_INET;
8756 sin->sin_len = sizeof(*sin);
8759 inp = (struct sctp_inpcb *)so->so_pcb;
8760 if ((inp == NULL) ||
8761 ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
8762 /* UDP type and listeners will drop out here */
8763 #if !defined(__Userspace__)
8764 SCTP_FREE_SONAME(sin);
8766 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
8769 SCTP_INP_RLOCK(inp);
8770 stcb = LIST_FIRST(&inp->sctp_asoc_list);
8772 SCTP_TCB_LOCK(stcb);
8774 SCTP_INP_RUNLOCK(inp);
8776 #if !defined(__Userspace__)
8777 SCTP_FREE_SONAME(sin);
8779 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8780 return (ECONNRESET);
8783 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
8784 sin_a = (struct sockaddr_in *)&net->ro._l_addr;
8785 if (sin_a->sin_family == AF_INET) {
8787 sin->sin_port = stcb->rport;
8788 sin->sin_addr = sin_a->sin_addr;
8792 SCTP_TCB_UNLOCK(stcb);
8794 /* No IPv4 address */
8795 #if !defined(__Userspace__)
8796 SCTP_FREE_SONAME(sin);
8798 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
8801 #if !defined(__Userspace__)
8802 (*addr) = (struct sockaddr *)sin;
8807 #if !defined(__Userspace__)
8808 struct pr_usrreqs sctp_usrreqs = {
8809 #if defined(__FreeBSD__)
8810 .pru_abort = sctp_abort,
8811 .pru_accept = sctp_accept,
8812 .pru_attach = sctp_attach,
8813 .pru_bind = sctp_bind,
8814 .pru_connect = sctp_connect,
8815 .pru_control = in_control,
8816 .pru_close = sctp_close,
8817 .pru_detach = sctp_close,
8818 .pru_sopoll = sopoll_generic,
8819 .pru_flush = sctp_flush,
8820 .pru_disconnect = sctp_disconnect,
8821 .pru_listen = sctp_listen,
8822 .pru_peeraddr = sctp_peeraddr,
8823 .pru_send = sctp_sendm,
8824 .pru_shutdown = sctp_shutdown,
8825 .pru_sockaddr = sctp_ingetaddr,
8826 .pru_sosend = sctp_sosend,
8827 .pru_soreceive = sctp_soreceive
8828 #elif defined(__APPLE__)
8829 .pru_abort = sctp_abort,
8830 .pru_accept = sctp_accept,
8831 .pru_attach = sctp_attach,
8832 .pru_bind = sctp_bind,
8833 .pru_connect = sctp_connect,
8834 .pru_connect2 = pru_connect2_notsupp,
8835 .pru_control = in_control,
8836 .pru_detach = sctp_detach,
8837 .pru_disconnect = sctp_disconnect,
8838 .pru_listen = sctp_listen,
8839 .pru_peeraddr = sctp_peeraddr,
8841 .pru_rcvoob = pru_rcvoob_notsupp,
8842 .pru_send = sctp_sendm,
8843 .pru_sense = pru_sense_null,
8844 .pru_shutdown = sctp_shutdown,
8845 .pru_sockaddr = sctp_ingetaddr,
8846 .pru_sosend = sctp_sosend,
8847 .pru_soreceive = sctp_soreceive,
8848 .pru_sopoll = sopoll
8849 #elif defined(_WIN32) && !defined(__Userspace__)
8855 pru_connect2_notsupp,
8875 #elif !defined(__Userspace__)
8877 sctp_usrreq(so, req, m, nam, control)
8880 struct mbuf *m, *nam, *control;
8882 struct proc *p = curproc;
8885 struct sctp_inpcb *inp = (struct sctp_inpcb *)so->so_pcb;
8888 family = so->so_proto->pr_domain->dom_family;
8889 if (req == PRU_CONTROL) {
8892 error = in_control(so, (long)m, (caddr_t)nam,
8893 (struct ifnet *)control);
8897 error = in6_control(so, (long)m, (caddr_t)nam,
8898 (struct ifnet *)control, p);
8902 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
8903 error = EAFNOSUPPORT;
8909 error = sctp_attach(so, family, p);
8912 error = sctp_detach(so);
8916 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8919 error = sctp_bind(so, nam, p);
8922 error = sctp_listen(so, p);
8926 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8929 error = sctp_connect(so, nam, p);
8931 case PRU_DISCONNECT:
8932 error = sctp_disconnect(so);
8936 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8939 error = sctp_accept(so, nam);
8942 error = sctp_shutdown(so);
8947 * For Open and Net BSD, this is real ugly. The mbuf *nam
8948 * that is passed (by soreceive()) is the int flags c ast as
8954 /* Flags are ignored */
8956 struct sockaddr *addr;
8961 addr = mtod(nam, struct sockaddr *);
8963 error = sctp_sendm(so, 0, m, addr, control, p);
8967 error = sctp_abort(so);
8974 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
8975 error = EAFNOSUPPORT;
8978 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
8979 error = EAFNOSUPPORT;
8982 error = sctp_peeraddr(so, nam);
8985 error = sctp_ingetaddr(so, nam);
8999 #if defined(__Userspace__)
9001 register_recv_cb(struct socket *so,
9002 int (*receive_cb)(struct socket *sock, union sctp_sockstore addr, void *data,
9003 size_t datalen, struct sctp_rcvinfo, int flags, void *ulp_info))
9005 struct sctp_inpcb *inp;
9007 inp = (struct sctp_inpcb *) so->so_pcb;
9011 SCTP_INP_WLOCK(inp);
9012 inp->recv_callback = receive_cb;
9013 SCTP_INP_WUNLOCK(inp);
9018 register_send_cb(struct socket *so, uint32_t sb_threshold, int (*send_cb)(struct socket *sock, uint32_t sb_free))
9020 struct sctp_inpcb *inp;
9022 inp = (struct sctp_inpcb *) so->so_pcb;
9026 SCTP_INP_WLOCK(inp);
9027 inp->send_callback = send_cb;
9028 inp->send_sb_threshold = sb_threshold;
9029 SCTP_INP_WUNLOCK(inp);
9030 /* FIXME change to current amount free. This will be the full buffer
9031 * the first time this is registered but it could be only a portion
9032 * of the send buffer if this is called a second time e.g. if the
9033 * threshold changes.
9039 register_ulp_info (struct socket *so, void *ulp_info)
9041 struct sctp_inpcb *inp;
9043 inp = (struct sctp_inpcb *) so->so_pcb;
9047 SCTP_INP_WLOCK(inp);
9048 inp->ulp_info = ulp_info;
9049 SCTP_INP_WUNLOCK(inp);
9054 retrieve_ulp_info (struct socket *so, void **pulp_info)
9056 struct sctp_inpcb *inp;
9058 if (pulp_info == NULL) {
9062 inp = (struct sctp_inpcb *) so->so_pcb;
9066 SCTP_INP_RLOCK(inp);
9067 *pulp_info = inp->ulp_info;
9068 SCTP_INP_RUNLOCK(inp);