2 * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved.
3 * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
4 * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
9 * a) Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
12 * b) Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the distribution.
16 * c) Neither the name of Cisco Systems, Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30 * THE POSSIBILITY OF SUCH DAMAGE.
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD: head/sys/netinet/sctp_usrreq.c 257555 2013-11-02 20:12:19Z tuexen $");
38 #include <netinet/sctp_os.h>
42 #include <netinet/sctp_pcb.h>
43 #include <netinet/sctp_header.h>
44 #include <netinet/sctp_var.h>
46 #if defined(__Userspace_os_FreeBSD)
47 #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_os_Windows)
60 #include <netinet/udp.h>
63 #if defined(HAVE_SCTP_PEELOFF_SOCKOPT)
64 #include <netinet/sctp_peeloff.h>
65 #endif /* HAVE_SCTP_PEELOFF_SOCKOPT */
67 #if defined(__APPLE__)
68 #define APPLE_FILE_NO 7
71 extern struct sctp_cc_functions sctp_cc_functions[];
72 extern struct sctp_ss_functions sctp_ss_functions[];
75 #if defined(__Userspace__)
76 sctp_init(uint16_t port,
77 int (*conn_output)(void *addr, void *buffer, size_t length, uint8_t tos, uint8_t set_df),
78 void (*debug_printf)(const char *format, ...))
83 #if !defined(__Panda__) && !defined(__Userspace__)
87 #if defined(__Userspace_os_Windows)
88 #if defined(INET) || defined(INET6)
91 if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
92 SCTP_PRINTF("WSAStartup failed\n");
96 InitializeConditionVariable(&accept_cond);
97 InitializeCriticalSection(&accept_mtx);
99 /* Initialize and modify the sysctled variables */
101 #if defined(__Userspace__)
102 #if defined(__Userspace_os_Windows)
103 srand((unsigned int)time(NULL));
105 srandom(getpid()); /* so inp->sctp_ep.random_numbers are truly random... */
108 #if defined(__Panda__)
109 sctp_sendspace = SB_MAX;
110 sctp_recvspace = SB_MAX;
112 #elif defined(__Userspace__)
113 SCTP_BASE_SYSCTL(sctp_sendspace) = SB_MAX;
114 SCTP_BASE_SYSCTL(sctp_recvspace) = SB_RAW;
115 SCTP_BASE_SYSCTL(sctp_udp_tunneling_port) = port;
117 #if !defined(__APPLE__)
118 if ((nmbclusters / 8) > SCTP_ASOC_MAX_CHUNKS_ON_QUEUE)
119 SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue) = (nmbclusters / 8);
122 * Allow a user to take no more than 1/2 the number of clusters or
123 * the SB_MAX whichever is smaller for the send window.
125 #if defined(__APPLE__)
126 sb_max_adj = (u_long)((u_quad_t) (sb_max) * MCLBYTES / (MSIZE + MCLBYTES));
128 sb_max_adj = (u_long)((u_quad_t) (SB_MAX) * MCLBYTES / (MSIZE + MCLBYTES));
130 #if defined(__APPLE__)
131 SCTP_BASE_SYSCTL(sctp_sendspace) = sb_max_adj;
133 SCTP_BASE_SYSCTL(sctp_sendspace) = min(sb_max_adj,
134 (((uint32_t)nmbclusters / 2) * SCTP_DEFAULT_MAXSEGMENT));
137 * Now for the recv window, should we take the same amount? or
138 * should I do 1/2 the SB_MAX instead in the SB_MAX min above. For
139 * now I will just copy.
141 SCTP_BASE_SYSCTL(sctp_recvspace) = SCTP_BASE_SYSCTL(sctp_sendspace);
143 SCTP_BASE_VAR(first_time) = 0;
144 SCTP_BASE_VAR(sctp_pcb_initialized) = 0;
145 #if defined(__Userspace__)
146 #if !defined(__Userspace_os_Windows)
147 #if defined(INET) || defined(INET6)
148 SCTP_BASE_VAR(userspace_route) = -1;
152 SCTP_BASE_VAR(userspace_rawsctp) = -1;
153 SCTP_BASE_VAR(userspace_udpsctp) = -1;
156 SCTP_BASE_VAR(userspace_rawsctp6) = -1;
157 SCTP_BASE_VAR(userspace_udpsctp6) = -1;
159 SCTP_BASE_VAR(timer_thread_should_exit) = 0;
160 SCTP_BASE_VAR(conn_output) = conn_output;
161 SCTP_BASE_VAR(debug_printf) = debug_printf;
164 #if defined(__Userspace__)
167 #if defined(SCTP_PACKET_LOGGING)
168 SCTP_BASE_VAR(packet_log_writers) = 0;
169 SCTP_BASE_VAR(packet_log_end) = 0;
170 bzero(&SCTP_BASE_VAR(packet_log_buffer), SCTP_PACKET_LOG_SIZE);
172 #if defined(__APPLE__)
173 SCTP_BASE_VAR(sctp_main_timer_ticks) = 0;
174 sctp_start_main_timer();
175 sctp_address_monitor_start();
176 sctp_over_udp_start();
183 #if defined(__APPLE__)
184 sctp_over_udp_stop();
185 sctp_address_monitor_stop();
186 sctp_stop_main_timer();
188 #if defined(__Userspace__)
189 #if defined(INET) || defined(INET6)
190 recv_thread_destroy();
192 #if !defined(__Userspace_os_Windows)
193 #if defined(INET) || defined(INET6)
194 if (SCTP_BASE_VAR(userspace_route) != -1) {
195 pthread_join(SCTP_BASE_VAR(recvthreadroute), NULL);
200 if (SCTP_BASE_VAR(userspace_rawsctp) != -1) {
201 #if defined(__Userspace_os_Windows)
202 WaitForSingleObject(SCTP_BASE_VAR(recvthreadraw), INFINITE);
203 CloseHandle(SCTP_BASE_VAR(recvthreadraw));
205 pthread_join(SCTP_BASE_VAR(recvthreadraw), NULL);
208 if (SCTP_BASE_VAR(userspace_udpsctp) != -1) {
209 #if defined(__Userspace_os_Windows)
210 WaitForSingleObject(SCTP_BASE_VAR(recvthreadudp), INFINITE);
211 CloseHandle(SCTP_BASE_VAR(recvthreadudp));
213 pthread_join(SCTP_BASE_VAR(recvthreadudp), NULL);
218 if (SCTP_BASE_VAR(userspace_rawsctp6) != -1) {
219 #if defined(__Userspace_os_Windows)
220 WaitForSingleObject(SCTP_BASE_VAR(recvthreadraw6), INFINITE);
221 CloseHandle(SCTP_BASE_VAR(recvthreadraw6));
223 pthread_join(SCTP_BASE_VAR(recvthreadraw6), NULL);
226 if (SCTP_BASE_VAR(userspace_udpsctp6) != -1) {
227 #if defined(__Userspace_os_Windows)
228 WaitForSingleObject(SCTP_BASE_VAR(recvthreadudp6), INFINITE);
229 CloseHandle(SCTP_BASE_VAR(recvthreadudp6));
231 pthread_join(SCTP_BASE_VAR(recvthreadudp6), NULL);
235 SCTP_BASE_VAR(timer_thread_should_exit) = 1;
236 #if defined(__Userspace_os_Windows)
237 WaitForSingleObject(SCTP_BASE_VAR(timer_thread), INFINITE);
238 CloseHandle(SCTP_BASE_VAR(timer_thread));
240 pthread_join(SCTP_BASE_VAR(timer_thread), NULL);
244 #if defined(__Userspace__)
245 #if defined(__Userspace_os_Windows)
246 DeleteConditionVariable(&accept_cond);
247 DeleteCriticalSection(&accept_mtx);
249 pthread_cond_destroy(&accept_cond);
250 pthread_mutex_destroy(&accept_mtx);
253 #if defined(__Windows__)
254 sctp_finish_sysctls();
255 #if defined(INET) || defined(INET6)
264 sctp_pathmtu_adjustment(struct sctp_tcb *stcb, uint16_t nxtsz)
266 struct sctp_tmit_chunk *chk;
269 /* Adjust that too */
270 stcb->asoc.smallest_mtu = nxtsz;
271 /* now off to subtract IP_DF flag if needed */
272 overhead = IP_HDR_SIZE;
273 if (sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.peer_auth_chunks)) {
274 overhead += sctp_get_auth_chunk_len(stcb->asoc.peer_hmac_id);
276 TAILQ_FOREACH(chk, &stcb->asoc.send_queue, sctp_next) {
277 if ((chk->send_size + overhead) > nxtsz) {
278 chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
281 TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
282 if ((chk->send_size + overhead) > nxtsz) {
284 * For this guy we also mark for immediate resend
285 * since we sent to big of chunk
287 chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
288 if (chk->sent < SCTP_DATAGRAM_RESEND) {
289 sctp_flight_size_decrease(chk);
290 sctp_total_flight_decrease(stcb, chk);
292 if (chk->sent != SCTP_DATAGRAM_RESEND) {
293 sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
295 chk->sent = SCTP_DATAGRAM_RESEND;
296 chk->rec.data.doing_fast_retransmit = 0;
297 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) {
298 sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_PMTU,
299 chk->whoTo->flight_size,
301 (uintptr_t)chk->whoTo,
302 chk->rec.data.TSN_seq);
304 /* Clear any time so NO RTT is being done */
311 #if !defined(__Userspace__)
312 #if defined(__Panda__) || defined(__Windows__)
317 sctp_notify_mbuf(struct sctp_inpcb *inp,
318 struct sctp_tcb *stcb,
319 struct sctp_nets *net,
324 int totsz, tmr_stopped = 0;
328 if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
329 (ip == NULL) || (sh == NULL)) {
331 SCTP_TCB_UNLOCK(stcb);
335 /* First job is to verify the vtag matches what I would send */
336 if (ntohl(sh->v_tag) != (stcb->asoc.peer_vtag)) {
337 SCTP_TCB_UNLOCK(stcb);
340 icmph = (struct icmp *)((caddr_t)ip - (sizeof(struct icmp) -
342 if (icmph->icmp_type != ICMP_UNREACH) {
343 /* We only care about unreachable */
344 SCTP_TCB_UNLOCK(stcb);
347 if (icmph->icmp_code != ICMP_UNREACH_NEEDFRAG) {
348 /* not a unreachable message due to frag. */
349 SCTP_TCB_UNLOCK(stcb);
352 #if defined(__FreeBSD__) && __FreeBSD_version >= 1000000
353 totsz = ntohs(ip->ip_len);
358 nxtsz = ntohs(icmph->icmp_nextmtu);
361 * old type router that does not tell us what the next size
362 * mtu is. Rats we will have to guess (in a educated fashion
365 nxtsz = sctp_get_prev_mtu(totsz);
367 /* Stop any PMTU timer */
368 if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
370 sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
371 SCTP_FROM_SCTP_USRREQ+SCTP_LOC_1);
373 /* Adjust destination size limit */
374 if (net->mtu > nxtsz) {
377 net->mtu -= sizeof(struct udphdr);
380 /* now what about the ep? */
381 if (stcb->asoc.smallest_mtu > nxtsz) {
382 sctp_pathmtu_adjustment(stcb, nxtsz);
385 sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
387 SCTP_TCB_UNLOCK(stcb);
393 sctp_notify(struct sctp_inpcb *inp,
397 struct sctp_tcb *stcb,
398 struct sctp_nets *net)
400 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
407 if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
408 (sh == NULL) || (to == NULL)) {
410 SCTP_TCB_UNLOCK(stcb);
413 /* First job is to verify the vtag matches what I would send */
414 if (ntohl(sh->v_tag) != (stcb->asoc.peer_vtag)) {
415 SCTP_TCB_UNLOCK(stcb);
419 icmph = (struct icmp *)((caddr_t)ip - (sizeof(struct icmp) -
421 if (icmph->icmp_type != ICMP_UNREACH) {
422 /* We only care about unreachable */
423 SCTP_TCB_UNLOCK(stcb);
426 if ((icmph->icmp_code == ICMP_UNREACH_NET) ||
427 (icmph->icmp_code == ICMP_UNREACH_HOST) ||
428 (icmph->icmp_code == ICMP_UNREACH_NET_UNKNOWN) ||
429 (icmph->icmp_code == ICMP_UNREACH_HOST_UNKNOWN) ||
430 (icmph->icmp_code == ICMP_UNREACH_ISOLATED) ||
431 (icmph->icmp_code == ICMP_UNREACH_NET_PROHIB) ||
432 (icmph->icmp_code == ICMP_UNREACH_HOST_PROHIB) ||
434 (icmph->icmp_code == ICMP_UNREACH_ADMIN)) {
436 (icmph->icmp_code == ICMP_UNREACH_FILTER_PROHIB)) {
440 * Hmm reachablity problems we must examine closely. If its
441 * not reachable, we may have lost a network. Or if there is
442 * NO protocol at the other end named SCTP. well we consider
445 if (net->dest_state & SCTP_ADDR_REACHABLE) {
446 /* Ok that destination is NOT reachable */
447 net->dest_state &= ~SCTP_ADDR_REACHABLE;
448 net->dest_state &= ~SCTP_ADDR_PF;
449 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
451 (void *)net, SCTP_SO_NOT_LOCKED);
453 SCTP_TCB_UNLOCK(stcb);
454 } else if ((icmph->icmp_code == ICMP_UNREACH_PROTOCOL) ||
455 (icmph->icmp_code == ICMP_UNREACH_PORT)) {
457 * Here the peer is either playing tricks on us,
458 * including an address that belongs to someone who
459 * does not support SCTP OR was a userland
460 * implementation that shutdown and now is dead. In
461 * either case treat it like a OOTB abort with no
464 sctp_abort_notification(stcb, 1, 0, NULL, SCTP_SO_NOT_LOCKED);
465 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
466 so = SCTP_INP_SO(inp);
467 atomic_add_int(&stcb->asoc.refcnt, 1);
468 SCTP_TCB_UNLOCK(stcb);
469 SCTP_SOCKET_LOCK(so, 1);
471 atomic_subtract_int(&stcb->asoc.refcnt, 1);
473 (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_2);
474 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
475 SCTP_SOCKET_UNLOCK(so, 1);
476 /* SCTP_TCB_UNLOCK(stcb); MT: I think this is not needed.*/
478 /* no need to unlock here, since the TCB is gone */
480 SCTP_TCB_UNLOCK(stcb);
485 #if !defined(__Panda__) && !defined(__Userspace__)
486 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
491 sctp_ctlinput(cmd, sa, vip)
499 /* FIX, for non-bsd is this right? */
500 vrf_id = SCTP_DEFAULT_VRFID;
501 if (sa->sa_family != AF_INET ||
502 ((struct sockaddr_in *)sa)->sin_addr.s_addr == INADDR_ANY) {
503 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
509 if (PRC_IS_REDIRECT(cmd)) {
511 } else if ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0) {
512 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
519 struct sctp_inpcb *inp = NULL;
520 struct sctp_tcb *stcb = NULL;
521 struct sctp_nets *net = NULL;
522 struct sockaddr_in to, from;
524 sh = (struct sctphdr *)((caddr_t)ip + (ip->ip_hl << 2));
525 bzero(&to, sizeof(to));
526 bzero(&from, sizeof(from));
527 from.sin_family = to.sin_family = AF_INET;
529 from.sin_len = to.sin_len = sizeof(to);
531 from.sin_port = sh->src_port;
532 from.sin_addr = ip->ip_src;
533 to.sin_port = sh->dest_port;
534 to.sin_addr = ip->ip_dst;
537 * 'to' holds the dest of the packet that failed to be sent.
538 * 'from' holds our local endpoint address. Thus we reverse
539 * the to and the from in the lookup.
541 stcb = sctp_findassociation_addr_sa((struct sockaddr *)&to,
542 (struct sockaddr *)&from,
543 &inp, &net, 1, vrf_id);
544 if (stcb != NULL && inp && (inp->sctp_socket != NULL)) {
545 if (cmd != PRC_MSGSIZE) {
546 sctp_notify(inp, ip, sh,
547 (struct sockaddr *)&to, stcb,
550 /* handle possible ICMP size messages */
551 sctp_notify_mbuf(inp, stcb, net, ip, sh);
554 #if defined(__FreeBSD__) && __FreeBSD_version < 500000
556 * XXX must be fixed for 5.x and higher, leave for
559 if (PRC_IS_REDIRECT(cmd) && inp) {
560 in_rtchange((struct inpcb *)inp,
564 if ((stcb == NULL) && (inp != NULL)) {
565 /* reduce ref-count */
567 SCTP_INP_DECR_REF(inp);
568 SCTP_INP_WUNLOCK(inp);
571 SCTP_TCB_UNLOCK(stcb);
575 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
584 #if defined(__FreeBSD__)
586 sctp_getcred(SYSCTL_HANDLER_ARGS)
589 struct sockaddr_in addrs[2];
590 struct sctp_inpcb *inp;
591 struct sctp_nets *net;
592 struct sctp_tcb *stcb;
596 /* FIX, for non-bsd is this right? */
597 vrf_id = SCTP_DEFAULT_VRFID;
599 #if __FreeBSD_version > 602000
600 error = priv_check(req->td, PRIV_NETINET_GETCRED);
602 #elif __FreeBSD_version >= 500000
603 error = suser(req->td);
605 error = suser(req->p);
610 error = SYSCTL_IN(req, addrs, sizeof(addrs));
614 stcb = sctp_findassociation_addr_sa(sintosa(&addrs[1]),
616 &inp, &net, 1, vrf_id);
617 if (stcb == NULL || inp == NULL || inp->sctp_socket == NULL) {
618 if ((inp != NULL) && (stcb == NULL)) {
619 /* reduce ref-count */
621 SCTP_INP_DECR_REF(inp);
625 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
629 SCTP_TCB_UNLOCK(stcb);
630 /* We use the write lock here, only
631 * since in the error leg we need it.
632 * If we used RLOCK, then we would have
633 * to wlock/decr/unlock/rlock. Which
634 * in theory could create a hole. Better
635 * to use higher wlock.
639 error = cr_canseesocket(req->td->td_ucred, inp->sctp_socket);
641 SCTP_INP_WUNLOCK(inp);
644 cru2x(inp->sctp_socket->so_cred, &xuc);
645 SCTP_INP_WUNLOCK(inp);
646 error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
651 SYSCTL_PROC(_net_inet_sctp, OID_AUTO, getcred, CTLTYPE_OPAQUE | CTLFLAG_RW,
652 0, 0, sctp_getcred, "S,ucred", "Get the ucred of a SCTP connection");
653 #endif /* #if defined(__FreeBSD__) */
657 #if defined(__Panda__) || defined(__Windows__) || defined(__Userspace__)
659 #elif defined(__FreeBSD__) && __FreeBSD_version > 690000
664 sctp_abort(struct socket *so)
666 struct sctp_inpcb *inp;
669 inp = (struct sctp_inpcb *)so->so_pcb;
671 #if defined(__FreeBSD__) && __FreeBSD_version > 690000
674 SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
680 flags = inp->sctp_flags;
681 #ifdef SCTP_LOG_CLOSING
682 sctp_log_closing(inp, NULL, 17);
684 if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
685 (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
686 #ifdef SCTP_LOG_CLOSING
687 sctp_log_closing(inp, NULL, 16);
689 sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
690 SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
692 SCTP_SB_CLEAR(so->so_snd);
693 /* same for the rcv ones, they are only
694 * here for the accounting/select.
696 SCTP_SB_CLEAR(so->so_rcv);
698 #if defined(__APPLE__)
701 /* Now null out the reference, we are completely detached. */
706 flags = inp->sctp_flags;
707 if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
708 goto sctp_must_try_again;
711 #if defined(__FreeBSD__) && __FreeBSD_version > 690000
718 #if defined(__Panda__) || defined(__Userspace__)
723 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
724 sctp_attach(struct socket *so, int proto SCTP_UNUSED, struct thread *p SCTP_UNUSED)
725 #elif defined(__Panda__) || defined(__Userspace__)
726 sctp_attach(struct socket *so, int proto SCTP_UNUSED, uint32_t vrf_id)
727 #elif defined(__Windows__)
728 sctp_attach(struct socket *so, int proto SCTP_UNUSED, PKTHREAD p SCTP_UNUSED)
730 sctp_attach(struct socket *so, int proto SCTP_UNUSED, struct proc *p SCTP_UNUSED)
733 struct sctp_inpcb *inp;
734 struct inpcb *ip_inp;
736 #if !defined(__Panda__) && !defined(__Userspace__)
737 uint32_t vrf_id = SCTP_DEFAULT_VRFID;
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; /* I'm not v6! */
761 ip_inp = &inp->ip_inp.inp;
762 ip_inp->inp_vflag |= INP_IPV4;
763 ip_inp->inp_ip_ttl = MODULE_GLOBAL(ip_defttl);
765 #if !(defined(__APPLE__))
766 error = ipsec_init_policy(so, &ip_inp->inp_sp);
767 #ifdef SCTP_LOG_CLOSING
768 sctp_log_closing(inp, NULL, 17);
772 flags = inp->sctp_flags;
773 if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
774 (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
775 #ifdef SCTP_LOG_CLOSING
776 sctp_log_closing(inp, NULL, 15);
778 SCTP_INP_WUNLOCK(inp);
779 sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
780 SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
782 flags = inp->sctp_flags;
783 if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
786 SCTP_INP_WUNLOCK(inp);
793 SCTP_INP_WUNLOCK(inp);
797 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
799 sctp_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
801 #elif defined(__FreeBSD__) || defined(__APPLE__)
803 sctp_bind(struct socket *so, struct sockaddr *addr, struct proc *p) {
804 #elif defined(__Panda__) || defined(__Userspace__)
806 sctp_bind(struct socket *so, struct sockaddr *addr) {
808 #elif defined(__Windows__)
810 sctp_bind(struct socket *so, struct sockaddr *addr, PKTHREAD p) {
813 sctp_bind(struct socket *so, struct mbuf *nam, struct proc *p)
815 struct sockaddr *addr = nam ? mtod(nam, struct sockaddr *): NULL;
818 struct sctp_inpcb *inp;
820 inp = (struct sctp_inpcb *)so->so_pcb;
822 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
827 if ((addr->sa_family != AF_INET) ||
828 (addr->sa_len != sizeof(struct sockaddr_in))) {
830 if (addr->sa_family != AF_INET) {
832 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
836 return (sctp_inpcb_bind(so, addr, NULL, p));
840 #if defined(__Userspace__)
843 sctpconn_attach(struct socket *so, int proto SCTP_UNUSED, uint32_t vrf_id)
845 struct sctp_inpcb *inp;
846 struct inpcb *ip_inp;
849 inp = (struct sctp_inpcb *)so->so_pcb;
851 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
854 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
855 error = SCTP_SORESERVE(so, SCTP_BASE_SYSCTL(sctp_sendspace), SCTP_BASE_SYSCTL(sctp_recvspace));
860 error = sctp_inpcb_alloc(so, vrf_id);
864 inp = (struct sctp_inpcb *)so->so_pcb;
866 inp->sctp_flags &= ~SCTP_PCB_FLAGS_BOUND_V6;
867 inp->sctp_flags |= SCTP_PCB_FLAGS_BOUND_CONN;
868 ip_inp = &inp->ip_inp.inp;
869 ip_inp->inp_vflag |= INP_CONN;
870 ip_inp->inp_ip_ttl = MODULE_GLOBAL(ip_defttl);
871 SCTP_INP_WUNLOCK(inp);
876 sctpconn_bind(struct socket *so, struct sockaddr *addr)
878 struct sctp_inpcb *inp;
880 inp = (struct sctp_inpcb *)so->so_pcb;
882 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
887 if ((addr->sa_family != AF_CONN) ||
888 (addr->sa_len != sizeof(struct sockaddr_conn))) {
890 if (addr->sa_family != AF_CONN) {
892 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
896 return (sctp_inpcb_bind(so, addr, NULL, NULL));
900 #if (defined(__FreeBSD__) && __FreeBSD_version > 690000) || defined(__Windows__) || defined(__Userspace__)
902 sctp_close(struct socket *so)
904 struct sctp_inpcb *inp;
907 inp = (struct sctp_inpcb *)so->so_pcb;
911 /* Inform all the lower layer assoc that we
915 flags = inp->sctp_flags;
916 #ifdef SCTP_LOG_CLOSING
917 sctp_log_closing(inp, NULL, 17);
919 if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
920 (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
921 #if defined(__Userspace__)
922 if (((so->so_options & SCTP_SO_LINGER) && (so->so_linger == 0)) ||
923 (so->so_rcv.sb_cc > 0)) {
925 if (((so->so_options & SO_LINGER) && (so->so_linger == 0)) ||
926 (so->so_rcv.sb_cc > 0)) {
928 #ifdef SCTP_LOG_CLOSING
929 sctp_log_closing(inp, NULL, 13);
931 sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
932 SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
934 #ifdef SCTP_LOG_CLOSING
935 sctp_log_closing(inp, NULL, 14);
937 sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_GRACEFUL_CLOSE,
938 SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
940 /* The socket is now detached, no matter what
941 * the state of the SCTP association.
944 SCTP_SB_CLEAR(so->so_snd);
945 /* same for the rcv ones, they are only
946 * here for the accounting/select.
948 SCTP_SB_CLEAR(so->so_rcv);
950 #if !defined(__APPLE__)
951 /* Now null out the reference, we are completely detached. */
956 flags = inp->sctp_flags;
957 if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
958 goto sctp_must_try_again;
968 sctp_detach(struct socket *so)
970 struct sctp_inpcb *inp;
973 inp = (struct sctp_inpcb *)so->so_pcb;
975 #if defined(__FreeBSD__) && __FreeBSD_version > 690000
978 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
983 flags = inp->sctp_flags;
984 #ifdef SCTP_LOG_CLOSING
985 sctp_log_closing(inp, NULL, 17);
987 if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
988 (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
989 #if defined(__Userspace__)
990 if (((so->so_options & SCTP_SO_LINGER) && (so->so_linger == 0)) ||
991 (so->so_rcv.sb_cc > 0)) {
993 if (((so->so_options & SO_LINGER) && (so->so_linger == 0)) ||
994 (so->so_rcv.sb_cc > 0)) {
996 #ifdef SCTP_LOG_CLOSING
997 sctp_log_closing(inp, NULL, 13);
999 sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
1000 SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
1002 #ifdef SCTP_LOG_CLOSING
1003 sctp_log_closing(inp, NULL, 13);
1005 sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_GRACEFUL_CLOSE,
1006 SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
1008 /* The socket is now detached, no matter what
1009 * the state of the SCTP association.
1011 SCTP_SB_CLEAR(so->so_snd);
1012 /* same for the rcv ones, they are only
1013 * here for the accounting/select.
1015 SCTP_SB_CLEAR(so->so_rcv);
1016 #if !defined(__APPLE__)
1017 /* Now disconnect */
1021 flags = inp->sctp_flags;
1022 if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
1023 goto sctp_must_try_again;
1026 #if defined(__FreeBSD__) && __FreeBSD_version > 690000
1034 #if defined(__Userspace__)
1035 /* __Userspace__ is not calling sctp_sendm */
1037 #if !(defined(__Panda__) || defined(__Windows__))
1039 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
1040 sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
1041 struct mbuf *control, struct thread *p);
1044 sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
1045 struct mbuf *control, struct proc *p);
1050 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
1051 sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
1052 struct mbuf *control, struct thread *p)
1055 sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
1056 struct mbuf *control, struct proc *p)
1059 struct sctp_inpcb *inp;
1062 inp = (struct sctp_inpcb *)so->so_pcb;
1065 sctp_m_freem(control);
1068 SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1072 /* Got to have an to address if we are NOT a connected socket */
1073 if ((addr == NULL) &&
1074 ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) ||
1075 (inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE))) {
1076 goto connected_type;
1077 } else if (addr == NULL) {
1078 SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EDESTADDRREQ);
1079 error = EDESTADDRREQ;
1082 sctp_m_freem(control);
1088 if (addr->sa_family != AF_INET) {
1089 /* must be a v4 address! */
1090 SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EDESTADDRREQ);
1093 sctp_m_freem(control);
1096 error = EDESTADDRREQ;
1101 /* now what about control */
1104 SCTP_PRINTF("huh? control set?\n");
1105 sctp_m_freem(inp->control);
1106 inp->control = NULL;
1108 inp->control = control;
1110 /* Place the data */
1112 SCTP_BUF_NEXT(inp->pkt_last) = m;
1115 inp->pkt_last = inp->pkt = m;
1118 #if defined(__FreeBSD__) || defined(__APPLE__)
1119 /* FreeBSD uses a flag passed */
1120 ((flags & PRUS_MORETOCOME) == 0)
1122 1 /* Open BSD does not have any "more to come"
1127 * note with the current version this code will only be used
1128 * by OpenBSD-- NetBSD, FreeBSD, and MacOS have methods for
1129 * re-defining sosend to use the sctp_sosend. One can
1130 * optionally switch back to this code (by changing back the
1131 * definitions) but this is not advisable. This code is used
1132 * by FreeBSD when sending a file with sendfile() though.
1136 ret = sctp_output(inp, inp->pkt, addr, inp->control, p, flags);
1138 inp->control = NULL;
1147 sctp_disconnect(struct socket *so)
1149 struct sctp_inpcb *inp;
1151 inp = (struct sctp_inpcb *)so->so_pcb;
1153 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
1156 SCTP_INP_RLOCK(inp);
1157 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1158 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
1159 if (LIST_EMPTY(&inp->sctp_asoc_list)) {
1161 SCTP_INP_RUNLOCK(inp);
1164 struct sctp_association *asoc;
1165 struct sctp_tcb *stcb;
1167 stcb = LIST_FIRST(&inp->sctp_asoc_list);
1169 SCTP_INP_RUNLOCK(inp);
1170 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1173 SCTP_TCB_LOCK(stcb);
1175 if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
1176 /* We are about to be freed, out of here */
1177 SCTP_TCB_UNLOCK(stcb);
1178 SCTP_INP_RUNLOCK(inp);
1181 #if defined(__Userspace__)
1182 if (((so->so_options & SCTP_SO_LINGER) &&
1183 (so->so_linger == 0)) ||
1184 (so->so_rcv.sb_cc > 0)) {
1186 if (((so->so_options & SO_LINGER) &&
1187 (so->so_linger == 0)) ||
1188 (so->so_rcv.sb_cc > 0)) {
1190 if (SCTP_GET_STATE(asoc) !=
1191 SCTP_STATE_COOKIE_WAIT) {
1192 /* Left with Data unread */
1195 err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), 0, M_NOWAIT, 1, MT_DATA);
1201 struct sctp_paramhdr *ph;
1203 ph = mtod(err, struct sctp_paramhdr *);
1204 SCTP_BUF_LEN(err) = sizeof(struct sctp_paramhdr);
1205 ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
1206 ph->param_length = htons(SCTP_BUF_LEN(err));
1208 sctp_send_abort_tcb(stcb, err, SCTP_SO_LOCKED);
1209 SCTP_STAT_INCR_COUNTER32(sctps_aborted);
1211 SCTP_INP_RUNLOCK(inp);
1212 if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
1213 (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
1214 SCTP_STAT_DECR_GAUGE32(sctps_currestab);
1216 (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_3);
1217 /* No unlock tcb assoc is gone */
1220 if (TAILQ_EMPTY(&asoc->send_queue) &&
1221 TAILQ_EMPTY(&asoc->sent_queue) &&
1222 (asoc->stream_queue_cnt == 0)) {
1223 /* there is nothing queued to send, so done */
1224 if (asoc->locked_on_sending) {
1227 if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) &&
1228 (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
1229 /* only send SHUTDOWN 1st time thru */
1230 struct sctp_nets *netp;
1232 if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
1233 (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
1234 SCTP_STAT_DECR_GAUGE32(sctps_currestab);
1236 SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
1237 SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
1238 sctp_stop_timers_for_shutdown(stcb);
1239 if (stcb->asoc.alternate) {
1240 netp = stcb->asoc.alternate;
1242 netp = stcb->asoc.primary_destination;
1244 sctp_send_shutdown(stcb,netp);
1245 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
1246 stcb->sctp_ep, stcb, netp);
1247 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
1248 stcb->sctp_ep, stcb, netp);
1249 sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_LOCKED);
1253 * we still got (or just got) data to send,
1254 * so set SHUTDOWN_PENDING
1257 * XXX sockets draft says that SCTP_EOF
1258 * should be sent with no data. currently,
1259 * we will allow user data to be sent first
1260 * and move to SHUTDOWN-PENDING
1262 struct sctp_nets *netp;
1263 if (stcb->asoc.alternate) {
1264 netp = stcb->asoc.alternate;
1266 netp = stcb->asoc.primary_destination;
1269 asoc->state |= SCTP_STATE_SHUTDOWN_PENDING;
1270 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb,
1272 if (asoc->locked_on_sending) {
1273 /* Locked to send out the data */
1274 struct sctp_stream_queue_pending *sp;
1275 sp = TAILQ_LAST(&asoc->locked_on_sending->outqueue, sctp_streamhead);
1277 SCTP_PRINTF("Error, sp is NULL, locked on sending is non-null strm:%d\n",
1278 asoc->locked_on_sending->stream_no);
1280 if ((sp->length == 0) && (sp->msg_is_complete == 0))
1281 asoc->state |= SCTP_STATE_PARTIAL_MSG_LEFT;
1284 if (TAILQ_EMPTY(&asoc->send_queue) &&
1285 TAILQ_EMPTY(&asoc->sent_queue) &&
1286 (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
1287 struct mbuf *op_err;
1289 op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr),
1290 0, M_NOWAIT, 1, MT_DATA);
1292 /* Fill in the user initiated abort */
1293 struct sctp_paramhdr *ph;
1295 SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr);
1296 ph = mtod(op_err, struct sctp_paramhdr *);
1297 ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
1298 ph->param_length = htons(SCTP_BUF_LEN(op_err));
1300 stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ+SCTP_LOC_4;
1301 sctp_send_abort_tcb(stcb, op_err, SCTP_SO_LOCKED);
1302 SCTP_STAT_INCR_COUNTER32(sctps_aborted);
1303 if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
1304 (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
1305 SCTP_STAT_DECR_GAUGE32(sctps_currestab);
1307 SCTP_INP_RUNLOCK(inp);
1308 (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_5);
1311 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
1314 soisdisconnecting(so);
1315 SCTP_TCB_UNLOCK(stcb);
1316 SCTP_INP_RUNLOCK(inp);
1321 /* UDP model does not support this */
1322 SCTP_INP_RUNLOCK(inp);
1323 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
1324 return (EOPNOTSUPP);
1328 #if defined(__FreeBSD__) || defined(__Windows__) || defined(__Userspace__)
1330 sctp_flush(struct socket *so, int how)
1333 * We will just clear out the values and let
1334 * subsequent close clear out the data, if any.
1335 * Note if the user did a shutdown(SHUT_RD) they
1336 * will not be able to read the data, the socket
1337 * will block that from happening.
1339 struct sctp_inpcb *inp;
1341 inp = (struct sctp_inpcb *)so->so_pcb;
1343 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1346 SCTP_INP_RLOCK(inp);
1347 /* For the 1 to many model this does nothing */
1348 if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
1349 SCTP_INP_RUNLOCK(inp);
1352 SCTP_INP_RUNLOCK(inp);
1353 if ((how == PRU_FLUSH_RD) || (how == PRU_FLUSH_RDWR)) {
1354 /* First make sure the sb will be happy, we don't
1355 * use these except maybe the count
1357 SCTP_INP_WLOCK(inp);
1358 SCTP_INP_READ_LOCK(inp);
1359 inp->sctp_flags |= SCTP_PCB_FLAGS_SOCKET_CANT_READ;
1360 SCTP_INP_READ_UNLOCK(inp);
1361 SCTP_INP_WUNLOCK(inp);
1362 so->so_rcv.sb_cc = 0;
1363 so->so_rcv.sb_mbcnt = 0;
1364 so->so_rcv.sb_mb = NULL;
1366 if ((how == PRU_FLUSH_WR) || (how == PRU_FLUSH_RDWR)) {
1367 /* First make sure the sb will be happy, we don't
1368 * use these except maybe the count
1370 so->so_snd.sb_cc = 0;
1371 so->so_snd.sb_mbcnt = 0;
1372 so->so_snd.sb_mb = NULL;
1380 sctp_shutdown(struct socket *so)
1382 struct sctp_inpcb *inp;
1384 inp = (struct sctp_inpcb *)so->so_pcb;
1386 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1389 SCTP_INP_RLOCK(inp);
1390 /* For UDP model this is a invalid call */
1391 if (!((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1392 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) {
1393 /* Restore the flags that the soshutdown took away. */
1394 #if (defined(__FreeBSD__) && __FreeBSD_version >= 502115) || defined(__Windows__)
1395 SOCKBUF_LOCK(&so->so_rcv);
1396 so->so_rcv.sb_state &= ~SBS_CANTRCVMORE;
1397 SOCKBUF_UNLOCK(&so->so_rcv);
1399 so->so_state &= ~SS_CANTRCVMORE;
1401 /* This proc will wakeup for read and do nothing (I hope) */
1402 SCTP_INP_RUNLOCK(inp);
1403 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
1404 return (EOPNOTSUPP);
1407 * Ok if we reach here its the TCP model and it is either a SHUT_WR
1408 * or SHUT_RDWR. This means we put the shutdown flag against it.
1411 struct sctp_tcb *stcb;
1412 struct sctp_association *asoc;
1415 (SS_ISCONNECTED|SS_ISCONNECTING|SS_ISDISCONNECTING)) == 0) {
1416 SCTP_INP_RUNLOCK(inp);
1421 stcb = LIST_FIRST(&inp->sctp_asoc_list);
1424 * Ok we hit the case that the shutdown call was
1425 * made after an abort or something. Nothing to do
1428 SCTP_INP_RUNLOCK(inp);
1431 SCTP_TCB_LOCK(stcb);
1433 if (TAILQ_EMPTY(&asoc->send_queue) &&
1434 TAILQ_EMPTY(&asoc->sent_queue) &&
1435 (asoc->stream_queue_cnt == 0)) {
1436 if (asoc->locked_on_sending) {
1439 /* there is nothing queued to send, so I'm done... */
1440 if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) {
1441 /* only send SHUTDOWN the first time through */
1442 struct sctp_nets *netp;
1444 if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
1445 (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
1446 SCTP_STAT_DECR_GAUGE32(sctps_currestab);
1448 SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
1449 SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
1450 sctp_stop_timers_for_shutdown(stcb);
1451 if (stcb->asoc.alternate) {
1452 netp = stcb->asoc.alternate;
1454 netp = stcb->asoc.primary_destination;
1456 sctp_send_shutdown(stcb, netp);
1457 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
1458 stcb->sctp_ep, stcb, netp);
1459 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
1460 stcb->sctp_ep, stcb, netp);
1461 sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_LOCKED);
1465 * we still got (or just got) data to send, so set
1468 struct sctp_nets *netp;
1469 if (stcb->asoc.alternate) {
1470 netp = stcb->asoc.alternate;
1472 netp = stcb->asoc.primary_destination;
1475 asoc->state |= SCTP_STATE_SHUTDOWN_PENDING;
1476 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb,
1479 if (asoc->locked_on_sending) {
1480 /* Locked to send out the data */
1481 struct sctp_stream_queue_pending *sp;
1482 sp = TAILQ_LAST(&asoc->locked_on_sending->outqueue, sctp_streamhead);
1484 SCTP_PRINTF("Error, sp is NULL, locked on sending is non-null strm:%d\n",
1485 asoc->locked_on_sending->stream_no);
1487 if ((sp->length == 0) && (sp-> msg_is_complete == 0)) {
1488 asoc->state |= SCTP_STATE_PARTIAL_MSG_LEFT;
1492 if (TAILQ_EMPTY(&asoc->send_queue) &&
1493 TAILQ_EMPTY(&asoc->sent_queue) &&
1494 (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
1495 struct mbuf *op_err;
1497 op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr),
1498 0, M_NOWAIT, 1, MT_DATA);
1500 /* Fill in the user initiated abort */
1501 struct sctp_paramhdr *ph;
1503 SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr);
1504 ph = mtod(op_err, struct sctp_paramhdr *);
1505 ph->param_type = htons( SCTP_CAUSE_USER_INITIATED_ABT);
1506 ph->param_length = htons(SCTP_BUF_LEN(op_err));
1508 stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ+SCTP_LOC_6;
1509 sctp_abort_an_association(stcb->sctp_ep, stcb,
1510 op_err, SCTP_SO_LOCKED);
1513 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
1516 SCTP_TCB_UNLOCK(stcb);
1519 SCTP_INP_RUNLOCK(inp);
1524 * copies a "user" presentable address and removes embedded scope, etc.
1525 * returns 0 on success, 1 on error
1528 sctp_fill_user_address(struct sockaddr_storage *ss, struct sockaddr *sa)
1531 #if defined(SCTP_EMBEDDED_V6_SCOPE)
1532 struct sockaddr_in6 lsa6;
1534 sa = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)sa,
1539 memcpy(ss, sa, sa->sa_len);
1541 switch (sa->sa_family) {
1544 memcpy(ss, sa, sizeof(struct sockaddr_in));
1549 memcpy(ss, sa, sizeof(struct sockaddr_in6));
1552 #if defined(__Userspace__)
1554 memcpy(ss, sa, sizeof(struct sockaddr_conn));
1568 * NOTE: assumes addr lock is held
1571 sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp,
1572 struct sctp_tcb *stcb,
1574 struct sockaddr_storage *sas,
1577 struct sctp_ifn *sctp_ifn;
1578 struct sctp_ifa *sctp_ifa;
1582 int ipv4_local_scope, ipv4_addr_legal;
1585 int local_scope, site_scope, ipv6_addr_legal;
1587 #if defined(__Userspace__)
1588 int conn_addr_legal;
1590 struct sctp_vrf *vrf;
1597 /* Turn on all the appropriate scope */
1598 loopback_scope = stcb->asoc.scope.loopback_scope;
1600 ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope;
1601 ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal;
1604 local_scope = stcb->asoc.scope.local_scope;
1605 site_scope = stcb->asoc.scope.site_scope;
1606 ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal;
1608 #if defined(__Userspace__)
1609 conn_addr_legal = stcb->asoc.scope.conn_addr_legal;
1612 /* Use generic values for endpoints. */
1615 ipv4_local_scope = 1;
1621 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
1623 ipv6_addr_legal = 1;
1626 if (SCTP_IPV6_V6ONLY(inp)) {
1627 ipv4_addr_legal = 0;
1629 ipv4_addr_legal = 1;
1632 #if defined(__Userspace__)
1633 conn_addr_legal = 0;
1637 ipv6_addr_legal = 0;
1639 #if defined(__Userspace__)
1640 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_CONN) {
1641 conn_addr_legal = 1;
1643 ipv4_addr_legal = 0;
1646 conn_addr_legal = 0;
1648 ipv4_addr_legal = 1;
1653 ipv4_addr_legal = 1;
1658 vrf = sctp_find_vrf(vrf_id);
1662 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
1663 LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
1664 if ((loopback_scope == 0) &&
1665 SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
1666 /* Skip loopback if loopback_scope not set */
1669 LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
1672 * For the BOUND-ALL case, the list
1673 * associated with a TCB is Always
1674 * considered a reverse list.. i.e.
1675 * it lists addresses that are NOT
1676 * part of the association. If this
1677 * is one of those we must skip it.
1679 if (sctp_is_addr_restricted(stcb,
1684 switch (sctp_ifa->address.sa.sa_family) {
1687 if (ipv4_addr_legal) {
1688 struct sockaddr_in *sin;
1690 sin = (struct sockaddr_in *)&sctp_ifa->address.sa;
1691 if (sin->sin_addr.s_addr == 0) {
1693 * we skip unspecifed
1698 if ((ipv4_local_scope == 0) &&
1699 (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) {
1703 if (sctp_is_feature_on(inp,SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
1704 in6_sin_2_v4mapsin6(sin, (struct sockaddr_in6 *)sas);
1705 ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
1706 sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(struct sockaddr_in6));
1707 actual += sizeof(struct sockaddr_in6);
1710 memcpy(sas, sin, sizeof(*sin));
1711 ((struct sockaddr_in *)sas)->sin_port = inp->sctp_lport;
1712 sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(*sin));
1713 actual += sizeof(*sin);
1717 if (actual >= limit) {
1727 if (ipv6_addr_legal) {
1728 struct sockaddr_in6 *sin6;
1730 #if defined(SCTP_EMBEDDED_V6_SCOPE) && !defined(SCTP_KAME)
1731 struct sockaddr_in6 lsa6;
1733 sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa;
1734 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
1736 * we skip unspecifed
1741 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
1742 if (local_scope == 0)
1744 #if defined(SCTP_EMBEDDED_V6_SCOPE)
1745 if (sin6->sin6_scope_id == 0) {
1747 if (sa6_recoverscope(sin6) != 0)
1756 if (in6_recoverscope(&lsa6,
1766 #endif /* SCTP_KAME */
1768 #endif /* SCTP_EMBEDDED_V6_SCOPE */
1770 if ((site_scope == 0) &&
1771 (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) {
1774 memcpy(sas, sin6, sizeof(*sin6));
1775 ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
1776 sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(*sin6));
1777 actual += sizeof(*sin6);
1778 if (actual >= limit) {
1786 #if defined(__Userspace__)
1788 if (conn_addr_legal) {
1789 memcpy(sas, &sctp_ifa->address.sconn, sizeof(struct sockaddr_conn));
1790 ((struct sockaddr_conn *)sas)->sconn_port = inp->sctp_lport;
1791 sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(struct sockaddr_conn));
1792 actual += sizeof(struct sockaddr_conn);
1793 if (actual >= limit) {
1807 struct sctp_laddr *laddr;
1809 uint32_t sa_len = 0;
1812 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
1814 if (sctp_is_addr_restricted(stcb, laddr->ifa)) {
1818 if (sctp_fill_user_address(sas, &laddr->ifa->address.sa))
1820 switch (laddr->ifa->address.sa.sa_family) {
1823 ((struct sockaddr_in *)sas)->sin_port = inp->sctp_lport;
1828 ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
1831 #if defined(__Userspace__)
1833 ((struct sockaddr_conn *)sas)->sconn_port = inp->sctp_lport;
1841 sas = (struct sockaddr_storage *)((caddr_t)sas +
1842 laddr->ifa->address.sa.sa_len);
1843 actual += laddr->ifa->address.sa.sa_len;
1845 switch (laddr->ifa->address.sa.sa_family) {
1848 sa_len = sizeof(struct sockaddr_in);
1853 sa_len = sizeof(struct sockaddr_in6);
1856 #if defined(__Userspace__)
1858 sa_len = sizeof(struct sockaddr_conn);
1865 sas = (struct sockaddr_storage *)((caddr_t)sas + sa_len);
1868 if (actual >= limit) {
1877 sctp_fill_up_addresses(struct sctp_inpcb *inp,
1878 struct sctp_tcb *stcb,
1880 struct sockaddr_storage *sas)
1887 SCTP_IPI_ADDR_RLOCK();
1890 * FIX ME: ?? this WILL report duplicate addresses if they appear
1891 * in more than one VRF.
1893 /* fill up addresses for all VRFs on the endpoint */
1894 for (id = 0; (id < inp->num_vrfs) && (size < limit); id++) {
1895 size += sctp_fill_up_addresses_vrf(inp, stcb, limit, sas,
1896 inp->m_vrf_ids[id]);
1897 sas = (struct sockaddr_storage *)((caddr_t)sas + size);
1900 /* fill up addresses for the endpoint's default vrf */
1901 size = sctp_fill_up_addresses_vrf(inp, stcb, limit, sas,
1904 SCTP_IPI_ADDR_RUNLOCK();
1909 * NOTE: assumes addr lock is held
1912 sctp_count_max_addresses_vrf(struct sctp_inpcb *inp, uint32_t vrf_id)
1915 struct sctp_vrf *vrf = NULL;
1918 * In both sub-set bound an bound_all cases we return the MAXIMUM
1919 * number of addresses that you COULD get. In reality the sub-set
1920 * bound may have an exclusion list for a given TCB OR in the
1921 * bound-all case a TCB may NOT include the loopback or other
1922 * addresses as well.
1924 vrf = sctp_find_vrf(vrf_id);
1928 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
1929 struct sctp_ifn *sctp_ifn;
1930 struct sctp_ifa *sctp_ifa;
1932 LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
1933 LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
1934 /* Count them if they are the right type */
1935 switch (sctp_ifa->address.sa.sa_family) {
1938 if (sctp_is_feature_on(inp,SCTP_PCB_FLAGS_NEEDS_MAPPED_V4))
1939 cnt += sizeof(struct sockaddr_in6);
1941 cnt += sizeof(struct sockaddr_in);
1946 cnt += sizeof(struct sockaddr_in6);
1949 #if defined(__Userspace__)
1951 cnt += sizeof(struct sockaddr_conn);
1960 struct sctp_laddr *laddr;
1962 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
1963 switch (laddr->ifa->address.sa.sa_family) {
1966 if (sctp_is_feature_on(inp,SCTP_PCB_FLAGS_NEEDS_MAPPED_V4))
1967 cnt += sizeof(struct sockaddr_in6);
1969 cnt += sizeof(struct sockaddr_in);
1974 cnt += sizeof(struct sockaddr_in6);
1977 #if defined(__Userspace__)
1979 cnt += sizeof(struct sockaddr_conn);
1991 sctp_count_max_addresses(struct sctp_inpcb *inp)
1998 SCTP_IPI_ADDR_RLOCK();
2001 * FIX ME: ?? this WILL count duplicate addresses if they appear
2002 * in more than one VRF.
2004 /* count addresses for all VRFs on the endpoint */
2005 for (id = 0; id < inp->num_vrfs; id++) {
2006 cnt += sctp_count_max_addresses_vrf(inp, inp->m_vrf_ids[id]);
2009 /* count addresses for the endpoint's default VRF */
2010 cnt = sctp_count_max_addresses_vrf(inp, inp->def_vrf_id);
2012 SCTP_IPI_ADDR_RUNLOCK();
2017 sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
2018 size_t optsize, void *p, int delay)
2021 int creat_lock_on = 0;
2022 struct sctp_tcb *stcb = NULL;
2023 struct sockaddr *sa;
2024 int num_v6 = 0, num_v4 = 0, *totaddrp, totaddr;
2026 int bad_addresses = 0;
2029 SCTPDBG(SCTP_DEBUG_PCB1, "Connectx called\n");
2031 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
2032 (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
2033 /* We are already connected AND the TCP model */
2034 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
2035 return (EADDRINUSE);
2038 if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
2039 (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
2040 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2044 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
2045 SCTP_INP_RLOCK(inp);
2046 stcb = LIST_FIRST(&inp->sctp_asoc_list);
2047 SCTP_INP_RUNLOCK(inp);
2050 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
2053 SCTP_INP_INCR_REF(inp);
2054 SCTP_ASOC_CREATE_LOCK(inp);
2056 if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
2057 (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
2058 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
2062 totaddrp = (int *)optval;
2063 totaddr = *totaddrp;
2064 sa = (struct sockaddr *)(totaddrp + 1);
2065 stcb = sctp_connectx_helper_find(inp, sa, &totaddr, &num_v4, &num_v6, &error, (optsize - sizeof(int)), &bad_addresses);
2066 if ((stcb != NULL) || bad_addresses) {
2067 /* Already have or am bring up an association */
2068 SCTP_ASOC_CREATE_UNLOCK(inp);
2071 SCTP_TCB_UNLOCK(stcb);
2072 if (bad_addresses == 0) {
2073 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
2079 if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
2084 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
2086 struct in6pcb *inp6;
2088 inp6 = (struct in6pcb *)inp;
2089 if (SCTP_IPV6_V6ONLY(inp6)) {
2091 * if IPV6_V6ONLY flag, ignore connections destined
2092 * to a v4 addr or v4-mapped addr
2094 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2100 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
2101 SCTP_PCB_FLAGS_UNBOUND) {
2102 /* Bind a ephemeral port */
2103 error = sctp_inpcb_bind(so, NULL, NULL, p);
2109 /* FIX ME: do we want to pass in a vrf on the connect call? */
2110 vrf_id = inp->def_vrf_id;
2113 /* We are GOOD to go */
2114 stcb = sctp_aloc_assoc(inp, sa, &error, 0, vrf_id,
2115 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
2117 #elif defined(__Windows__)
2124 /* Gak! no memory */
2127 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
2128 stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
2129 /* Set the connected flag so we can queue data */
2132 SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
2133 /* move to second address */
2134 switch (sa->sa_family) {
2137 sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in));
2142 sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in6));
2150 sctp_connectx_helper_add(stcb, sa, (totaddr-1), &error);
2151 /* Fill in the return id */
2153 (void)sctp_free_assoc(inp, stcb, SCTP_PCBFREE_FORCE, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_6);
2156 a_id = (sctp_assoc_t *)optval;
2157 *a_id = sctp_get_associd(stcb);
2159 /* initialize authentication parameters for the assoc */
2160 sctp_initialize_auth_params(inp, stcb);
2163 /* doing delayed connection */
2164 stcb->asoc.delayed_connection = 1;
2165 sctp_timer_start(SCTP_TIMER_TYPE_INIT, inp, stcb, stcb->asoc.primary_destination);
2167 (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
2168 sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
2170 SCTP_TCB_UNLOCK(stcb);
2171 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
2172 stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
2173 /* Set the connected flag so we can queue data */
2177 if (creat_lock_on) {
2178 SCTP_ASOC_CREATE_UNLOCK(inp);
2180 SCTP_INP_DECR_REF(inp);
2184 #define SCTP_FIND_STCB(inp, stcb, assoc_id) { \
2185 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||\
2186 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { \
2187 SCTP_INP_RLOCK(inp); \
2188 stcb = LIST_FIRST(&inp->sctp_asoc_list); \
2190 SCTP_TCB_LOCK(stcb); \
2192 SCTP_INP_RUNLOCK(inp); \
2193 } else if (assoc_id > SCTP_ALL_ASSOC) { \
2194 stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1); \
2195 if (stcb == NULL) { \
2196 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT); \
2206 #define SCTP_CHECK_AND_CAST(destp, srcp, type, size) {\
2207 if (size < sizeof(type)) { \
2208 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); \
2212 destp = (type *)srcp; \
2216 #if defined(__Panda__) || defined(__Userspace__)
2221 sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
2223 struct sctp_inpcb *inp = NULL;
2225 struct sctp_tcb *stcb = NULL;
2227 if (optval == NULL) {
2228 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2232 inp = (struct sctp_inpcb *)so->so_pcb;
2234 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2241 case SCTP_AUTOCLOSE:
2242 case SCTP_EXPLICIT_EOR:
2243 case SCTP_AUTO_ASCONF:
2244 case SCTP_DISABLE_FRAGMENTS:
2245 case SCTP_I_WANT_MAPPED_V4_ADDR:
2246 case SCTP_USE_EXT_RCVINFO:
2247 SCTP_INP_RLOCK(inp);
2249 case SCTP_DISABLE_FRAGMENTS:
2250 val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NO_FRAGMENT);
2252 case SCTP_I_WANT_MAPPED_V4_ADDR:
2253 val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4);
2255 case SCTP_AUTO_ASCONF:
2256 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
2257 /* only valid for bound all sockets */
2258 val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTO_ASCONF);
2260 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2265 case SCTP_EXPLICIT_EOR:
2266 val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR);
2269 val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NODELAY);
2271 case SCTP_USE_EXT_RCVINFO:
2272 val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO);
2274 case SCTP_AUTOCLOSE:
2275 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE))
2276 val = TICKS_TO_SEC(inp->sctp_ep.auto_close_time);
2282 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
2283 error = ENOPROTOOPT;
2284 } /* end switch (sopt->sopt_name) */
2285 if (*optsize < sizeof(val)) {
2286 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2290 SCTP_INP_RUNLOCK(inp);
2292 /* return the option value */
2293 *(int *)optval = val;
2294 *optsize = sizeof(val);
2297 case SCTP_GET_PACKET_LOG:
2299 #ifdef SCTP_PACKET_LOGGING
2303 SCTP_CHECK_AND_CAST(target, optval, uint8_t, *optsize);
2304 ret = sctp_copy_out_packet_log(target , (int)*optsize);
2307 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
2312 case SCTP_REUSE_PORT:
2316 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
2317 /* Can't do this for a 1-m socket */
2321 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2322 *value = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE);
2323 *optsize = sizeof(uint32_t);
2326 case SCTP_PARTIAL_DELIVERY_POINT:
2330 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2331 *value = inp->partial_delivery_point;
2332 *optsize = sizeof(uint32_t);
2335 case SCTP_FRAGMENT_INTERLEAVE:
2339 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2340 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE)) {
2341 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS)) {
2342 *value = SCTP_FRAG_LEVEL_2;
2344 *value = SCTP_FRAG_LEVEL_1;
2347 *value = SCTP_FRAG_LEVEL_0;
2349 *optsize = sizeof(uint32_t);
2352 case SCTP_CMT_ON_OFF:
2354 struct sctp_assoc_value *av;
2356 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2357 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2359 av->assoc_value = stcb->asoc.sctp_cmt_on_off;
2360 SCTP_TCB_UNLOCK(stcb);
2362 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2363 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2364 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
2365 SCTP_INP_RLOCK(inp);
2366 av->assoc_value = inp->sctp_cmt_on_off;
2367 SCTP_INP_RUNLOCK(inp);
2369 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2374 *optsize = sizeof(struct sctp_assoc_value);
2378 case SCTP_PLUGGABLE_CC:
2380 struct sctp_assoc_value *av;
2382 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2383 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2385 av->assoc_value = stcb->asoc.congestion_control_module;
2386 SCTP_TCB_UNLOCK(stcb);
2388 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2389 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2390 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
2391 SCTP_INP_RLOCK(inp);
2392 av->assoc_value = inp->sctp_ep.sctp_default_cc_module;
2393 SCTP_INP_RUNLOCK(inp);
2395 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2400 *optsize = sizeof(struct sctp_assoc_value);
2404 case SCTP_CC_OPTION:
2406 struct sctp_cc_option *cc_opt;
2408 SCTP_CHECK_AND_CAST(cc_opt, optval, struct sctp_cc_option, *optsize);
2409 SCTP_FIND_STCB(inp, stcb, cc_opt->aid_value.assoc_id);
2413 if (stcb->asoc.cc_functions.sctp_cwnd_socket_option == NULL) {
2416 error = (*stcb->asoc.cc_functions.sctp_cwnd_socket_option)(stcb, 0, cc_opt);
2417 *optsize = sizeof(struct sctp_cc_option);
2419 SCTP_TCB_UNLOCK(stcb);
2423 case SCTP_PLUGGABLE_SS:
2425 struct sctp_assoc_value *av;
2427 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2428 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2430 av->assoc_value = stcb->asoc.stream_scheduling_module;
2431 SCTP_TCB_UNLOCK(stcb);
2433 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2434 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2435 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
2436 SCTP_INP_RLOCK(inp);
2437 av->assoc_value = inp->sctp_ep.sctp_default_ss_module;
2438 SCTP_INP_RUNLOCK(inp);
2440 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2445 *optsize = sizeof(struct sctp_assoc_value);
2451 struct sctp_stream_value *av;
2453 SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, *optsize);
2454 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2456 if (stcb->asoc.ss_functions.sctp_ss_get_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id],
2457 &av->stream_value) < 0) {
2458 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2461 *optsize = sizeof(struct sctp_stream_value);
2463 SCTP_TCB_UNLOCK(stcb);
2465 /* Can't get stream value without association */
2466 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2471 case SCTP_GET_ADDR_LEN:
2473 struct sctp_assoc_value *av;
2475 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2478 if (av->assoc_value == AF_INET) {
2479 av->assoc_value = sizeof(struct sockaddr_in);
2484 if (av->assoc_value == AF_INET6) {
2485 av->assoc_value = sizeof(struct sockaddr_in6);
2489 #if defined(__Userspace__)
2490 if (av->assoc_value == AF_CONN) {
2491 av->assoc_value = sizeof(struct sockaddr_conn);
2496 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2498 *optsize = sizeof(struct sctp_assoc_value);
2502 case SCTP_GET_ASSOC_NUMBER:
2504 uint32_t *value, cnt;
2506 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2508 SCTP_INP_RLOCK(inp);
2509 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
2512 SCTP_INP_RUNLOCK(inp);
2514 *optsize = sizeof(uint32_t);
2517 case SCTP_GET_ASSOC_ID_LIST:
2519 struct sctp_assoc_ids *ids;
2520 unsigned int at, limit;
2522 SCTP_CHECK_AND_CAST(ids, optval, struct sctp_assoc_ids, *optsize);
2524 limit = (*optsize-sizeof(uint32_t))/ sizeof(sctp_assoc_t);
2525 SCTP_INP_RLOCK(inp);
2526 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
2528 ids->gaids_assoc_id[at++] = sctp_get_associd(stcb);
2531 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2535 SCTP_INP_RUNLOCK(inp);
2537 ids->gaids_number_of_ids = at;
2538 *optsize = ((at * sizeof(sctp_assoc_t)) + sizeof(uint32_t));
2544 struct sctp_assoc_value *av;
2546 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2547 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2550 av->assoc_value = stcb->asoc.context;
2551 SCTP_TCB_UNLOCK(stcb);
2553 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2554 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2555 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
2556 SCTP_INP_RLOCK(inp);
2557 av->assoc_value = inp->sctp_context;
2558 SCTP_INP_RUNLOCK(inp);
2560 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2565 *optsize = sizeof(struct sctp_assoc_value);
2571 uint32_t *default_vrfid;
2573 SCTP_CHECK_AND_CAST(default_vrfid, optval, uint32_t, *optsize);
2574 *default_vrfid = inp->def_vrf_id;
2575 *optsize = sizeof(uint32_t);
2578 case SCTP_GET_ASOC_VRF:
2580 struct sctp_assoc_value *id;
2582 SCTP_CHECK_AND_CAST(id, optval, struct sctp_assoc_value, *optsize);
2583 SCTP_FIND_STCB(inp, stcb, id->assoc_id);
2586 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2588 id->assoc_value = stcb->asoc.vrf_id;
2589 *optsize = sizeof(struct sctp_assoc_value);
2593 case SCTP_GET_VRF_IDS:
2599 SCTP_CHECK_AND_CAST(vrf_ids, optval, uint32_t, *optsize);
2600 siz_needed = inp->num_vrfs * sizeof(uint32_t);
2601 if (*optsize < siz_needed) {
2603 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2605 memcpy(vrf_ids, inp->m_vrf_ids, siz_needed);
2606 *optsize = siz_needed;
2609 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
2614 case SCTP_GET_NONCE_VALUES:
2616 struct sctp_get_nonce_values *gnv;
2618 SCTP_CHECK_AND_CAST(gnv, optval, struct sctp_get_nonce_values, *optsize);
2619 SCTP_FIND_STCB(inp, stcb, gnv->gn_assoc_id);
2622 gnv->gn_peers_tag = stcb->asoc.peer_vtag;
2623 gnv->gn_local_tag = stcb->asoc.my_vtag;
2624 SCTP_TCB_UNLOCK(stcb);
2625 *optsize = sizeof(struct sctp_get_nonce_values);
2627 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
2632 case SCTP_DELAYED_SACK:
2634 struct sctp_sack_info *sack;
2636 SCTP_CHECK_AND_CAST(sack, optval, struct sctp_sack_info, *optsize);
2637 SCTP_FIND_STCB(inp, stcb, sack->sack_assoc_id);
2639 sack->sack_delay = stcb->asoc.delayed_ack;
2640 sack->sack_freq = stcb->asoc.sack_freq;
2641 SCTP_TCB_UNLOCK(stcb);
2643 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2644 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2645 (sack->sack_assoc_id == SCTP_FUTURE_ASSOC)) {
2646 SCTP_INP_RLOCK(inp);
2647 sack->sack_delay = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
2648 sack->sack_freq = inp->sctp_ep.sctp_sack_freq;
2649 SCTP_INP_RUNLOCK(inp);
2651 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2656 *optsize = sizeof(struct sctp_sack_info);
2660 case SCTP_GET_SNDBUF_USE:
2662 struct sctp_sockstat *ss;
2664 SCTP_CHECK_AND_CAST(ss, optval, struct sctp_sockstat, *optsize);
2665 SCTP_FIND_STCB(inp, stcb, ss->ss_assoc_id);
2668 ss->ss_total_sndbuf = stcb->asoc.total_output_queue_size;
2669 ss->ss_total_recv_buf = (stcb->asoc.size_on_reasm_queue +
2670 stcb->asoc.size_on_all_streams);
2671 SCTP_TCB_UNLOCK(stcb);
2672 *optsize = sizeof(struct sctp_sockstat);
2674 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
2679 case SCTP_MAX_BURST:
2681 #if defined(__FreeBSD__) && __FreeBSD_version < 900000
2684 SCTP_CHECK_AND_CAST(value, optval, uint8_t, *optsize);
2686 SCTP_INP_RLOCK(inp);
2687 if (inp->sctp_ep.max_burst < 256) {
2688 *value = inp->sctp_ep.max_burst;
2692 SCTP_INP_RUNLOCK(inp);
2693 *optsize = sizeof(uint8_t);
2695 struct sctp_assoc_value *av;
2697 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2698 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2701 av->assoc_value = stcb->asoc.max_burst;
2702 SCTP_TCB_UNLOCK(stcb);
2704 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2705 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2706 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
2707 SCTP_INP_RLOCK(inp);
2708 av->assoc_value = inp->sctp_ep.max_burst;
2709 SCTP_INP_RUNLOCK(inp);
2711 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2716 *optsize = sizeof(struct sctp_assoc_value);
2723 struct sctp_assoc_value *av;
2726 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2727 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2730 av->assoc_value = sctp_get_frag_point(stcb, &stcb->asoc);
2731 SCTP_TCB_UNLOCK(stcb);
2733 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2734 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2735 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
2736 SCTP_INP_RLOCK(inp);
2737 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
2738 ovh = SCTP_MED_OVERHEAD;
2740 ovh = SCTP_MED_V4_OVERHEAD;
2742 if (inp->sctp_frag_point >= SCTP_DEFAULT_MAXSEGMENT)
2743 av->assoc_value = 0;
2745 av->assoc_value = inp->sctp_frag_point - ovh;
2746 SCTP_INP_RUNLOCK(inp);
2748 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2753 *optsize = sizeof(struct sctp_assoc_value);
2757 case SCTP_GET_STAT_LOG:
2758 error = sctp_fill_stat_log(optval, optsize);
2762 struct sctp_event_subscribe *events;
2764 SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, *optsize);
2765 memset(events, 0, sizeof(struct sctp_event_subscribe));
2766 SCTP_INP_RLOCK(inp);
2767 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT))
2768 events->sctp_data_io_event = 1;
2770 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT))
2771 events->sctp_association_event = 1;
2773 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVPADDREVNT))
2774 events->sctp_address_event = 1;
2776 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT))
2777 events->sctp_send_failure_event = 1;
2779 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVPEERERR))
2780 events->sctp_peer_error_event = 1;
2782 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT))
2783 events->sctp_shutdown_event = 1;
2785 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT))
2786 events->sctp_partial_delivery_event = 1;
2788 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT))
2789 events->sctp_adaptation_layer_event = 1;
2791 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT))
2792 events->sctp_authentication_event = 1;
2794 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT))
2795 events->sctp_sender_dry_event = 1;
2797 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT))
2798 events->sctp_stream_reset_event = 1;
2799 SCTP_INP_RUNLOCK(inp);
2800 *optsize = sizeof(struct sctp_event_subscribe);
2803 case SCTP_ADAPTATION_LAYER:
2807 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2809 SCTP_INP_RLOCK(inp);
2810 *value = inp->sctp_ep.adaptation_layer_indicator;
2811 SCTP_INP_RUNLOCK(inp);
2812 *optsize = sizeof(uint32_t);
2815 case SCTP_SET_INITIAL_DBG_SEQ:
2819 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2820 SCTP_INP_RLOCK(inp);
2821 *value = inp->sctp_ep.initial_sequence_debug;
2822 SCTP_INP_RUNLOCK(inp);
2823 *optsize = sizeof(uint32_t);
2826 case SCTP_GET_LOCAL_ADDR_SIZE:
2830 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2831 SCTP_INP_RLOCK(inp);
2832 *value = sctp_count_max_addresses(inp);
2833 SCTP_INP_RUNLOCK(inp);
2834 *optsize = sizeof(uint32_t);
2837 case SCTP_GET_REMOTE_ADDR_SIZE:
2841 struct sctp_nets *net;
2843 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2844 /* FIXME MT: change to sctp_assoc_value? */
2845 SCTP_FIND_STCB(inp, stcb, (sctp_assoc_t) *value);
2849 /* Count the sizes */
2850 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
2851 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
2852 size += sizeof(struct sockaddr_in6);
2854 switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) {
2857 size += sizeof(struct sockaddr_in);
2862 size += sizeof(struct sockaddr_in6);
2865 #if defined(__Userspace__)
2867 size += sizeof(struct sockaddr_conn);
2875 SCTP_TCB_UNLOCK(stcb);
2876 *value = (uint32_t) size;
2877 *optsize = sizeof(uint32_t);
2879 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
2884 case SCTP_GET_PEER_ADDRESSES:
2886 * Get the address information, an array is passed in to
2887 * fill up we pack it.
2891 struct sockaddr_storage *sas;
2892 struct sctp_nets *net;
2893 struct sctp_getaddresses *saddr;
2895 SCTP_CHECK_AND_CAST(saddr, optval, struct sctp_getaddresses, *optsize);
2896 SCTP_FIND_STCB(inp, stcb, saddr->sget_assoc_id);
2899 left = (*optsize) - sizeof(struct sctp_getaddresses);
2900 *optsize = sizeof(struct sctp_getaddresses);
2901 sas = (struct sockaddr_storage *)&saddr->addr[0];
2903 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
2904 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
2905 cpsz = sizeof(struct sockaddr_in6);
2907 switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) {
2910 cpsz = sizeof(struct sockaddr_in);
2915 cpsz = sizeof(struct sockaddr_in6);
2918 #if defined(__Userspace__)
2920 cpsz = sizeof(struct sockaddr_conn);
2932 /* not enough room. */
2935 #if defined(INET) && defined(INET6)
2936 if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) &&
2937 (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET)) {
2938 /* Must map the address */
2939 in6_sin_2_v4mapsin6((struct sockaddr_in *)&net->ro._l_addr,
2940 (struct sockaddr_in6 *)sas);
2943 memcpy(sas, &net->ro._l_addr, cpsz);
2944 #if defined(INET) && defined(INET6)
2947 ((struct sockaddr_in *)sas)->sin_port = stcb->rport;
2949 sas = (struct sockaddr_storage *)((caddr_t)sas + cpsz);
2953 SCTP_TCB_UNLOCK(stcb);
2955 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
2960 case SCTP_GET_LOCAL_ADDRESSES:
2962 size_t limit, actual;
2963 struct sockaddr_storage *sas;
2964 struct sctp_getaddresses *saddr;
2966 SCTP_CHECK_AND_CAST(saddr, optval, struct sctp_getaddresses, *optsize);
2967 SCTP_FIND_STCB(inp, stcb, saddr->sget_assoc_id);
2969 sas = (struct sockaddr_storage *)&saddr->addr[0];
2970 limit = *optsize - sizeof(sctp_assoc_t);
2971 actual = sctp_fill_up_addresses(inp, stcb, limit, sas);
2973 SCTP_TCB_UNLOCK(stcb);
2975 *optsize = sizeof(struct sockaddr_storage) + actual;
2978 case SCTP_PEER_ADDR_PARAMS:
2980 struct sctp_paddrparams *paddrp;
2981 struct sctp_nets *net;
2983 SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, *optsize);
2984 SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
2988 net = sctp_findnet(stcb, (struct sockaddr *)&paddrp->spp_address);
2990 /* We increment here since sctp_findassociation_ep_addr() wil
2991 * do a decrement if it finds the stcb as long as the locked
2992 * tcb (last argument) is NOT a TCB.. aka NULL.
2994 SCTP_INP_INCR_REF(inp);
2995 stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&paddrp->spp_address, &net, NULL, NULL);
2997 SCTP_INP_DECR_REF(inp);
3000 if (stcb && (net == NULL)) {
3001 struct sockaddr *sa;
3003 sa = (struct sockaddr *)&paddrp->spp_address;
3005 if (sa->sa_family == AF_INET) {
3006 struct sockaddr_in *sin;
3008 sin = (struct sockaddr_in *)sa;
3009 if (sin->sin_addr.s_addr) {
3011 SCTP_TCB_UNLOCK(stcb);
3012 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3018 if (sa->sa_family == AF_INET6) {
3019 struct sockaddr_in6 *sin6;
3021 sin6 = (struct sockaddr_in6 *)sa;
3022 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
3024 SCTP_TCB_UNLOCK(stcb);
3025 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3030 #if defined(__Userspace__)
3031 if (sa->sa_family == AF_CONN) {
3032 struct sockaddr_conn *sconn;
3034 sconn = (struct sockaddr_conn *)sa;
3035 if (sconn->sconn_addr != NULL) {
3037 SCTP_TCB_UNLOCK(stcb);
3038 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3044 error = EAFNOSUPPORT;
3045 SCTP_TCB_UNLOCK(stcb);
3046 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3052 /* Applies to the specific association */
3053 paddrp->spp_flags = 0;
3056 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
3057 ovh = SCTP_MED_OVERHEAD;
3059 ovh = SCTP_MED_V4_OVERHEAD;
3062 paddrp->spp_hbinterval = net->heart_beat_delay;
3063 paddrp->spp_pathmaxrxt = net->failure_threshold;
3064 paddrp->spp_pathmtu = net->mtu - ovh;
3065 /* get flags for HB */
3066 if (net->dest_state & SCTP_ADDR_NOHB) {
3067 paddrp->spp_flags |= SPP_HB_DISABLE;
3069 paddrp->spp_flags |= SPP_HB_ENABLE;
3071 /* get flags for PMTU */
3072 if (net->dest_state & SCTP_ADDR_NO_PMTUD) {
3073 paddrp->spp_flags |= SPP_PMTUD_ENABLE;
3075 paddrp->spp_flags |= SPP_PMTUD_DISABLE;
3077 if (net->dscp & 0x01) {
3078 paddrp->spp_dscp = net->dscp & 0xfc;
3079 paddrp->spp_flags |= SPP_DSCP;
3082 if ((net->ro._l_addr.sa.sa_family == AF_INET6) &&
3083 (net->flowlabel & 0x80000000)) {
3084 paddrp->spp_ipv6_flowlabel = net->flowlabel & 0x000fffff;
3085 paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
3090 * No destination so return default
3093 paddrp->spp_pathmaxrxt = stcb->asoc.def_net_failure;
3094 paddrp->spp_pathmtu = sctp_get_frag_point(stcb, &stcb->asoc);
3095 if (stcb->asoc.default_dscp & 0x01) {
3096 paddrp->spp_dscp = stcb->asoc.default_dscp & 0xfc;
3097 paddrp->spp_flags |= SPP_DSCP;
3100 if (stcb->asoc.default_flowlabel & 0x80000000) {
3101 paddrp->spp_ipv6_flowlabel = stcb->asoc.default_flowlabel & 0x000fffff;
3102 paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
3105 /* default settings should be these */
3106 if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
3107 paddrp->spp_flags |= SPP_HB_DISABLE;
3109 paddrp->spp_flags |= SPP_HB_ENABLE;
3111 if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD)) {
3112 paddrp->spp_flags |= SPP_PMTUD_DISABLE;
3114 paddrp->spp_flags |= SPP_PMTUD_ENABLE;
3116 paddrp->spp_hbinterval = stcb->asoc.heart_beat_delay;
3118 paddrp->spp_assoc_id = sctp_get_associd(stcb);
3119 SCTP_TCB_UNLOCK(stcb);
3121 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3122 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3123 (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC)) {
3124 /* Use endpoint defaults */
3125 SCTP_INP_RLOCK(inp);
3126 paddrp->spp_pathmaxrxt = inp->sctp_ep.def_net_failure;
3127 paddrp->spp_hbinterval = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]);
3128 paddrp->spp_assoc_id = SCTP_FUTURE_ASSOC;
3129 /* get inp's default */
3130 if (inp->sctp_ep.default_dscp & 0x01) {
3131 paddrp->spp_dscp = inp->sctp_ep.default_dscp & 0xfc;
3132 paddrp->spp_flags |= SPP_DSCP;
3135 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
3136 (inp->sctp_ep.default_flowlabel & 0x80000000)) {
3137 paddrp->spp_ipv6_flowlabel = inp->sctp_ep.default_flowlabel & 0x000fffff;
3138 paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
3141 /* can't return this */
3142 paddrp->spp_pathmtu = 0;
3144 if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
3145 paddrp->spp_flags |= SPP_HB_ENABLE;
3147 paddrp->spp_flags |= SPP_HB_DISABLE;
3149 if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD)) {
3150 paddrp->spp_flags |= SPP_PMTUD_ENABLE;
3152 paddrp->spp_flags |= SPP_PMTUD_DISABLE;
3154 SCTP_INP_RUNLOCK(inp);
3156 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3161 *optsize = sizeof(struct sctp_paddrparams);
3165 case SCTP_GET_PEER_ADDR_INFO:
3167 struct sctp_paddrinfo *paddri;
3168 struct sctp_nets *net;
3170 SCTP_CHECK_AND_CAST(paddri, optval, struct sctp_paddrinfo, *optsize);
3171 SCTP_FIND_STCB(inp, stcb, paddri->spinfo_assoc_id);
3175 net = sctp_findnet(stcb, (struct sockaddr *)&paddri->spinfo_address);
3177 /* We increment here since sctp_findassociation_ep_addr() wil
3178 * do a decrement if it finds the stcb as long as the locked
3179 * tcb (last argument) is NOT a TCB.. aka NULL.
3181 SCTP_INP_INCR_REF(inp);
3182 stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&paddri->spinfo_address, &net, NULL, NULL);
3184 SCTP_INP_DECR_REF(inp);
3188 if ((stcb) && (net)) {
3189 if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
3190 /* It's unconfirmed */
3191 paddri->spinfo_state = SCTP_UNCONFIRMED;
3192 } else if (net->dest_state & SCTP_ADDR_REACHABLE) {
3194 paddri->spinfo_state = SCTP_ACTIVE;
3197 paddri->spinfo_state = SCTP_INACTIVE;
3199 paddri->spinfo_cwnd = net->cwnd;
3200 paddri->spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT;
3201 paddri->spinfo_rto = net->RTO;
3202 paddri->spinfo_assoc_id = sctp_get_associd(stcb);
3203 paddri->spinfo_mtu = net->mtu;
3204 SCTP_TCB_UNLOCK(stcb);
3205 *optsize = sizeof(struct sctp_paddrinfo);
3208 SCTP_TCB_UNLOCK(stcb);
3210 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
3215 case SCTP_PCB_STATUS:
3217 struct sctp_pcbinfo *spcb;
3219 SCTP_CHECK_AND_CAST(spcb, optval, struct sctp_pcbinfo, *optsize);
3220 sctp_fill_pcbinfo(spcb);
3221 *optsize = sizeof(struct sctp_pcbinfo);
3226 struct sctp_nets *net;
3227 struct sctp_status *sstat;
3229 SCTP_CHECK_AND_CAST(sstat, optval, struct sctp_status, *optsize);
3230 SCTP_FIND_STCB(inp, stcb, sstat->sstat_assoc_id);
3233 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3238 * I think passing the state is fine since
3239 * sctp_constants.h will be available to the user
3242 sstat->sstat_state = stcb->asoc.state;
3243 sstat->sstat_assoc_id = sctp_get_associd(stcb);
3244 sstat->sstat_rwnd = stcb->asoc.peers_rwnd;
3245 sstat->sstat_unackdata = stcb->asoc.sent_queue_cnt;
3247 * We can't include chunks that have been passed to
3248 * the socket layer. Only things in queue.
3250 sstat->sstat_penddata = (stcb->asoc.cnt_on_reasm_queue +
3251 stcb->asoc.cnt_on_all_streams);
3254 sstat->sstat_instrms = stcb->asoc.streamincnt;
3255 sstat->sstat_outstrms = stcb->asoc.streamoutcnt;
3256 sstat->sstat_fragmentation_point = sctp_get_frag_point(stcb, &stcb->asoc);
3258 memcpy(&sstat->sstat_primary.spinfo_address,
3259 &stcb->asoc.primary_destination->ro._l_addr,
3260 ((struct sockaddr *)(&stcb->asoc.primary_destination->ro._l_addr))->sa_len);
3262 if (stcb->asoc.primary_destination->ro._l_addr.sa.sa_family == AF_INET) {
3263 memcpy(&sstat->sstat_primary.spinfo_address,
3264 &stcb->asoc.primary_destination->ro._l_addr,
3265 sizeof(struct sockaddr_in));
3267 memcpy(&sstat->sstat_primary.spinfo_address,
3268 &stcb->asoc.primary_destination->ro._l_addr,
3269 sizeof(struct sockaddr_in6));
3272 net = stcb->asoc.primary_destination;
3273 ((struct sockaddr_in *)&sstat->sstat_primary.spinfo_address)->sin_port = stcb->rport;
3275 * Again the user can get info from sctp_constants.h
3276 * for what the state of the network is.
3278 if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
3279 /* It's unconfirmed */
3280 sstat->sstat_primary.spinfo_state = SCTP_UNCONFIRMED;
3281 } else if (net->dest_state & SCTP_ADDR_REACHABLE) {
3283 sstat->sstat_primary.spinfo_state = SCTP_ACTIVE;
3286 sstat->sstat_primary.spinfo_state = SCTP_INACTIVE;
3288 sstat->sstat_primary.spinfo_cwnd = net->cwnd;
3289 sstat->sstat_primary.spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT;
3290 sstat->sstat_primary.spinfo_rto = net->RTO;
3291 sstat->sstat_primary.spinfo_mtu = net->mtu;
3292 sstat->sstat_primary.spinfo_assoc_id = sctp_get_associd(stcb);
3293 SCTP_TCB_UNLOCK(stcb);
3294 *optsize = sizeof(struct sctp_status);
3299 struct sctp_rtoinfo *srto;
3301 SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, *optsize);
3302 SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
3305 srto->srto_initial = stcb->asoc.initial_rto;
3306 srto->srto_max = stcb->asoc.maxrto;
3307 srto->srto_min = stcb->asoc.minrto;
3308 SCTP_TCB_UNLOCK(stcb);
3310 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3311 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3312 (srto->srto_assoc_id == SCTP_FUTURE_ASSOC)) {
3313 SCTP_INP_RLOCK(inp);
3314 srto->srto_initial = inp->sctp_ep.initial_rto;
3315 srto->srto_max = inp->sctp_ep.sctp_maxrto;
3316 srto->srto_min = inp->sctp_ep.sctp_minrto;
3317 SCTP_INP_RUNLOCK(inp);
3319 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3324 *optsize = sizeof(struct sctp_rtoinfo);
3330 struct sctp_timeouts *stimo;
3332 SCTP_CHECK_AND_CAST(stimo, optval, struct sctp_timeouts, *optsize);
3333 SCTP_FIND_STCB(inp, stcb, stimo->stimo_assoc_id);
3336 stimo->stimo_init= stcb->asoc.timoinit;
3337 stimo->stimo_data= stcb->asoc.timodata;
3338 stimo->stimo_sack= stcb->asoc.timosack;
3339 stimo->stimo_shutdown= stcb->asoc.timoshutdown;
3340 stimo->stimo_heartbeat= stcb->asoc.timoheartbeat;
3341 stimo->stimo_cookie= stcb->asoc.timocookie;
3342 stimo->stimo_shutdownack= stcb->asoc.timoshutdownack;
3343 SCTP_TCB_UNLOCK(stcb);
3344 *optsize = sizeof(struct sctp_timeouts);
3346 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3351 case SCTP_ASSOCINFO:
3353 struct sctp_assocparams *sasoc;
3355 SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, *optsize);
3356 SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
3359 sasoc->sasoc_cookie_life = TICKS_TO_MSEC(stcb->asoc.cookie_life);
3360 sasoc->sasoc_asocmaxrxt = stcb->asoc.max_send_times;
3361 sasoc->sasoc_number_peer_destinations = stcb->asoc.numnets;
3362 sasoc->sasoc_peer_rwnd = stcb->asoc.peers_rwnd;
3363 sasoc->sasoc_local_rwnd = stcb->asoc.my_rwnd;
3364 SCTP_TCB_UNLOCK(stcb);
3366 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3367 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3368 (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC)) {
3369 SCTP_INP_RLOCK(inp);
3370 sasoc->sasoc_cookie_life = TICKS_TO_MSEC(inp->sctp_ep.def_cookie_life);
3371 sasoc->sasoc_asocmaxrxt = inp->sctp_ep.max_send_times;
3372 sasoc->sasoc_number_peer_destinations = 0;
3373 sasoc->sasoc_peer_rwnd = 0;
3374 sasoc->sasoc_local_rwnd = sbspace(&inp->sctp_socket->so_rcv);
3375 SCTP_INP_RUNLOCK(inp);
3377 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3382 *optsize = sizeof(struct sctp_assocparams);
3386 case SCTP_DEFAULT_SEND_PARAM:
3388 struct sctp_sndrcvinfo *s_info;
3390 SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, *optsize);
3391 SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
3394 memcpy(s_info, &stcb->asoc.def_send, sizeof(stcb->asoc.def_send));
3395 SCTP_TCB_UNLOCK(stcb);
3397 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3398 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3399 (s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC)) {
3400 SCTP_INP_RLOCK(inp);
3401 memcpy(s_info, &inp->def_send, sizeof(inp->def_send));
3402 SCTP_INP_RUNLOCK(inp);
3404 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3409 *optsize = sizeof(struct sctp_sndrcvinfo);
3415 struct sctp_initmsg *sinit;
3417 SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, *optsize);
3418 SCTP_INP_RLOCK(inp);
3419 sinit->sinit_num_ostreams = inp->sctp_ep.pre_open_stream_count;
3420 sinit->sinit_max_instreams = inp->sctp_ep.max_open_streams_intome;
3421 sinit->sinit_max_attempts = inp->sctp_ep.max_init_times;
3422 sinit->sinit_max_init_timeo = inp->sctp_ep.initial_init_rto_max;
3423 SCTP_INP_RUNLOCK(inp);
3424 *optsize = sizeof(struct sctp_initmsg);
3427 case SCTP_PRIMARY_ADDR:
3428 /* we allow a "get" operation on this */
3430 struct sctp_setprim *ssp;
3432 SCTP_CHECK_AND_CAST(ssp, optval, struct sctp_setprim, *optsize);
3433 SCTP_FIND_STCB(inp, stcb, ssp->ssp_assoc_id);
3436 /* simply copy out the sockaddr_storage... */
3441 if (len > stcb->asoc.primary_destination->ro._l_addr.sa.sa_len)
3442 len = stcb->asoc.primary_destination->ro._l_addr.sa.sa_len;
3444 if (stcb->asoc.primary_destination->ro._l_addr.sa.sa_family == AF_INET &&
3445 len > sizeof(struct sockaddr_in))
3446 len = sizeof(struct sockaddr_in);
3448 stcb->asoc.primary_destination->ro._l_addr.sa.sa_family == AF_INET6 &&
3449 len > sizeof(struct sockaddr_in6))
3450 len = sizeof(struct sockaddr_in6);
3453 memcpy(&ssp->ssp_addr,
3454 &stcb->asoc.primary_destination->ro._l_addr,
3456 SCTP_TCB_UNLOCK(stcb);
3457 *optsize = sizeof(struct sctp_setprim);
3459 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3464 case SCTP_HMAC_IDENT:
3466 struct sctp_hmacalgo *shmac;
3467 sctp_hmaclist_t *hmaclist;
3471 SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, *optsize);
3473 SCTP_INP_RLOCK(inp);
3474 hmaclist = inp->sctp_ep.local_hmacs;
3475 if (hmaclist == NULL) {
3476 /* no HMACs to return */
3477 *optsize = sizeof(*shmac);
3478 SCTP_INP_RUNLOCK(inp);
3481 /* is there room for all of the hmac ids? */
3482 size = sizeof(*shmac) + (hmaclist->num_algo *
3483 sizeof(shmac->shmac_idents[0]));
3484 if ((size_t)(*optsize) < size) {
3485 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3487 SCTP_INP_RUNLOCK(inp);
3490 /* copy in the list */
3491 shmac->shmac_number_of_idents = hmaclist->num_algo;
3492 for (i = 0; i < hmaclist->num_algo; i++) {
3493 shmac->shmac_idents[i] = hmaclist->hmac[i];
3495 SCTP_INP_RUNLOCK(inp);
3499 case SCTP_AUTH_ACTIVE_KEY:
3501 struct sctp_authkeyid *scact;
3503 SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, *optsize);
3504 SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id);
3507 /* get the active key on the assoc */
3508 scact->scact_keynumber = stcb->asoc.authinfo.active_keyid;
3509 SCTP_TCB_UNLOCK(stcb);
3511 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3512 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3513 (scact->scact_assoc_id == SCTP_FUTURE_ASSOC)) {
3514 /* get the endpoint active key */
3515 SCTP_INP_RLOCK(inp);
3516 scact->scact_keynumber = inp->sctp_ep.default_keyid;
3517 SCTP_INP_RUNLOCK(inp);
3519 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3524 *optsize = sizeof(struct sctp_authkeyid);
3528 case SCTP_LOCAL_AUTH_CHUNKS:
3530 struct sctp_authchunks *sac;
3531 sctp_auth_chklist_t *chklist = NULL;
3534 SCTP_CHECK_AND_CAST(sac, optval, struct sctp_authchunks, *optsize);
3535 SCTP_FIND_STCB(inp, stcb, sac->gauth_assoc_id);
3538 /* get off the assoc */
3539 chklist = stcb->asoc.local_auth_chunks;
3540 /* is there enough space? */
3541 size = sctp_auth_get_chklist_size(chklist);
3542 if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
3544 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3546 /* copy in the chunks */
3547 (void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
3548 sac->gauth_number_of_chunks = (uint32_t)size;
3549 *optsize = sizeof(struct sctp_authchunks) + size;
3551 SCTP_TCB_UNLOCK(stcb);
3553 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3554 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3555 (sac->gauth_assoc_id == SCTP_FUTURE_ASSOC)) {
3556 /* get off the endpoint */
3557 SCTP_INP_RLOCK(inp);
3558 chklist = inp->sctp_ep.local_auth_chunks;
3559 /* is there enough space? */
3560 size = sctp_auth_get_chklist_size(chklist);
3561 if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
3563 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3565 /* copy in the chunks */
3566 (void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
3567 sac->gauth_number_of_chunks = (uint32_t)size;
3568 *optsize = sizeof(struct sctp_authchunks) + size;
3570 SCTP_INP_RUNLOCK(inp);
3572 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3578 case SCTP_PEER_AUTH_CHUNKS:
3580 struct sctp_authchunks *sac;
3581 sctp_auth_chklist_t *chklist = NULL;
3584 SCTP_CHECK_AND_CAST(sac, optval, struct sctp_authchunks, *optsize);
3585 SCTP_FIND_STCB(inp, stcb, sac->gauth_assoc_id);
3588 /* get off the assoc */
3589 chklist = stcb->asoc.peer_auth_chunks;
3590 /* is there enough space? */
3591 size = sctp_auth_get_chklist_size(chklist);
3592 if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
3594 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3596 /* copy in the chunks */
3597 (void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
3598 sac->gauth_number_of_chunks = (uint32_t)size;
3599 *optsize = sizeof(struct sctp_authchunks) + size;
3601 SCTP_TCB_UNLOCK(stcb);
3603 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
3608 #if defined(HAVE_SCTP_PEELOFF_SOCKOPT)
3611 struct sctp_peeloff_opt *peeloff;
3613 SCTP_CHECK_AND_CAST(peeloff, optval, struct sctp_peeloff_opt, *optsize);
3614 /* do the peeloff */
3615 error = sctp_peeloff_option(p, peeloff);
3617 *optsize = sizeof(struct sctp_peeloff_opt);
3621 #endif /* HAVE_SCTP_PEELOFF_SOCKOPT */
3624 struct sctp_event *event;
3625 uint32_t event_type;
3627 SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, *optsize);
3628 SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
3630 switch (event->se_type) {
3631 case SCTP_ASSOC_CHANGE:
3632 event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
3634 case SCTP_PEER_ADDR_CHANGE:
3635 event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
3637 case SCTP_REMOTE_ERROR:
3638 event_type = SCTP_PCB_FLAGS_RECVPEERERR;
3640 case SCTP_SEND_FAILED:
3641 event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
3643 case SCTP_SHUTDOWN_EVENT:
3644 event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
3646 case SCTP_ADAPTATION_INDICATION:
3647 event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
3649 case SCTP_PARTIAL_DELIVERY_EVENT:
3650 event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
3652 case SCTP_AUTHENTICATION_EVENT:
3653 event_type = SCTP_PCB_FLAGS_AUTHEVNT;
3655 case SCTP_STREAM_RESET_EVENT:
3656 event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
3658 case SCTP_SENDER_DRY_EVENT:
3659 event_type = SCTP_PCB_FLAGS_DRYEVNT;
3661 case SCTP_NOTIFICATIONS_STOPPED_EVENT:
3663 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
3666 case SCTP_ASSOC_RESET_EVENT:
3667 event_type = SCTP_PCB_FLAGS_ASSOC_RESETEVNT;
3669 case SCTP_STREAM_CHANGE_EVENT:
3670 event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT;
3672 case SCTP_SEND_FAILED_EVENT:
3673 event_type = SCTP_PCB_FLAGS_RECVNSENDFAILEVNT;
3677 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3681 if (event_type > 0) {
3683 event->se_on = sctp_stcb_is_feature_on(inp, stcb, event_type);
3684 SCTP_TCB_UNLOCK(stcb);
3686 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3687 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3688 (event->se_assoc_id == SCTP_FUTURE_ASSOC)) {
3689 SCTP_INP_RLOCK(inp);
3690 event->se_on = sctp_is_feature_on(inp, event_type);
3691 SCTP_INP_RUNLOCK(inp);
3693 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3699 *optsize = sizeof(struct sctp_event);
3703 case SCTP_RECVRCVINFO:
3707 if (*optsize < sizeof(int)) {
3708 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3711 SCTP_INP_RLOCK(inp);
3712 onoff = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
3713 SCTP_INP_RUNLOCK(inp);
3716 /* return the option value */
3717 *(int *)optval = onoff;
3718 *optsize = sizeof(int);
3722 case SCTP_RECVNXTINFO:
3726 if (*optsize < sizeof(int)) {
3727 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3730 SCTP_INP_RLOCK(inp);
3731 onoff = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
3732 SCTP_INP_RUNLOCK(inp);
3735 /* return the option value */
3736 *(int *)optval = onoff;
3737 *optsize = sizeof(int);
3741 case SCTP_DEFAULT_SNDINFO:
3743 struct sctp_sndinfo *info;
3745 SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, *optsize);
3746 SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
3749 info->snd_sid = stcb->asoc.def_send.sinfo_stream;
3750 info->snd_flags = stcb->asoc.def_send.sinfo_flags;
3751 info->snd_flags &= 0xfff0;
3752 info->snd_ppid = stcb->asoc.def_send.sinfo_ppid;
3753 info->snd_context = stcb->asoc.def_send.sinfo_context;
3754 SCTP_TCB_UNLOCK(stcb);
3756 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3757 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3758 (info->snd_assoc_id == SCTP_FUTURE_ASSOC)) {
3759 SCTP_INP_RLOCK(inp);
3760 info->snd_sid = inp->def_send.sinfo_stream;
3761 info->snd_flags = inp->def_send.sinfo_flags;
3762 info->snd_flags &= 0xfff0;
3763 info->snd_ppid = inp->def_send.sinfo_ppid;
3764 info->snd_context = inp->def_send.sinfo_context;
3765 SCTP_INP_RUNLOCK(inp);
3767 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3772 *optsize = sizeof(struct sctp_sndinfo);
3776 case SCTP_DEFAULT_PRINFO:
3778 struct sctp_default_prinfo *info;
3780 SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, *optsize);
3781 SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
3784 info->pr_policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
3785 info->pr_value = stcb->asoc.def_send.sinfo_timetolive;
3786 SCTP_TCB_UNLOCK(stcb);
3788 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3789 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3790 (info->pr_assoc_id == SCTP_FUTURE_ASSOC)) {
3791 SCTP_INP_RLOCK(inp);
3792 info->pr_policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
3793 info->pr_value = inp->def_send.sinfo_timetolive;
3794 SCTP_INP_RUNLOCK(inp);
3796 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3801 *optsize = sizeof(struct sctp_default_prinfo);
3805 case SCTP_PEER_ADDR_THLDS:
3807 struct sctp_paddrthlds *thlds;
3808 struct sctp_nets *net;
3810 SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, *optsize);
3811 SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
3815 net = sctp_findnet(stcb, (struct sockaddr *)&thlds->spt_address);
3817 /* We increment here since sctp_findassociation_ep_addr() wil
3818 * do a decrement if it finds the stcb as long as the locked
3819 * tcb (last argument) is NOT a TCB.. aka NULL.
3821 SCTP_INP_INCR_REF(inp);
3822 stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&thlds->spt_address, &net, NULL, NULL);
3824 SCTP_INP_DECR_REF(inp);
3827 if (stcb && (net == NULL)) {
3828 struct sockaddr *sa;
3830 sa = (struct sockaddr *)&thlds->spt_address;
3832 if (sa->sa_family == AF_INET) {
3833 struct sockaddr_in *sin;
3835 sin = (struct sockaddr_in *)sa;
3836 if (sin->sin_addr.s_addr) {
3838 SCTP_TCB_UNLOCK(stcb);
3839 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3845 if (sa->sa_family == AF_INET6) {
3846 struct sockaddr_in6 *sin6;
3848 sin6 = (struct sockaddr_in6 *)sa;
3849 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
3851 SCTP_TCB_UNLOCK(stcb);
3852 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3857 #if defined(__Userspace__)
3858 if (sa->sa_family == AF_CONN) {
3859 struct sockaddr_conn *sconn;
3861 sconn = (struct sockaddr_conn *)sa;
3862 if (sconn->sconn_addr != NULL) {
3864 SCTP_TCB_UNLOCK(stcb);
3865 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3871 error = EAFNOSUPPORT;
3872 SCTP_TCB_UNLOCK(stcb);
3873 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3880 thlds->spt_pathmaxrxt = net->failure_threshold;
3881 thlds->spt_pathpfthld = net->pf_threshold;
3883 thlds->spt_pathmaxrxt = stcb->asoc.def_net_failure;
3884 thlds->spt_pathpfthld = stcb->asoc.def_net_pf_threshold;
3886 thlds->spt_assoc_id = sctp_get_associd(stcb);
3887 SCTP_TCB_UNLOCK(stcb);
3889 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3890 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3891 (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC)) {
3892 /* Use endpoint defaults */
3893 SCTP_INP_RLOCK(inp);
3894 thlds->spt_pathmaxrxt = inp->sctp_ep.def_net_failure;
3895 thlds->spt_pathpfthld = inp->sctp_ep.def_net_pf_threshold;
3896 SCTP_INP_RUNLOCK(inp);
3898 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3903 *optsize = sizeof(struct sctp_paddrthlds);
3907 case SCTP_REMOTE_UDP_ENCAPS_PORT:
3909 struct sctp_udpencaps *encaps;
3910 struct sctp_nets *net;
3912 SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, *optsize);
3913 SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
3916 net = sctp_findnet(stcb, (struct sockaddr *)&encaps->sue_address);
3918 /* We increment here since sctp_findassociation_ep_addr() wil
3919 * do a decrement if it finds the stcb as long as the locked
3920 * tcb (last argument) is NOT a TCB.. aka NULL.
3923 SCTP_INP_INCR_REF(inp);
3924 stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&encaps->sue_address, &net, NULL, NULL);
3926 SCTP_INP_DECR_REF(inp);
3929 if (stcb && (net == NULL)) {
3930 struct sockaddr *sa;
3932 sa = (struct sockaddr *)&encaps->sue_address;
3934 if (sa->sa_family == AF_INET) {
3935 struct sockaddr_in *sin;
3937 sin = (struct sockaddr_in *)sa;
3938 if (sin->sin_addr.s_addr) {
3940 SCTP_TCB_UNLOCK(stcb);
3941 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3947 if (sa->sa_family == AF_INET6) {
3948 struct sockaddr_in6 *sin6;
3950 sin6 = (struct sockaddr_in6 *)sa;
3951 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
3953 SCTP_TCB_UNLOCK(stcb);
3954 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3959 #if defined(__Userspace__)
3960 if (sa->sa_family == AF_CONN) {
3961 struct sockaddr_conn *sconn;
3963 sconn = (struct sockaddr_conn *)sa;
3964 if (sconn->sconn_addr != NULL) {
3966 SCTP_TCB_UNLOCK(stcb);
3967 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3973 error = EAFNOSUPPORT;
3974 SCTP_TCB_UNLOCK(stcb);
3975 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3982 encaps->sue_port = net->port;
3984 encaps->sue_port = stcb->asoc.port;
3986 SCTP_TCB_UNLOCK(stcb);
3988 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3989 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3990 (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC)) {
3991 SCTP_INP_RLOCK(inp);
3992 encaps->sue_port = inp->sctp_ep.port;
3993 SCTP_INP_RUNLOCK(inp);
3995 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4000 *optsize = sizeof(struct sctp_udpencaps);
4004 case SCTP_ENABLE_STREAM_RESET:
4006 struct sctp_assoc_value *av;
4008 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
4009 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4012 av->assoc_value = (uint32_t)stcb->asoc.local_strreset_support;
4013 SCTP_TCB_UNLOCK(stcb);
4015 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4016 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4017 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
4018 SCTP_INP_RLOCK(inp);
4019 av->assoc_value = (uint32_t)inp->local_strreset_support;
4020 SCTP_INP_RUNLOCK(inp);
4022 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4027 *optsize = sizeof(struct sctp_assoc_value);
4032 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
4033 error = ENOPROTOOPT;
4035 } /* end switch (sopt->sopt_name) */
4042 #if defined(__Panda__) || defined(__Userspace__)
4047 sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
4052 struct sctp_tcb *stcb = NULL;
4053 struct sctp_inpcb *inp = NULL;
4056 if (optval == NULL) {
4057 SCTP_PRINTF("optval is NULL\n");
4058 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4061 inp = (struct sctp_inpcb *)so->so_pcb;
4063 SCTP_PRINTF("inp is NULL?\n");
4064 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4067 vrf_id = inp->def_vrf_id;
4072 case SCTP_AUTOCLOSE:
4073 case SCTP_AUTO_ASCONF:
4074 case SCTP_EXPLICIT_EOR:
4075 case SCTP_DISABLE_FRAGMENTS:
4076 case SCTP_USE_EXT_RCVINFO:
4077 case SCTP_I_WANT_MAPPED_V4_ADDR:
4078 /* copy in the option value */
4079 SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
4084 case SCTP_DISABLE_FRAGMENTS:
4085 set_opt = SCTP_PCB_FLAGS_NO_FRAGMENT;
4087 case SCTP_AUTO_ASCONF:
4089 * NOTE: we don't really support this flag
4091 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
4092 /* only valid for bound all sockets */
4093 if ((SCTP_BASE_SYSCTL(sctp_auto_asconf) == 0) &&
4095 /* forbidden by admin */
4096 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EPERM);
4099 set_opt = SCTP_PCB_FLAGS_AUTO_ASCONF;
4101 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4105 case SCTP_EXPLICIT_EOR:
4106 set_opt = SCTP_PCB_FLAGS_EXPLICIT_EOR;
4108 case SCTP_USE_EXT_RCVINFO:
4109 set_opt = SCTP_PCB_FLAGS_EXT_RCVINFO;
4111 case SCTP_I_WANT_MAPPED_V4_ADDR:
4112 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
4113 set_opt = SCTP_PCB_FLAGS_NEEDS_MAPPED_V4;
4115 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4120 set_opt = SCTP_PCB_FLAGS_NODELAY;
4122 case SCTP_AUTOCLOSE:
4123 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4124 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
4125 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4128 set_opt = SCTP_PCB_FLAGS_AUTOCLOSE;
4130 * The value is in ticks. Note this does not effect
4131 * old associations, only new ones.
4133 inp->sctp_ep.auto_close_time = SEC_TO_TICKS(*mopt);
4136 SCTP_INP_WLOCK(inp);
4138 sctp_feature_on(inp, set_opt);
4140 sctp_feature_off(inp, set_opt);
4142 SCTP_INP_WUNLOCK(inp);
4144 case SCTP_REUSE_PORT:
4146 SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
4147 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) {
4148 /* Can't set it after we are bound */
4152 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
4153 /* Can't do this for a 1-m socket */
4158 sctp_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE);
4160 sctp_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE);
4163 case SCTP_PARTIAL_DELIVERY_POINT:
4167 SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
4168 if (*value > SCTP_SB_LIMIT_RCV(so)) {
4169 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4173 inp->partial_delivery_point = *value;
4176 case SCTP_FRAGMENT_INTERLEAVE:
4177 /* not yet until we re-write sctp_recvmsg() */
4181 SCTP_CHECK_AND_CAST(level, optval, uint32_t, optsize);
4182 if (*level == SCTP_FRAG_LEVEL_2) {
4183 sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
4184 sctp_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
4185 } else if (*level == SCTP_FRAG_LEVEL_1) {
4186 sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
4187 sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
4188 } else if (*level == SCTP_FRAG_LEVEL_0) {
4189 sctp_feature_off(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
4190 sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
4193 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4198 case SCTP_CMT_ON_OFF:
4199 if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
4200 struct sctp_assoc_value *av;
4202 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4203 if (av->assoc_value > SCTP_CMT_MAX) {
4204 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4208 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4210 stcb->asoc.sctp_cmt_on_off = av->assoc_value;
4211 SCTP_TCB_UNLOCK(stcb);
4213 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4214 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4215 (av->assoc_id == SCTP_FUTURE_ASSOC) ||
4216 (av->assoc_id == SCTP_ALL_ASSOC)) {
4217 SCTP_INP_WLOCK(inp);
4218 inp->sctp_cmt_on_off = av->assoc_value;
4219 SCTP_INP_WUNLOCK(inp);
4221 if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4222 (av->assoc_id == SCTP_ALL_ASSOC)) {
4223 SCTP_INP_RLOCK(inp);
4224 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4225 SCTP_TCB_LOCK(stcb);
4226 stcb->asoc.sctp_cmt_on_off = av->assoc_value;
4227 SCTP_TCB_UNLOCK(stcb);
4229 SCTP_INP_RUNLOCK(inp);
4233 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
4234 error = ENOPROTOOPT;
4237 case SCTP_PLUGGABLE_CC:
4239 struct sctp_assoc_value *av;
4240 struct sctp_nets *net;
4242 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4243 if ((av->assoc_value != SCTP_CC_RFC2581) &&
4244 (av->assoc_value != SCTP_CC_HSTCP) &&
4245 (av->assoc_value != SCTP_CC_HTCP) &&
4246 (av->assoc_value != SCTP_CC_RTCC)) {
4247 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4251 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4253 stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
4254 stcb->asoc.congestion_control_module = av->assoc_value;
4255 if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
4256 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4257 stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
4260 SCTP_TCB_UNLOCK(stcb);
4262 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4263 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4264 (av->assoc_id == SCTP_FUTURE_ASSOC) ||
4265 (av->assoc_id == SCTP_ALL_ASSOC)) {
4266 SCTP_INP_WLOCK(inp);
4267 inp->sctp_ep.sctp_default_cc_module = av->assoc_value;
4268 SCTP_INP_WUNLOCK(inp);
4270 if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4271 (av->assoc_id == SCTP_ALL_ASSOC)) {
4272 SCTP_INP_RLOCK(inp);
4273 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4274 SCTP_TCB_LOCK(stcb);
4275 stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
4276 stcb->asoc.congestion_control_module = av->assoc_value;
4277 if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
4278 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4279 stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
4282 SCTP_TCB_UNLOCK(stcb);
4284 SCTP_INP_RUNLOCK(inp);
4289 case SCTP_CC_OPTION:
4291 struct sctp_cc_option *cc_opt;
4293 SCTP_CHECK_AND_CAST(cc_opt, optval, struct sctp_cc_option, optsize);
4294 SCTP_FIND_STCB(inp, stcb, cc_opt->aid_value.assoc_id);
4296 if (cc_opt->aid_value.assoc_id == SCTP_CURRENT_ASSOC) {
4297 SCTP_INP_RLOCK(inp);
4298 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4299 SCTP_TCB_LOCK(stcb);
4300 if (stcb->asoc.cc_functions.sctp_cwnd_socket_option) {
4301 (*stcb->asoc.cc_functions.sctp_cwnd_socket_option)(stcb, 1, cc_opt);
4303 SCTP_TCB_UNLOCK(stcb);
4305 SCTP_INP_RUNLOCK(inp);
4310 if (stcb->asoc.cc_functions.sctp_cwnd_socket_option == NULL) {
4313 error = (*stcb->asoc.cc_functions.sctp_cwnd_socket_option)(stcb, 1,
4316 SCTP_TCB_UNLOCK(stcb);
4320 case SCTP_PLUGGABLE_SS:
4322 struct sctp_assoc_value *av;
4324 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4325 if ((av->assoc_value != SCTP_SS_DEFAULT) &&
4326 (av->assoc_value != SCTP_SS_ROUND_ROBIN) &&
4327 (av->assoc_value != SCTP_SS_ROUND_ROBIN_PACKET) &&
4328 (av->assoc_value != SCTP_SS_PRIORITY) &&
4329 (av->assoc_value != SCTP_SS_FAIR_BANDWITH) &&
4330 (av->assoc_value != SCTP_SS_FIRST_COME)) {
4331 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4335 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4337 stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1);
4338 stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
4339 stcb->asoc.stream_scheduling_module = av->assoc_value;
4340 stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
4341 SCTP_TCB_UNLOCK(stcb);
4343 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4344 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4345 (av->assoc_id == SCTP_FUTURE_ASSOC) ||
4346 (av->assoc_id == SCTP_ALL_ASSOC)) {
4347 SCTP_INP_WLOCK(inp);
4348 inp->sctp_ep.sctp_default_ss_module = av->assoc_value;
4349 SCTP_INP_WUNLOCK(inp);
4351 if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4352 (av->assoc_id == SCTP_ALL_ASSOC)) {
4353 SCTP_INP_RLOCK(inp);
4354 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4355 SCTP_TCB_LOCK(stcb);
4356 stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1);
4357 stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
4358 stcb->asoc.stream_scheduling_module = av->assoc_value;
4359 stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
4360 SCTP_TCB_UNLOCK(stcb);
4362 SCTP_INP_RUNLOCK(inp);
4369 struct sctp_stream_value *av;
4371 SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, optsize);
4372 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4374 if (stcb->asoc.ss_functions.sctp_ss_set_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id],
4375 av->stream_value) < 0) {
4376 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4379 SCTP_TCB_UNLOCK(stcb);
4381 if (av->assoc_id == SCTP_CURRENT_ASSOC) {
4382 SCTP_INP_RLOCK(inp);
4383 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4384 SCTP_TCB_LOCK(stcb);
4385 stcb->asoc.ss_functions.sctp_ss_set_value(stcb,
4387 &stcb->asoc.strmout[av->stream_id],
4389 SCTP_TCB_UNLOCK(stcb);
4391 SCTP_INP_RUNLOCK(inp);
4394 /* Can't set stream value without association */
4395 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4401 case SCTP_CLR_STAT_LOG:
4402 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4407 struct sctp_assoc_value *av;
4409 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4410 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4413 stcb->asoc.context = av->assoc_value;
4414 SCTP_TCB_UNLOCK(stcb);
4416 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4417 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4418 (av->assoc_id == SCTP_FUTURE_ASSOC) ||
4419 (av->assoc_id == SCTP_ALL_ASSOC)) {
4420 SCTP_INP_WLOCK(inp);
4421 inp->sctp_context = av->assoc_value;
4422 SCTP_INP_WUNLOCK(inp);
4424 if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4425 (av->assoc_id == SCTP_ALL_ASSOC)) {
4426 SCTP_INP_RLOCK(inp);
4427 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4428 SCTP_TCB_LOCK(stcb);
4429 stcb->asoc.context = av->assoc_value;
4430 SCTP_TCB_UNLOCK(stcb);
4432 SCTP_INP_RUNLOCK(inp);
4439 uint32_t *default_vrfid;
4443 SCTP_CHECK_AND_CAST(default_vrfid, optval, uint32_t, optsize);
4444 if (*default_vrfid > SCTP_MAX_VRF_ID) {
4445 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4450 for (i = 0; i < inp->num_vrfs; i++) {
4451 /* The VRF must be in the VRF list */
4452 if (*default_vrfid == inp->m_vrf_ids[i]) {
4453 SCTP_INP_WLOCK(inp);
4454 inp->def_vrf_id = *default_vrfid;
4455 SCTP_INP_WUNLOCK(inp);
4459 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4462 inp->def_vrf_id = *default_vrfid;
4469 case SCTP_DEL_VRF_ID:
4472 uint32_t *del_vrfid;
4475 SCTP_CHECK_AND_CAST(del_vrfid, optval, uint32_t, optsize);
4476 if (*del_vrfid > SCTP_MAX_VRF_ID) {
4477 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4481 if (inp->num_vrfs == 1) {
4482 /* Can't delete last one */
4483 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4487 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) {
4488 /* Can't add more once you are bound */
4489 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4493 SCTP_INP_WLOCK(inp);
4494 for (i = 0; i < inp->num_vrfs; i++) {
4495 if (*del_vrfid == inp->m_vrf_ids[i]) {
4501 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4505 if (i != (inp->num_vrfs - 1)) {
4506 /* Take bottom one and move to this slot */
4507 inp->m_vrf_ids[i] = inp->m_vrf_ids[(inp->num_vrfs-1)];
4509 if (*del_vrfid == inp->def_vrf_id) {
4510 /* Take the first one as the new default */
4511 inp->def_vrf_id = inp->m_vrf_ids[0];
4513 /* Drop the number by one killing last one */
4516 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4521 case SCTP_ADD_VRF_ID:
4524 uint32_t *add_vrfid;
4527 SCTP_CHECK_AND_CAST(add_vrfid, optval, uint32_t, optsize);
4528 if (*add_vrfid > SCTP_MAX_VRF_ID) {
4529 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4533 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) {
4534 /* Can't add more once you are bound */
4535 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4539 SCTP_INP_WLOCK(inp);
4540 /* Verify its not already here */
4541 for (i = 0; i < inp->num_vrfs; i++) {
4542 if (*add_vrfid == inp->m_vrf_ids[i]) {
4543 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4545 SCTP_INP_WUNLOCK(inp);
4549 if ((inp->num_vrfs + 1) > inp->vrf_size) {
4550 /* need to grow array */
4552 SCTP_MALLOC(tarray, uint32_t *,
4553 (sizeof(uint32_t) * (inp->vrf_size + SCTP_DEFAULT_VRF_SIZE)),
4555 if (tarray == NULL) {
4556 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4558 SCTP_INP_WUNLOCK(inp);
4561 memcpy(tarray, inp->m_vrf_ids, (sizeof(uint32_t) * inp->vrf_size));
4562 SCTP_FREE(inp->m_vrf_ids, SCTP_M_MVRF);
4563 inp->m_vrf_ids = tarray;
4564 inp->vrf_size += SCTP_DEFAULT_VRF_SIZE;
4566 inp->m_vrf_ids[inp->num_vrfs] = *add_vrfid;
4568 SCTP_INP_WUNLOCK(inp);
4570 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4575 case SCTP_DELAYED_SACK:
4577 struct sctp_sack_info *sack;
4579 SCTP_CHECK_AND_CAST(sack, optval, struct sctp_sack_info, optsize);
4580 SCTP_FIND_STCB(inp, stcb, sack->sack_assoc_id);
4581 if (sack->sack_delay) {
4582 if (sack->sack_delay > SCTP_MAX_SACK_DELAY)
4583 sack->sack_delay = SCTP_MAX_SACK_DELAY;
4584 if (MSEC_TO_TICKS(sack->sack_delay) < 1) {
4585 sack->sack_delay = TICKS_TO_MSEC(1);
4589 if (sack->sack_delay) {
4590 stcb->asoc.delayed_ack = sack->sack_delay;
4592 if (sack->sack_freq) {
4593 stcb->asoc.sack_freq = sack->sack_freq;
4595 SCTP_TCB_UNLOCK(stcb);
4597 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4598 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4599 (sack->sack_assoc_id == SCTP_FUTURE_ASSOC) ||
4600 (sack->sack_assoc_id == SCTP_ALL_ASSOC)) {
4601 SCTP_INP_WLOCK(inp);
4602 if (sack->sack_delay) {
4603 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV] = MSEC_TO_TICKS(sack->sack_delay);
4605 if (sack->sack_freq) {
4606 inp->sctp_ep.sctp_sack_freq = sack->sack_freq;
4608 SCTP_INP_WUNLOCK(inp);
4610 if ((sack->sack_assoc_id == SCTP_CURRENT_ASSOC) ||
4611 (sack->sack_assoc_id == SCTP_ALL_ASSOC)) {
4612 SCTP_INP_RLOCK(inp);
4613 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4614 SCTP_TCB_LOCK(stcb);
4615 if (sack->sack_delay) {
4616 stcb->asoc.delayed_ack = sack->sack_delay;
4618 if (sack->sack_freq) {
4619 stcb->asoc.sack_freq = sack->sack_freq;
4621 SCTP_TCB_UNLOCK(stcb);
4623 SCTP_INP_RUNLOCK(inp);
4628 case SCTP_AUTH_CHUNK:
4630 struct sctp_authchunk *sauth;
4632 SCTP_CHECK_AND_CAST(sauth, optval, struct sctp_authchunk, optsize);
4634 SCTP_INP_WLOCK(inp);
4635 if (sctp_auth_add_chunk(sauth->sauth_chunk, inp->sctp_ep.local_auth_chunks)) {
4636 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4639 SCTP_INP_WUNLOCK(inp);
4644 struct sctp_authkey *sca;
4645 struct sctp_keyhead *shared_keys;
4646 sctp_sharedkey_t *shared_key;
4647 sctp_key_t *key = NULL;
4650 SCTP_CHECK_AND_CAST(sca, optval, struct sctp_authkey, optsize);
4651 if (sca->sca_keylength == 0) {
4652 size = optsize - sizeof(struct sctp_authkey);
4654 if (sca->sca_keylength + sizeof(struct sctp_authkey) <= optsize) {
4655 size = sca->sca_keylength;
4657 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4662 SCTP_FIND_STCB(inp, stcb, sca->sca_assoc_id);
4665 shared_keys = &stcb->asoc.shared_keys;
4666 /* clear the cached keys for this key id */
4667 sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
4669 * create the new shared key and
4673 key = sctp_set_key(sca->sca_key, (uint32_t) size);
4675 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4677 SCTP_TCB_UNLOCK(stcb);
4681 shared_key = sctp_alloc_sharedkey();
4682 if (shared_key == NULL) {
4684 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4686 SCTP_TCB_UNLOCK(stcb);
4689 shared_key->key = key;
4690 shared_key->keyid = sca->sca_keynumber;
4691 error = sctp_insert_sharedkey(shared_keys, shared_key);
4692 SCTP_TCB_UNLOCK(stcb);
4694 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4695 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4696 (sca->sca_assoc_id == SCTP_FUTURE_ASSOC) ||
4697 (sca->sca_assoc_id == SCTP_ALL_ASSOC)) {
4698 SCTP_INP_WLOCK(inp);
4699 shared_keys = &inp->sctp_ep.shared_keys;
4701 * clear the cached keys on all assocs for
4704 sctp_clear_cachedkeys_ep(inp, sca->sca_keynumber);
4706 * create the new shared key and
4710 key = sctp_set_key(sca->sca_key, (uint32_t) size);
4712 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4714 SCTP_INP_WUNLOCK(inp);
4718 shared_key = sctp_alloc_sharedkey();
4719 if (shared_key == NULL) {
4721 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4723 SCTP_INP_WUNLOCK(inp);
4726 shared_key->key = key;
4727 shared_key->keyid = sca->sca_keynumber;
4728 error = sctp_insert_sharedkey(shared_keys, shared_key);
4729 SCTP_INP_WUNLOCK(inp);
4731 if ((sca->sca_assoc_id == SCTP_CURRENT_ASSOC) ||
4732 (sca->sca_assoc_id == SCTP_ALL_ASSOC)) {
4733 SCTP_INP_RLOCK(inp);
4734 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4735 SCTP_TCB_LOCK(stcb);
4736 shared_keys = &stcb->asoc.shared_keys;
4737 /* clear the cached keys for this key id */
4738 sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
4740 * create the new shared key and
4744 key = sctp_set_key(sca->sca_key, (uint32_t) size);
4746 SCTP_TCB_UNLOCK(stcb);
4750 shared_key = sctp_alloc_sharedkey();
4751 if (shared_key == NULL) {
4753 SCTP_TCB_UNLOCK(stcb);
4756 shared_key->key = key;
4757 shared_key->keyid = sca->sca_keynumber;
4758 error = sctp_insert_sharedkey(shared_keys, shared_key);
4759 SCTP_TCB_UNLOCK(stcb);
4761 SCTP_INP_RUNLOCK(inp);
4766 case SCTP_HMAC_IDENT:
4768 struct sctp_hmacalgo *shmac;
4769 sctp_hmaclist_t *hmaclist;
4773 SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, optsize);
4774 if (optsize < sizeof(struct sctp_hmacalgo) + shmac->shmac_number_of_idents * sizeof(uint16_t)) {
4775 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4780 hmaclist = sctp_alloc_hmaclist(shmac->shmac_number_of_idents);
4781 if (hmaclist == NULL) {
4782 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4786 for (i = 0; i < shmac->shmac_number_of_idents; i++) {
4787 hmacid = shmac->shmac_idents[i];
4788 if (sctp_auth_add_hmacid(hmaclist, hmacid)) {
4789 /* invalid HMACs were found */;
4790 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4792 sctp_free_hmaclist(hmaclist);
4793 goto sctp_set_hmac_done;
4796 for (i = 0; i < hmaclist->num_algo; i++) {
4797 if (hmaclist->hmac[i] == SCTP_AUTH_HMAC_ID_SHA1) {
4798 /* already in list */
4802 if (i == hmaclist->num_algo) {
4803 /* not found in list */
4804 sctp_free_hmaclist(hmaclist);
4805 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4809 /* set it on the endpoint */
4810 SCTP_INP_WLOCK(inp);
4811 if (inp->sctp_ep.local_hmacs)
4812 sctp_free_hmaclist(inp->sctp_ep.local_hmacs);
4813 inp->sctp_ep.local_hmacs = hmaclist;
4814 SCTP_INP_WUNLOCK(inp);
4818 case SCTP_AUTH_ACTIVE_KEY:
4820 struct sctp_authkeyid *scact;
4822 SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, optsize);
4823 SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id);
4825 /* set the active key on the right place */
4827 /* set the active key on the assoc */
4828 if (sctp_auth_setactivekey(stcb,
4829 scact->scact_keynumber)) {
4830 SCTP_LTRACE_ERR_RET(inp, NULL, NULL,
4831 SCTP_FROM_SCTP_USRREQ,
4835 SCTP_TCB_UNLOCK(stcb);
4837 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4838 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4839 (scact->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
4840 (scact->scact_assoc_id == SCTP_ALL_ASSOC)) {
4841 SCTP_INP_WLOCK(inp);
4842 if (sctp_auth_setactivekey_ep(inp, scact->scact_keynumber)) {
4843 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4846 SCTP_INP_WUNLOCK(inp);
4848 if ((scact->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
4849 (scact->scact_assoc_id == SCTP_ALL_ASSOC)) {
4850 SCTP_INP_RLOCK(inp);
4851 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4852 SCTP_TCB_LOCK(stcb);
4853 sctp_auth_setactivekey(stcb, scact->scact_keynumber);
4854 SCTP_TCB_UNLOCK(stcb);
4856 SCTP_INP_RUNLOCK(inp);
4861 case SCTP_AUTH_DELETE_KEY:
4863 struct sctp_authkeyid *scdel;
4865 SCTP_CHECK_AND_CAST(scdel, optval, struct sctp_authkeyid, optsize);
4866 SCTP_FIND_STCB(inp, stcb, scdel->scact_assoc_id);
4868 /* delete the key from the right place */
4870 if (sctp_delete_sharedkey(stcb, scdel->scact_keynumber)) {
4871 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4874 SCTP_TCB_UNLOCK(stcb);
4876 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4877 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4878 (scdel->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
4879 (scdel->scact_assoc_id == SCTP_ALL_ASSOC)) {
4880 SCTP_INP_WLOCK(inp);
4881 if (sctp_delete_sharedkey_ep(inp, scdel->scact_keynumber)) {
4882 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4885 SCTP_INP_WUNLOCK(inp);
4887 if ((scdel->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
4888 (scdel->scact_assoc_id == SCTP_ALL_ASSOC)) {
4889 SCTP_INP_RLOCK(inp);
4890 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4891 SCTP_TCB_LOCK(stcb);
4892 sctp_delete_sharedkey(stcb, scdel->scact_keynumber);
4893 SCTP_TCB_UNLOCK(stcb);
4895 SCTP_INP_RUNLOCK(inp);
4900 case SCTP_AUTH_DEACTIVATE_KEY:
4902 struct sctp_authkeyid *keyid;
4904 SCTP_CHECK_AND_CAST(keyid, optval, struct sctp_authkeyid, optsize);
4905 SCTP_FIND_STCB(inp, stcb, keyid->scact_assoc_id);
4907 /* deactivate the key from the right place */
4909 if (sctp_deact_sharedkey(stcb, keyid->scact_keynumber)) {
4910 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4913 SCTP_TCB_UNLOCK(stcb);
4915 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4916 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4917 (keyid->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
4918 (keyid->scact_assoc_id == SCTP_ALL_ASSOC)) {
4919 SCTP_INP_WLOCK(inp);
4920 if (sctp_deact_sharedkey_ep(inp, keyid->scact_keynumber)) {
4921 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4924 SCTP_INP_WUNLOCK(inp);
4926 if ((keyid->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
4927 (keyid->scact_assoc_id == SCTP_ALL_ASSOC)) {
4928 SCTP_INP_RLOCK(inp);
4929 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4930 SCTP_TCB_LOCK(stcb);
4931 sctp_deact_sharedkey(stcb, keyid->scact_keynumber);
4932 SCTP_TCB_UNLOCK(stcb);
4934 SCTP_INP_RUNLOCK(inp);
4939 case SCTP_ENABLE_STREAM_RESET:
4941 struct sctp_assoc_value *av;
4943 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4944 if (av->assoc_value & (~SCTP_ENABLE_VALUE_MASK)) {
4945 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4949 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4951 stcb->asoc.local_strreset_support = (uint8_t)av->assoc_value;
4952 SCTP_TCB_UNLOCK(stcb);
4954 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4955 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4956 (av->assoc_id == SCTP_FUTURE_ASSOC) ||
4957 (av->assoc_id == SCTP_ALL_ASSOC)) {
4958 SCTP_INP_WLOCK(inp);
4959 inp->local_strreset_support = (uint8_t)av->assoc_value;
4960 SCTP_INP_WUNLOCK(inp);
4962 if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4963 (av->assoc_id == SCTP_ALL_ASSOC)) {
4964 SCTP_INP_RLOCK(inp);
4965 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4966 SCTP_TCB_LOCK(stcb);
4967 stcb->asoc.local_strreset_support = (uint8_t)av->assoc_value;
4968 SCTP_TCB_UNLOCK(stcb);
4970 SCTP_INP_RUNLOCK(inp);
4976 case SCTP_RESET_STREAMS:
4978 struct sctp_reset_streams *strrst;
4979 int i, send_out = 0;
4982 SCTP_CHECK_AND_CAST(strrst, optval, struct sctp_reset_streams, optsize);
4983 SCTP_FIND_STCB(inp, stcb, strrst->srs_assoc_id);
4985 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4989 if (stcb->asoc.peer_supports_strreset == 0) {
4991 * Peer does not support the chunk type.
4993 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4995 SCTP_TCB_UNLOCK(stcb);
4998 if (stcb->asoc.stream_reset_outstanding) {
4999 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
5001 SCTP_TCB_UNLOCK(stcb);
5004 if (strrst->srs_flags & SCTP_STREAM_RESET_INCOMING) {
5007 if (strrst->srs_flags & SCTP_STREAM_RESET_OUTGOING) {
5010 if ((send_in == 0) && (send_out == 0)) {
5011 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5013 SCTP_TCB_UNLOCK(stcb);
5016 for (i = 0; i < strrst->srs_number_streams; i++) {
5018 (strrst->srs_stream_list[i] > stcb->asoc.streamincnt)) {
5019 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5024 (strrst->srs_stream_list[i] > stcb->asoc.streamoutcnt)) {
5025 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5031 SCTP_TCB_UNLOCK(stcb);
5034 error = sctp_send_str_reset_req(stcb, strrst->srs_number_streams,
5035 strrst->srs_stream_list,
5036 send_out, send_in, 0, 0, 0, 0, 0);
5038 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
5039 SCTP_TCB_UNLOCK(stcb);
5042 case SCTP_ADD_STREAMS:
5044 struct sctp_add_streams *stradd;
5045 uint8_t addstream = 0;
5046 uint16_t add_o_strmcnt = 0;
5047 uint16_t add_i_strmcnt = 0;
5049 SCTP_CHECK_AND_CAST(stradd, optval, struct sctp_add_streams, optsize);
5050 SCTP_FIND_STCB(inp, stcb, stradd->sas_assoc_id);
5052 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
5056 if (stcb->asoc.peer_supports_strreset == 0) {
5058 * Peer does not support the chunk type.
5060 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
5062 SCTP_TCB_UNLOCK(stcb);
5065 if (stcb->asoc.stream_reset_outstanding) {
5066 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
5068 SCTP_TCB_UNLOCK(stcb);
5071 if ((stradd->sas_outstrms == 0) &&
5072 (stradd->sas_instrms == 0)) {
5076 if (stradd->sas_outstrms) {
5078 /* We allocate here */
5079 add_o_strmcnt = stradd->sas_outstrms;
5080 if ((((int)add_o_strmcnt) + ((int)stcb->asoc.streamoutcnt)) > 0x0000ffff) {
5081 /* You can't have more than 64k */
5086 if (stradd->sas_instrms) {
5090 /* We allocate inside sctp_send_str_reset_req() */
5091 add_i_strmcnt = stradd->sas_instrms;
5092 cnt = add_i_strmcnt;
5093 cnt += stcb->asoc.streamincnt;
5094 if (cnt > 0x0000ffff) {
5095 /* You can't have more than 64k */
5099 if (cnt > (int)stcb->asoc.max_inbound_streams) {
5100 /* More than you are allowed */
5105 error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 0, addstream, add_o_strmcnt, add_i_strmcnt, 0);
5106 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
5108 SCTP_TCB_UNLOCK(stcb);
5111 case SCTP_RESET_ASSOC:
5115 SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
5116 SCTP_FIND_STCB(inp, stcb, (sctp_assoc_t) *value);
5118 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
5122 if (stcb->asoc.peer_supports_strreset == 0) {
5124 * Peer does not support the chunk type.
5126 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
5128 SCTP_TCB_UNLOCK(stcb);
5131 if (stcb->asoc.stream_reset_outstanding) {
5132 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
5134 SCTP_TCB_UNLOCK(stcb);
5137 error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 1, 0, 0, 0, 0);
5138 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
5139 SCTP_TCB_UNLOCK(stcb);
5142 case SCTP_CONNECT_X:
5143 if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
5144 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5148 error = sctp_do_connect_x(so, inp, optval, optsize, p, 0);
5150 case SCTP_CONNECT_X_DELAYED:
5151 if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
5152 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5156 error = sctp_do_connect_x(so, inp, optval, optsize, p, 1);
5158 case SCTP_CONNECT_X_COMPLETE:
5160 struct sockaddr *sa;
5161 struct sctp_nets *net;
5163 /* FIXME MT: check correct? */
5164 SCTP_CHECK_AND_CAST(sa, optval, struct sockaddr, optsize);
5167 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
5168 SCTP_INP_RLOCK(inp);
5169 stcb = LIST_FIRST(&inp->sctp_asoc_list);
5171 SCTP_TCB_LOCK(stcb);
5172 net = sctp_findnet(stcb, sa);
5174 SCTP_INP_RUNLOCK(inp);
5176 /* We increment here since sctp_findassociation_ep_addr() wil
5177 * do a decrement if it finds the stcb as long as the locked
5178 * tcb (last argument) is NOT a TCB.. aka NULL.
5180 SCTP_INP_INCR_REF(inp);
5181 stcb = sctp_findassociation_ep_addr(&inp, sa, &net, NULL, NULL);
5183 SCTP_INP_DECR_REF(inp);
5188 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
5192 if (stcb->asoc.delayed_connection == 1) {
5193 stcb->asoc.delayed_connection = 0;
5194 (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
5195 sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb,
5196 stcb->asoc.primary_destination,
5197 SCTP_FROM_SCTP_USRREQ+SCTP_LOC_9);
5198 sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
5201 * already expired or did not use delayed
5204 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
5207 SCTP_TCB_UNLOCK(stcb);
5210 case SCTP_MAX_BURST:
5212 #if defined(__FreeBSD__) && __FreeBSD_version < 900000
5215 SCTP_CHECK_AND_CAST(burst, optval, uint8_t, optsize);
5217 SCTP_INP_WLOCK(inp);
5218 inp->sctp_ep.max_burst = *burst;
5219 SCTP_INP_WUNLOCK(inp);
5221 struct sctp_assoc_value *av;
5223 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
5224 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
5227 stcb->asoc.max_burst = av->assoc_value;
5228 SCTP_TCB_UNLOCK(stcb);
5230 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5231 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5232 (av->assoc_id == SCTP_FUTURE_ASSOC) ||
5233 (av->assoc_id == SCTP_ALL_ASSOC)) {
5234 SCTP_INP_WLOCK(inp);
5235 inp->sctp_ep.max_burst = av->assoc_value;
5236 SCTP_INP_WUNLOCK(inp);
5238 if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
5239 (av->assoc_id == SCTP_ALL_ASSOC)) {
5240 SCTP_INP_RLOCK(inp);
5241 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5242 SCTP_TCB_LOCK(stcb);
5243 stcb->asoc.max_burst = av->assoc_value;
5244 SCTP_TCB_UNLOCK(stcb);
5246 SCTP_INP_RUNLOCK(inp);
5254 struct sctp_assoc_value *av;
5257 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
5258 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
5260 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
5261 ovh = SCTP_MED_OVERHEAD;
5263 ovh = SCTP_MED_V4_OVERHEAD;
5266 if (av->assoc_value) {
5267 stcb->asoc.sctp_frag_point = (av->assoc_value + ovh);
5269 stcb->asoc.sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
5271 SCTP_TCB_UNLOCK(stcb);
5273 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5274 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5275 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
5276 SCTP_INP_WLOCK(inp);
5277 /* FIXME MT: I think this is not in tune with the API ID */
5278 if (av->assoc_value) {
5279 inp->sctp_frag_point = (av->assoc_value + ovh);
5281 inp->sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
5283 SCTP_INP_WUNLOCK(inp);
5285 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5293 struct sctp_event_subscribe *events;
5295 SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, optsize);
5297 SCTP_INP_WLOCK(inp);
5298 if (events->sctp_data_io_event) {
5299 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
5301 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
5304 if (events->sctp_association_event) {
5305 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
5307 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
5310 if (events->sctp_address_event) {
5311 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
5313 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
5316 if (events->sctp_send_failure_event) {
5317 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
5319 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
5322 if (events->sctp_peer_error_event) {
5323 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPEERERR);
5325 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPEERERR);
5328 if (events->sctp_shutdown_event) {
5329 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
5331 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
5334 if (events->sctp_partial_delivery_event) {
5335 sctp_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
5337 sctp_feature_off(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
5340 if (events->sctp_adaptation_layer_event) {
5341 sctp_feature_on(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
5343 sctp_feature_off(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
5346 if (events->sctp_authentication_event) {
5347 sctp_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT);
5349 sctp_feature_off(inp, SCTP_PCB_FLAGS_AUTHEVNT);
5352 if (events->sctp_sender_dry_event) {
5353 sctp_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT);
5355 sctp_feature_off(inp, SCTP_PCB_FLAGS_DRYEVNT);
5358 if (events->sctp_stream_reset_event) {
5359 sctp_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
5361 sctp_feature_off(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
5363 SCTP_INP_WUNLOCK(inp);
5365 SCTP_INP_RLOCK(inp);
5366 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5367 SCTP_TCB_LOCK(stcb);
5368 if (events->sctp_association_event) {
5369 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
5371 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
5373 if (events->sctp_address_event) {
5374 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
5376 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
5378 if (events->sctp_send_failure_event) {
5379 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
5381 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
5383 if (events->sctp_peer_error_event) {
5384 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
5386 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
5388 if (events->sctp_shutdown_event) {
5389 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
5391 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
5393 if (events->sctp_partial_delivery_event) {
5394 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
5396 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
5398 if (events->sctp_adaptation_layer_event) {
5399 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
5401 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
5403 if (events->sctp_authentication_event) {
5404 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
5406 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
5408 if (events->sctp_sender_dry_event) {
5409 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
5411 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
5413 if (events->sctp_stream_reset_event) {
5414 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
5416 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
5418 SCTP_TCB_UNLOCK(stcb);
5420 /* Send up the sender dry event only for 1-to-1 style sockets. */
5421 if (events->sctp_sender_dry_event) {
5422 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5423 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
5424 stcb = LIST_FIRST(&inp->sctp_asoc_list);
5426 SCTP_TCB_LOCK(stcb);
5427 if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
5428 TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
5429 (stcb->asoc.stream_queue_cnt == 0)) {
5430 sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_LOCKED);
5432 SCTP_TCB_UNLOCK(stcb);
5436 SCTP_INP_RUNLOCK(inp);
5439 case SCTP_ADAPTATION_LAYER:
5441 struct sctp_setadaptation *adap_bits;
5443 SCTP_CHECK_AND_CAST(adap_bits, optval, struct sctp_setadaptation, optsize);
5444 SCTP_INP_WLOCK(inp);
5445 inp->sctp_ep.adaptation_layer_indicator = adap_bits->ssb_adaptation_ind;
5446 inp->sctp_ep.adaptation_layer_indicator_provided = 1;
5447 SCTP_INP_WUNLOCK(inp);
5451 case SCTP_SET_INITIAL_DBG_SEQ:
5455 SCTP_CHECK_AND_CAST(vvv, optval, uint32_t, optsize);
5456 SCTP_INP_WLOCK(inp);
5457 inp->sctp_ep.initial_sequence_debug = *vvv;
5458 SCTP_INP_WUNLOCK(inp);
5462 case SCTP_DEFAULT_SEND_PARAM:
5464 struct sctp_sndrcvinfo *s_info;
5466 SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, optsize);
5467 SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
5470 if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
5471 memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
5473 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5476 SCTP_TCB_UNLOCK(stcb);
5478 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5479 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5480 (s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC) ||
5481 (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)) {
5482 SCTP_INP_WLOCK(inp);
5483 memcpy(&inp->def_send, s_info, min(optsize, sizeof(inp->def_send)));
5484 SCTP_INP_WUNLOCK(inp);
5486 if ((s_info->sinfo_assoc_id == SCTP_CURRENT_ASSOC) ||
5487 (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)) {
5488 SCTP_INP_RLOCK(inp);
5489 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5490 SCTP_TCB_LOCK(stcb);
5491 if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
5492 memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
5494 SCTP_TCB_UNLOCK(stcb);
5496 SCTP_INP_RUNLOCK(inp);
5501 case SCTP_PEER_ADDR_PARAMS:
5503 struct sctp_paddrparams *paddrp;
5504 struct sctp_nets *net;
5506 SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, optsize);
5507 SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
5510 net = sctp_findnet(stcb, (struct sockaddr *)&paddrp->spp_address);
5512 /* We increment here since sctp_findassociation_ep_addr() wil
5513 * do a decrement if it finds the stcb as long as the locked
5514 * tcb (last argument) is NOT a TCB.. aka NULL.
5516 SCTP_INP_INCR_REF(inp);
5517 stcb = sctp_findassociation_ep_addr(&inp,
5518 (struct sockaddr *)&paddrp->spp_address,
5521 SCTP_INP_DECR_REF(inp);
5524 if (stcb && (net == NULL)) {
5525 struct sockaddr *sa;
5527 sa = (struct sockaddr *)&paddrp->spp_address;
5529 if (sa->sa_family == AF_INET) {
5531 struct sockaddr_in *sin;
5532 sin = (struct sockaddr_in *)sa;
5533 if (sin->sin_addr.s_addr) {
5534 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5535 SCTP_TCB_UNLOCK(stcb);
5542 if (sa->sa_family == AF_INET6) {
5543 struct sockaddr_in6 *sin6;
5545 sin6 = (struct sockaddr_in6 *)sa;
5546 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
5547 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5548 SCTP_TCB_UNLOCK(stcb);
5554 #if defined(__Userspace__)
5555 if (sa->sa_family == AF_CONN) {
5556 struct sockaddr_conn *sconn;
5558 sconn = (struct sockaddr_conn *)sa;
5559 if (sconn->sconn_addr != NULL) {
5560 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5561 SCTP_TCB_UNLOCK(stcb);
5568 error = EAFNOSUPPORT;
5569 SCTP_TCB_UNLOCK(stcb);
5570 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
5575 if ((paddrp->spp_flags & SPP_HB_ENABLE) && (paddrp->spp_flags & SPP_HB_DISABLE)) {
5577 SCTP_TCB_UNLOCK(stcb);
5578 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5582 if ((paddrp->spp_flags & SPP_PMTUD_ENABLE) && (paddrp->spp_flags & SPP_PMTUD_DISABLE)) {
5584 SCTP_TCB_UNLOCK(stcb);
5585 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5590 /************************TCB SPECIFIC SET ******************/
5592 * do we change the timer for HB, we run
5597 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
5598 ovh = SCTP_MED_OVERHEAD;
5600 ovh = SCTP_MED_V4_OVERHEAD;
5603 /* network sets ? */
5605 /************************NET SPECIFIC SET ******************/
5606 if (paddrp->spp_flags & SPP_HB_DISABLE) {
5607 if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
5608 !(net->dest_state & SCTP_ADDR_NOHB)) {
5609 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
5610 SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
5612 net->dest_state |= SCTP_ADDR_NOHB;
5614 if (paddrp->spp_flags & SPP_HB_ENABLE) {
5615 if (paddrp->spp_hbinterval) {
5616 net->heart_beat_delay = paddrp->spp_hbinterval;
5617 } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
5618 net->heart_beat_delay = 0;
5620 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
5621 SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
5622 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
5623 net->dest_state &= ~SCTP_ADDR_NOHB;
5625 if (paddrp->spp_flags & SPP_HB_DEMAND) {
5627 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5628 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED);
5629 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
5631 if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
5632 if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
5633 sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
5634 SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
5636 net->dest_state |= SCTP_ADDR_NO_PMTUD;
5637 net->mtu = paddrp->spp_pathmtu + ovh;
5638 if (net->mtu < stcb->asoc.smallest_mtu) {
5639 sctp_pathmtu_adjustment(stcb, net->mtu);
5642 if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
5643 if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
5644 sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
5646 net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
5648 if (paddrp->spp_pathmaxrxt) {
5649 if (net->dest_state & SCTP_ADDR_PF) {
5650 if (net->error_count > paddrp->spp_pathmaxrxt) {
5651 net->dest_state &= ~SCTP_ADDR_PF;
5654 if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
5655 (net->error_count > net->pf_threshold)) {
5656 net->dest_state |= SCTP_ADDR_PF;
5657 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5658 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
5659 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
5662 if (net->dest_state & SCTP_ADDR_REACHABLE) {
5663 if (net->error_count > paddrp->spp_pathmaxrxt) {
5664 net->dest_state &= ~SCTP_ADDR_REACHABLE;
5665 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
5668 if (net->error_count <= paddrp->spp_pathmaxrxt) {
5669 net->dest_state |= SCTP_ADDR_REACHABLE;
5670 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
5673 net->failure_threshold = paddrp->spp_pathmaxrxt;
5675 if (paddrp->spp_flags & SPP_DSCP) {
5676 net->dscp = paddrp->spp_dscp & 0xfc;
5680 if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
5681 if (net->ro._l_addr.sa.sa_family == AF_INET6) {
5682 net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5683 net->flowlabel |= 0x80000000;
5688 /************************ASSOC ONLY -- NO NET SPECIFIC SET ******************/
5689 if (paddrp->spp_pathmaxrxt) {
5690 stcb->asoc.def_net_failure = paddrp->spp_pathmaxrxt;
5691 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5692 if (net->dest_state & SCTP_ADDR_PF) {
5693 if (net->error_count > paddrp->spp_pathmaxrxt) {
5694 net->dest_state &= ~SCTP_ADDR_PF;
5697 if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
5698 (net->error_count > net->pf_threshold)) {
5699 net->dest_state |= SCTP_ADDR_PF;
5700 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5701 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
5702 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
5705 if (net->dest_state & SCTP_ADDR_REACHABLE) {
5706 if (net->error_count > paddrp->spp_pathmaxrxt) {
5707 net->dest_state &= ~SCTP_ADDR_REACHABLE;
5708 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
5711 if (net->error_count <= paddrp->spp_pathmaxrxt) {
5712 net->dest_state |= SCTP_ADDR_REACHABLE;
5713 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
5716 net->failure_threshold = paddrp->spp_pathmaxrxt;
5720 if (paddrp->spp_flags & SPP_HB_ENABLE) {
5721 if (paddrp->spp_hbinterval) {
5722 stcb->asoc.heart_beat_delay = paddrp->spp_hbinterval;
5723 } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
5724 stcb->asoc.heart_beat_delay = 0;
5726 /* Turn back on the timer */
5727 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5728 if (paddrp->spp_hbinterval) {
5729 net->heart_beat_delay = paddrp->spp_hbinterval;
5730 } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
5731 net->heart_beat_delay = 0;
5733 if (net->dest_state & SCTP_ADDR_NOHB) {
5734 net->dest_state &= ~SCTP_ADDR_NOHB;
5736 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
5737 SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
5738 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
5740 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5742 if (paddrp->spp_flags & SPP_HB_DISABLE) {
5743 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5744 if (!(net->dest_state & SCTP_ADDR_NOHB)) {
5745 net->dest_state |= SCTP_ADDR_NOHB;
5746 if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED)) {
5747 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
5751 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5753 if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
5754 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5755 if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
5756 sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
5757 SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
5759 net->dest_state |= SCTP_ADDR_NO_PMTUD;
5760 net->mtu = paddrp->spp_pathmtu + ovh;
5761 if (net->mtu < stcb->asoc.smallest_mtu) {
5762 sctp_pathmtu_adjustment(stcb, net->mtu);
5765 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5767 if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
5768 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5769 if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
5770 sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
5772 net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
5774 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5776 if (paddrp->spp_flags & SPP_DSCP) {
5777 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5778 net->dscp = paddrp->spp_dscp & 0xfc;
5781 stcb->asoc.default_dscp = paddrp->spp_dscp & 0xfc;
5782 stcb->asoc.default_dscp |= 0x01;
5785 if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
5786 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5787 if (net->ro._l_addr.sa.sa_family == AF_INET6) {
5788 net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5789 net->flowlabel |= 0x80000000;
5792 stcb->asoc.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5793 stcb->asoc.default_flowlabel |= 0x80000000;
5797 SCTP_TCB_UNLOCK(stcb);
5799 /************************NO TCB, SET TO default stuff ******************/
5800 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5801 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5802 (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC)) {
5803 SCTP_INP_WLOCK(inp);
5805 * For the TOS/FLOWLABEL stuff you set it
5806 * with the options on the socket
5808 if (paddrp->spp_pathmaxrxt) {
5809 inp->sctp_ep.def_net_failure = paddrp->spp_pathmaxrxt;
5812 if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO)
5813 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
5814 else if (paddrp->spp_hbinterval) {
5815 if (paddrp->spp_hbinterval > SCTP_MAX_HB_INTERVAL)
5816 paddrp->spp_hbinterval= SCTP_MAX_HB_INTERVAL;
5817 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
5820 if (paddrp->spp_flags & SPP_HB_ENABLE) {
5821 if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
5822 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
5823 } else if (paddrp->spp_hbinterval) {
5824 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
5826 sctp_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5827 } else if (paddrp->spp_flags & SPP_HB_DISABLE) {
5828 sctp_feature_on(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5830 if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
5831 sctp_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5832 } else if (paddrp->spp_flags & SPP_PMTUD_DISABLE) {
5833 sctp_feature_on(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5835 if (paddrp->spp_flags & SPP_DSCP) {
5836 inp->sctp_ep.default_dscp = paddrp->spp_dscp & 0xfc;
5837 inp->sctp_ep.default_dscp |= 0x01;
5840 if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
5841 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
5842 inp->sctp_ep.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5843 inp->sctp_ep.default_flowlabel |= 0x80000000;
5847 SCTP_INP_WUNLOCK(inp);
5849 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5857 struct sctp_rtoinfo *srto;
5858 uint32_t new_init, new_min, new_max;
5860 SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, optsize);
5861 SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
5864 if (srto->srto_initial)
5865 new_init = srto->srto_initial;
5867 new_init = stcb->asoc.initial_rto;
5869 new_max = srto->srto_max;
5871 new_max = stcb->asoc.maxrto;
5873 new_min = srto->srto_min;
5875 new_min = stcb->asoc.minrto;
5876 if ((new_min <= new_init) && (new_init <= new_max)) {
5877 stcb->asoc.initial_rto = new_init;
5878 stcb->asoc.maxrto = new_max;
5879 stcb->asoc.minrto = new_min;
5881 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5884 SCTP_TCB_UNLOCK(stcb);
5886 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5887 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5888 (srto->srto_assoc_id == SCTP_FUTURE_ASSOC)) {
5889 SCTP_INP_WLOCK(inp);
5890 if (srto->srto_initial)
5891 new_init = srto->srto_initial;
5893 new_init = inp->sctp_ep.initial_rto;
5895 new_max = srto->srto_max;
5897 new_max = inp->sctp_ep.sctp_maxrto;
5899 new_min = srto->srto_min;
5901 new_min = inp->sctp_ep.sctp_minrto;
5902 if ((new_min <= new_init) && (new_init <= new_max)) {
5903 inp->sctp_ep.initial_rto = new_init;
5904 inp->sctp_ep.sctp_maxrto = new_max;
5905 inp->sctp_ep.sctp_minrto = new_min;
5907 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5910 SCTP_INP_WUNLOCK(inp);
5912 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5918 case SCTP_ASSOCINFO:
5920 struct sctp_assocparams *sasoc;
5922 SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, optsize);
5923 SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
5924 if (sasoc->sasoc_cookie_life) {
5925 /* boundary check the cookie life */
5926 if (sasoc->sasoc_cookie_life < 1000)
5927 sasoc->sasoc_cookie_life = 1000;
5928 if (sasoc->sasoc_cookie_life > SCTP_MAX_COOKIE_LIFE) {
5929 sasoc->sasoc_cookie_life = SCTP_MAX_COOKIE_LIFE;
5933 if (sasoc->sasoc_asocmaxrxt)
5934 stcb->asoc.max_send_times = sasoc->sasoc_asocmaxrxt;
5935 if (sasoc->sasoc_cookie_life) {
5936 stcb->asoc.cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
5938 SCTP_TCB_UNLOCK(stcb);
5940 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5941 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5942 (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC)) {
5943 SCTP_INP_WLOCK(inp);
5944 if (sasoc->sasoc_asocmaxrxt)
5945 inp->sctp_ep.max_send_times = sasoc->sasoc_asocmaxrxt;
5946 if (sasoc->sasoc_cookie_life) {
5947 inp->sctp_ep.def_cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
5949 SCTP_INP_WUNLOCK(inp);
5951 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5959 struct sctp_initmsg *sinit;
5961 SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, optsize);
5962 SCTP_INP_WLOCK(inp);
5963 if (sinit->sinit_num_ostreams)
5964 inp->sctp_ep.pre_open_stream_count = sinit->sinit_num_ostreams;
5966 if (sinit->sinit_max_instreams)
5967 inp->sctp_ep.max_open_streams_intome = sinit->sinit_max_instreams;
5969 if (sinit->sinit_max_attempts)
5970 inp->sctp_ep.max_init_times = sinit->sinit_max_attempts;
5972 if (sinit->sinit_max_init_timeo)
5973 inp->sctp_ep.initial_init_rto_max = sinit->sinit_max_init_timeo;
5974 SCTP_INP_WUNLOCK(inp);
5977 case SCTP_PRIMARY_ADDR:
5979 struct sctp_setprim *spa;
5980 struct sctp_nets *net;
5982 SCTP_CHECK_AND_CAST(spa, optval, struct sctp_setprim, optsize);
5983 SCTP_FIND_STCB(inp, stcb, spa->ssp_assoc_id);
5987 net = sctp_findnet(stcb, (struct sockaddr *)&spa->ssp_addr);
5989 /* We increment here since sctp_findassociation_ep_addr() wil
5990 * do a decrement if it finds the stcb as long as the locked
5991 * tcb (last argument) is NOT a TCB.. aka NULL.
5993 SCTP_INP_INCR_REF(inp);
5994 stcb = sctp_findassociation_ep_addr(&inp,
5995 (struct sockaddr *)&spa->ssp_addr,
5998 SCTP_INP_DECR_REF(inp);
6002 if ((stcb) && (net)) {
6003 if ((net != stcb->asoc.primary_destination) &&
6004 (!(net->dest_state & SCTP_ADDR_UNCONFIRMED))) {
6005 /* Ok we need to set it */
6006 if (sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net) == 0) {
6007 if ((stcb->asoc.alternate) &&
6008 (!(net->dest_state & SCTP_ADDR_PF)) &&
6009 (net->dest_state & SCTP_ADDR_REACHABLE)) {
6010 sctp_free_remote_addr(stcb->asoc.alternate);
6011 stcb->asoc.alternate = NULL;
6016 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6020 SCTP_TCB_UNLOCK(stcb);
6024 case SCTP_SET_DYNAMIC_PRIMARY:
6026 union sctp_sockstore *ss;
6030 #if !defined(__Windows__) && !defined(__Userspace__)
6031 #if defined(__APPLE__)
6035 #if __FreeBSD_version > 602000
6036 error = priv_check(curthread,
6037 PRIV_NETINET_RESERVEDPORT);
6038 #elif __FreeBSD_version >= 500000
6039 error = suser((struct thread *)p);
6043 #elif defined(__APPLE__)
6044 proc = (struct proc *)p;
6046 error = suser(proc->p_ucred, &proc->p_acflag);
6051 error = suser(p, 0);
6057 SCTP_CHECK_AND_CAST(ss, optval, union sctp_sockstore, optsize);
6058 /* SUPER USER CHECK? */
6060 for (i = 0; i < inp->num_vrfs; i++) {
6061 if (vrf_id == inp->m_vrf_ids[i]) {
6067 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6072 error = sctp_dynamic_set_primary(&ss->sa, vrf_id);
6075 case SCTP_SET_PEER_PRIMARY_ADDR:
6077 struct sctp_setpeerprim *sspp;
6079 SCTP_CHECK_AND_CAST(sspp, optval, struct sctp_setpeerprim, optsize);
6080 SCTP_FIND_STCB(inp, stcb, sspp->sspp_assoc_id);
6082 struct sctp_ifa *ifa;
6083 ifa = sctp_find_ifa_by_addr((struct sockaddr *)&sspp->sspp_addr,
6084 stcb->asoc.vrf_id, SCTP_ADDR_NOT_LOCKED);
6086 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6090 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
6091 /* Must validate the ifa found is in our ep */
6092 struct sctp_laddr *laddr;
6094 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
6095 if (laddr->ifa == NULL) {
6096 SCTPDBG(SCTP_DEBUG_OUTPUT1, "%s: NULL ifa\n",
6100 if (laddr->ifa == ifa) {
6106 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6111 if (sctp_set_primary_ip_address_sa(stcb,
6112 (struct sockaddr *)&sspp->sspp_addr) != 0) {
6113 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6117 SCTP_TCB_UNLOCK(stcb);
6119 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6124 case SCTP_BINDX_ADD_ADDR:
6126 struct sctp_getaddresses *addrs;
6127 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
6130 td = (struct thread *)p;
6132 SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses,
6135 if (addrs->addr->sa_family == AF_INET) {
6136 if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in)) {
6137 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6141 #if defined(__FreeBSD__) && __FreeBSD_version >= 800000
6142 if (td != NULL && (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)(addrs->addr))->sin_addr)))) {
6143 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
6150 if (addrs->addr->sa_family == AF_INET6) {
6151 if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6)) {
6152 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6156 #if defined(__FreeBSD__) && __FreeBSD_version >= 800000
6157 if (td != NULL && (error = prison_local_ip6(td->td_ucred, &(((struct sockaddr_in6 *)(addrs->addr))->sin6_addr),
6158 (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
6159 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
6166 error = EAFNOSUPPORT;
6169 sctp_bindx_add_address(so, inp, addrs->addr,
6170 addrs->sget_assoc_id, vrf_id,
6174 case SCTP_BINDX_REM_ADDR:
6176 struct sctp_getaddresses *addrs;
6177 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
6179 td = (struct thread *)p;
6182 SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses, optsize);
6184 if (addrs->addr->sa_family == AF_INET) {
6185 if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in)) {
6186 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6190 #if defined(__FreeBSD__) && __FreeBSD_version >= 800000
6191 if (td != NULL && (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)(addrs->addr))->sin_addr)))) {
6192 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
6199 if (addrs->addr->sa_family == AF_INET6) {
6200 if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6)) {
6201 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6205 #if defined(__FreeBSD__) && __FreeBSD_version >= 800000
6207 (error = prison_local_ip6(td->td_ucred,
6208 &(((struct sockaddr_in6 *)(addrs->addr))->sin6_addr),
6209 (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
6210 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
6217 error = EAFNOSUPPORT;
6220 sctp_bindx_delete_address(inp, addrs->addr,
6221 addrs->sget_assoc_id, vrf_id,
6226 case SCTP_LISTEN_FIX:
6227 /* only applies to one-to-many sockets */
6228 if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
6229 /* make sure the ACCEPTCONN flag is OFF */
6230 so->so_options &= ~SO_ACCEPTCONN;
6232 /* otherwise, not allowed */
6233 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6237 #endif /* __APPLE__ */
6240 struct sctp_event *event;
6241 uint32_t event_type;
6243 SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, optsize);
6244 SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
6245 switch (event->se_type) {
6246 case SCTP_ASSOC_CHANGE:
6247 event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
6249 case SCTP_PEER_ADDR_CHANGE:
6250 event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
6252 case SCTP_REMOTE_ERROR:
6253 event_type = SCTP_PCB_FLAGS_RECVPEERERR;
6255 case SCTP_SEND_FAILED:
6256 event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
6258 case SCTP_SHUTDOWN_EVENT:
6259 event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
6261 case SCTP_ADAPTATION_INDICATION:
6262 event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
6264 case SCTP_PARTIAL_DELIVERY_EVENT:
6265 event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
6267 case SCTP_AUTHENTICATION_EVENT:
6268 event_type = SCTP_PCB_FLAGS_AUTHEVNT;
6270 case SCTP_STREAM_RESET_EVENT:
6271 event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
6273 case SCTP_SENDER_DRY_EVENT:
6274 event_type = SCTP_PCB_FLAGS_DRYEVNT;
6276 case SCTP_NOTIFICATIONS_STOPPED_EVENT:
6278 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
6281 case SCTP_ASSOC_RESET_EVENT:
6282 event_type = SCTP_PCB_FLAGS_ASSOC_RESETEVNT;
6284 case SCTP_STREAM_CHANGE_EVENT:
6285 event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT;
6287 case SCTP_SEND_FAILED_EVENT:
6288 event_type = SCTP_PCB_FLAGS_RECVNSENDFAILEVNT;
6292 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6296 if (event_type > 0) {
6299 sctp_stcb_feature_on(inp, stcb, event_type);
6300 if (event_type == SCTP_PCB_FLAGS_DRYEVNT) {
6301 if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
6302 TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
6303 (stcb->asoc.stream_queue_cnt == 0)) {
6304 sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_LOCKED);
6308 sctp_stcb_feature_off(inp, stcb, event_type);
6310 SCTP_TCB_UNLOCK(stcb);
6313 * We don't want to send up a storm of events,
6314 * so return an error for sender dry events
6316 if ((event_type == SCTP_PCB_FLAGS_DRYEVNT) &&
6317 ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) == 0) &&
6318 ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
6319 ((event->se_assoc_id == SCTP_ALL_ASSOC) ||
6320 (event->se_assoc_id == SCTP_CURRENT_ASSOC))) {
6321 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
6325 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6326 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6327 (event->se_assoc_id == SCTP_FUTURE_ASSOC) ||
6328 (event->se_assoc_id == SCTP_ALL_ASSOC)) {
6329 SCTP_INP_WLOCK(inp);
6331 sctp_feature_on(inp, event_type);
6333 sctp_feature_off(inp, event_type);
6335 SCTP_INP_WUNLOCK(inp);
6337 if ((event->se_assoc_id == SCTP_CURRENT_ASSOC) ||
6338 (event->se_assoc_id == SCTP_ALL_ASSOC)) {
6339 SCTP_INP_RLOCK(inp);
6340 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
6341 SCTP_TCB_LOCK(stcb);
6343 sctp_stcb_feature_on(inp, stcb, event_type);
6345 sctp_stcb_feature_off(inp, stcb, event_type);
6347 SCTP_TCB_UNLOCK(stcb);
6349 SCTP_INP_RUNLOCK(inp);
6355 case SCTP_RECVRCVINFO:
6359 SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
6360 SCTP_INP_WLOCK(inp);
6362 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
6364 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
6366 SCTP_INP_WUNLOCK(inp);
6369 case SCTP_RECVNXTINFO:
6373 SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
6374 SCTP_INP_WLOCK(inp);
6376 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
6378 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
6380 SCTP_INP_WUNLOCK(inp);
6383 case SCTP_DEFAULT_SNDINFO:
6385 struct sctp_sndinfo *info;
6388 SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, optsize);
6389 SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
6392 if (info->snd_sid < stcb->asoc.streamoutcnt) {
6393 stcb->asoc.def_send.sinfo_stream = info->snd_sid;
6394 policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
6395 stcb->asoc.def_send.sinfo_flags = info->snd_flags;
6396 stcb->asoc.def_send.sinfo_flags |= policy;
6397 stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
6398 stcb->asoc.def_send.sinfo_context = info->snd_context;
6400 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6403 SCTP_TCB_UNLOCK(stcb);
6405 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6406 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6407 (info->snd_assoc_id == SCTP_FUTURE_ASSOC) ||
6408 (info->snd_assoc_id == SCTP_ALL_ASSOC)) {
6409 SCTP_INP_WLOCK(inp);
6410 inp->def_send.sinfo_stream = info->snd_sid;
6411 policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
6412 inp->def_send.sinfo_flags = info->snd_flags;
6413 inp->def_send.sinfo_flags |= policy;
6414 inp->def_send.sinfo_ppid = info->snd_ppid;
6415 inp->def_send.sinfo_context = info->snd_context;
6416 SCTP_INP_WUNLOCK(inp);
6418 if ((info->snd_assoc_id == SCTP_CURRENT_ASSOC) ||
6419 (info->snd_assoc_id == SCTP_ALL_ASSOC)) {
6420 SCTP_INP_RLOCK(inp);
6421 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
6422 SCTP_TCB_LOCK(stcb);
6423 if (info->snd_sid < stcb->asoc.streamoutcnt) {
6424 stcb->asoc.def_send.sinfo_stream = info->snd_sid;
6425 policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
6426 stcb->asoc.def_send.sinfo_flags = info->snd_flags;
6427 stcb->asoc.def_send.sinfo_flags |= policy;
6428 stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
6429 stcb->asoc.def_send.sinfo_context = info->snd_context;
6431 SCTP_TCB_UNLOCK(stcb);
6433 SCTP_INP_RUNLOCK(inp);
6438 case SCTP_DEFAULT_PRINFO:
6440 struct sctp_default_prinfo *info;
6442 SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, optsize);
6443 SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
6445 if (PR_SCTP_INVALID_POLICY(info->pr_policy)) {
6446 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6451 stcb->asoc.def_send.sinfo_flags &= 0xfff0;
6452 stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
6453 stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
6454 SCTP_TCB_UNLOCK(stcb);
6456 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6457 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6458 (info->pr_assoc_id == SCTP_FUTURE_ASSOC) ||
6459 (info->pr_assoc_id == SCTP_ALL_ASSOC)) {
6460 SCTP_INP_WLOCK(inp);
6461 inp->def_send.sinfo_flags &= 0xfff0;
6462 inp->def_send.sinfo_flags |= info->pr_policy;
6463 inp->def_send.sinfo_timetolive = info->pr_value;
6464 SCTP_INP_WUNLOCK(inp);
6466 if ((info->pr_assoc_id == SCTP_CURRENT_ASSOC) ||
6467 (info->pr_assoc_id == SCTP_ALL_ASSOC)) {
6468 SCTP_INP_RLOCK(inp);
6469 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
6470 SCTP_TCB_LOCK(stcb);
6471 stcb->asoc.def_send.sinfo_flags &= 0xfff0;
6472 stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
6473 stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
6474 SCTP_TCB_UNLOCK(stcb);
6476 SCTP_INP_RUNLOCK(inp);
6481 case SCTP_PEER_ADDR_THLDS:
6482 /* Applies to the specific association */
6484 struct sctp_paddrthlds *thlds;
6485 struct sctp_nets *net;
6487 SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, optsize);
6488 SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
6491 net = sctp_findnet(stcb, (struct sockaddr *)&thlds->spt_assoc_id);
6493 /* We increment here since sctp_findassociation_ep_addr() wil
6494 * do a decrement if it finds the stcb as long as the locked
6495 * tcb (last argument) is NOT a TCB.. aka NULL.
6497 SCTP_INP_INCR_REF(inp);
6498 stcb = sctp_findassociation_ep_addr(&inp,
6499 (struct sockaddr *)&thlds->spt_assoc_id,
6502 SCTP_INP_DECR_REF(inp);
6505 if (stcb && (net == NULL)) {
6506 struct sockaddr *sa;
6508 sa = (struct sockaddr *)&thlds->spt_assoc_id;
6510 if (sa->sa_family == AF_INET) {
6512 struct sockaddr_in *sin;
6513 sin = (struct sockaddr_in *)sa;
6514 if (sin->sin_addr.s_addr) {
6515 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6516 SCTP_TCB_UNLOCK(stcb);
6523 if (sa->sa_family == AF_INET6) {
6524 struct sockaddr_in6 *sin6;
6526 sin6 = (struct sockaddr_in6 *)sa;
6527 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
6528 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6529 SCTP_TCB_UNLOCK(stcb);
6535 #if defined(__Userspace__)
6536 if (sa->sa_family == AF_CONN) {
6537 struct sockaddr_conn *sconn;
6539 sconn = (struct sockaddr_conn *)sa;
6540 if (sconn->sconn_addr != NULL) {
6541 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6542 SCTP_TCB_UNLOCK(stcb);
6549 error = EAFNOSUPPORT;
6550 SCTP_TCB_UNLOCK(stcb);
6551 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6557 if (net->dest_state & SCTP_ADDR_PF) {
6558 if ((net->failure_threshold > thlds->spt_pathmaxrxt) ||
6559 (net->failure_threshold <= thlds->spt_pathpfthld)) {
6560 net->dest_state &= ~SCTP_ADDR_PF;
6563 if ((net->failure_threshold > thlds->spt_pathpfthld) &&
6564 (net->failure_threshold <= thlds->spt_pathmaxrxt)) {
6565 net->dest_state |= SCTP_ADDR_PF;
6566 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
6567 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
6568 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
6571 if (net->dest_state & SCTP_ADDR_REACHABLE) {
6572 if (net->failure_threshold > thlds->spt_pathmaxrxt) {
6573 net->dest_state &= ~SCTP_ADDR_REACHABLE;
6574 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
6577 if (net->failure_threshold <= thlds->spt_pathmaxrxt) {
6578 net->dest_state |= SCTP_ADDR_REACHABLE;
6579 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
6582 net->failure_threshold = thlds->spt_pathmaxrxt;
6583 net->pf_threshold = thlds->spt_pathpfthld;
6585 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6586 if (net->dest_state & SCTP_ADDR_PF) {
6587 if ((net->failure_threshold > thlds->spt_pathmaxrxt) ||
6588 (net->failure_threshold <= thlds->spt_pathpfthld)) {
6589 net->dest_state &= ~SCTP_ADDR_PF;
6592 if ((net->failure_threshold > thlds->spt_pathpfthld) &&
6593 (net->failure_threshold <= thlds->spt_pathmaxrxt)) {
6594 net->dest_state |= SCTP_ADDR_PF;
6595 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
6596 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
6597 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
6600 if (net->dest_state & SCTP_ADDR_REACHABLE) {
6601 if (net->failure_threshold > thlds->spt_pathmaxrxt) {
6602 net->dest_state &= ~SCTP_ADDR_REACHABLE;
6603 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
6606 if (net->failure_threshold <= thlds->spt_pathmaxrxt) {
6607 net->dest_state |= SCTP_ADDR_REACHABLE;
6608 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
6611 net->failure_threshold = thlds->spt_pathmaxrxt;
6612 net->pf_threshold = thlds->spt_pathpfthld;
6614 stcb->asoc.def_net_failure = thlds->spt_pathmaxrxt;
6615 stcb->asoc.def_net_pf_threshold = thlds->spt_pathpfthld;
6618 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6619 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6620 (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC)) {
6621 SCTP_INP_WLOCK(inp);
6622 inp->sctp_ep.def_net_failure = thlds->spt_pathmaxrxt;
6623 inp->sctp_ep.def_net_pf_threshold = thlds->spt_pathpfthld;
6624 SCTP_INP_WUNLOCK(inp);
6626 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6632 case SCTP_REMOTE_UDP_ENCAPS_PORT:
6634 struct sctp_udpencaps *encaps;
6635 struct sctp_nets *net;
6637 SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, optsize);
6638 SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
6640 net = sctp_findnet(stcb, (struct sockaddr *)&encaps->sue_address);
6642 /* We increment here since sctp_findassociation_ep_addr() wil
6643 * do a decrement if it finds the stcb as long as the locked
6644 * tcb (last argument) is NOT a TCB.. aka NULL.
6647 SCTP_INP_INCR_REF(inp);
6648 stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&encaps->sue_address, &net, NULL, NULL);
6650 SCTP_INP_DECR_REF(inp);
6653 if (stcb && (net == NULL)) {
6654 struct sockaddr *sa;
6656 sa = (struct sockaddr *)&encaps->sue_address;
6658 if (sa->sa_family == AF_INET) {
6660 struct sockaddr_in *sin;
6661 sin = (struct sockaddr_in *)sa;
6662 if (sin->sin_addr.s_addr) {
6663 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6664 SCTP_TCB_UNLOCK(stcb);
6671 if (sa->sa_family == AF_INET6) {
6672 struct sockaddr_in6 *sin6;
6674 sin6 = (struct sockaddr_in6 *)sa;
6675 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
6676 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6677 SCTP_TCB_UNLOCK(stcb);
6683 #if defined(__Userspace__)
6684 if (sa->sa_family == AF_CONN) {
6685 struct sockaddr_conn *sconn;
6687 sconn = (struct sockaddr_conn *)sa;
6688 if (sconn->sconn_addr != NULL) {
6689 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6690 SCTP_TCB_UNLOCK(stcb);
6697 error = EAFNOSUPPORT;
6698 SCTP_TCB_UNLOCK(stcb);
6699 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6706 net->port = encaps->sue_port;
6708 stcb->asoc.port = encaps->sue_port;
6710 SCTP_TCB_UNLOCK(stcb);
6712 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6713 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6714 (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC)) {
6715 SCTP_INP_WLOCK(inp);
6716 inp->sctp_ep.port = encaps->sue_port;
6717 SCTP_INP_WUNLOCK(inp);
6719 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6726 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
6727 error = ENOPROTOOPT;
6729 } /* end switch (opt) */
6733 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
6735 sctp_ctloutput(struct socket *so, struct sockopt *sopt)
6737 void *optval = NULL;
6742 if (sopt->sopt_level != IPPROTO_SCTP) {
6743 /* wrong proto level... send back up to IP */
6745 if (INP_CHECK_SOCKAF(so, AF_INET6))
6746 error = ip6_ctloutput(so, sopt);
6748 #if defined(INET) && defined(INET6)
6752 error = ip_ctloutput(so, sopt);
6756 optsize = sopt->sopt_valsize;
6758 SCTP_MALLOC(optval, void *, optsize, SCTP_M_SOCKOPT);
6759 if (optval == NULL) {
6760 SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS);
6763 error = sooptcopyin(sopt, optval, optsize, optsize);
6765 SCTP_FREE(optval, SCTP_M_SOCKOPT);
6769 #if (defined(__FreeBSD__) && __FreeBSD_version >= 500000) || defined(__Windows__)
6770 p = (void *)sopt->sopt_td;
6772 p = (void *)sopt->sopt_p;
6774 if (sopt->sopt_dir == SOPT_SET) {
6775 error = sctp_setopt(so, sopt->sopt_name, optval, optsize, p);
6776 } else if (sopt->sopt_dir == SOPT_GET) {
6777 error = sctp_getopt(so, sopt->sopt_name, optval, &optsize, p);
6779 SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6782 if ((error == 0) && (optval != NULL)) {
6783 error = sooptcopyout(sopt, optval, optsize);
6784 SCTP_FREE(optval, SCTP_M_SOCKOPT);
6785 } else if (optval != NULL) {
6786 SCTP_FREE(optval, SCTP_M_SOCKOPT);
6794 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
6796 sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
6799 #if defined(__FreeBSD__) || defined(__APPLE__)
6801 sctp_connect(struct socket *so, struct sockaddr *addr, struct proc *p)
6803 #elif defined(__Panda__) || defined(__Userspace__)
6805 sctp_connect(struct socket *so, struct sockaddr *addr)
6808 #elif defined(__Windows__)
6810 sctp_connect(struct socket *so, struct sockaddr *addr, PKTHREAD p)
6814 sctp_connect(struct socket *so, struct mbuf *nam, struct proc *p)
6816 struct sockaddr *addr = mtod(nam, struct sockaddr *);
6824 int create_lock_on = 0;
6826 struct sctp_inpcb *inp;
6827 struct sctp_tcb *stcb = NULL;
6829 inp = (struct sctp_inpcb *)so->so_pcb;
6831 /* I made the same as TCP since we are not setup? */
6832 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6833 return (ECONNRESET);
6836 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6840 #if defined(__Userspace__)
6841 /* TODO __Userspace__ falls into this code for IPv6 stuff at the moment... */
6843 #if !defined(__Windows__) && !defined(__Userspace_os_Linux) && !defined(__Userspace_os_Windows)
6844 switch (addr->sa_family) {
6848 #if defined(__FreeBSD__) && __FreeBSD_version >= 800000
6849 struct sockaddr_in6 *sin6p;
6852 if (addr->sa_len != sizeof(struct sockaddr_in6)) {
6853 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6856 #if defined(__FreeBSD__) && __FreeBSD_version >= 800000
6857 sin6p = (struct sockaddr_in6 *)addr;
6858 if (p != NULL && (error = prison_remote_ip6(p->td_ucred, &sin6p->sin6_addr)) != 0) {
6859 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6869 #if defined(__FreeBSD__) && __FreeBSD_version >= 800000
6870 struct sockaddr_in *sinp;
6873 #if !defined(__Userspace_os_Windows)
6874 if (addr->sa_len != sizeof(struct sockaddr_in)) {
6875 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6879 #if defined(__FreeBSD__) && __FreeBSD_version >= 800000
6880 sinp = (struct sockaddr_in *)addr;
6881 if (p != NULL && (error = prison_remote_ip4(p->td_ucred, &sinp->sin_addr)) != 0) {
6882 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6890 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
6891 return (EAFNOSUPPORT);
6894 SCTP_INP_INCR_REF(inp);
6895 SCTP_ASOC_CREATE_LOCK(inp);
6899 if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
6900 (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
6901 /* Should I really unlock ? */
6902 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
6907 if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
6908 (addr->sa_family == AF_INET6)) {
6909 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6914 #if defined(__Userspace__)
6915 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_CONN) &&
6916 (addr->sa_family != AF_CONN)) {
6917 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6922 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
6923 SCTP_PCB_FLAGS_UNBOUND) {
6924 /* Bind a ephemeral port */
6925 error = sctp_inpcb_bind(so, NULL, NULL, p);
6930 /* Now do we connect? */
6931 if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
6932 (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
6933 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6937 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
6938 (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
6939 /* We are already connected AND the TCP model */
6940 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
6944 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
6945 SCTP_INP_RLOCK(inp);
6946 stcb = LIST_FIRST(&inp->sctp_asoc_list);
6947 SCTP_INP_RUNLOCK(inp);
6949 /* We increment here since sctp_findassociation_ep_addr() will
6950 * do a decrement if it finds the stcb as long as the locked
6951 * tcb (last argument) is NOT a TCB.. aka NULL.
6953 SCTP_INP_INCR_REF(inp);
6954 stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
6956 SCTP_INP_DECR_REF(inp);
6958 SCTP_TCB_UNLOCK(stcb);
6962 /* Already have or am bring up an association */
6963 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
6968 vrf_id = inp->def_vrf_id;
6970 for (i = 0; i < inp->num_vrfs; i++) {
6971 if (vrf_id == inp->m_vrf_ids[i]) {
6977 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6982 /* We are GOOD to go */
6983 stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, p);
6985 /* Gak! no memory */
6988 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
6989 stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
6990 /* Set the connected flag so we can queue data */
6993 SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
6994 (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
6996 /* initialize authentication parameters for the assoc */
6997 sctp_initialize_auth_params(inp, stcb);
6999 sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
7000 SCTP_TCB_UNLOCK(stcb);
7002 if (create_lock_on) {
7003 SCTP_ASOC_CREATE_UNLOCK(inp);
7006 SCTP_INP_DECR_REF(inp);
7011 #if defined(__Userspace__)
7013 sctpconn_connect(struct socket *so, struct sockaddr *addr)
7020 int create_lock_on = 0;
7022 struct sctp_inpcb *inp;
7023 struct sctp_tcb *stcb = NULL;
7025 inp = (struct sctp_inpcb *)so->so_pcb;
7027 /* I made the same as TCP since we are not setup? */
7028 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7029 return (ECONNRESET);
7032 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7035 switch (addr->sa_family) {
7039 if (addr->sa_len != sizeof(struct sockaddr_in)) {
7040 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7049 if (addr->sa_len != sizeof(struct sockaddr_in6)) {
7050 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7058 if (addr->sa_len != sizeof(struct sockaddr_conn)) {
7059 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7065 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
7066 return (EAFNOSUPPORT);
7068 SCTP_INP_INCR_REF(inp);
7069 SCTP_ASOC_CREATE_LOCK(inp);
7073 if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
7074 (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
7075 /* Should I really unlock ? */
7076 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
7081 if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
7082 (addr->sa_family == AF_INET6)) {
7083 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7088 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == SCTP_PCB_FLAGS_UNBOUND) {
7089 /* Bind a ephemeral port */
7090 error = sctp_inpcb_bind(so, NULL, NULL, p);
7095 /* Now do we connect? */
7096 if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
7097 (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
7098 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7102 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
7103 (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
7104 /* We are already connected AND the TCP model */
7105 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
7109 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
7110 SCTP_INP_RLOCK(inp);
7111 stcb = LIST_FIRST(&inp->sctp_asoc_list);
7112 SCTP_INP_RUNLOCK(inp);
7114 /* We increment here since sctp_findassociation_ep_addr() will
7115 * do a decrement if it finds the stcb as long as the locked
7116 * tcb (last argument) is NOT a TCB.. aka NULL.
7118 SCTP_INP_INCR_REF(inp);
7119 stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
7121 SCTP_INP_DECR_REF(inp);
7123 SCTP_TCB_UNLOCK(stcb);
7127 /* Already have or am bring up an association */
7128 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
7133 vrf_id = inp->def_vrf_id;
7135 for (i = 0; i < inp->num_vrfs; i++) {
7136 if (vrf_id == inp->m_vrf_ids[i]) {
7142 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7147 /* We are GOOD to go */
7148 stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, p);
7150 /* Gak! no memory */
7153 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
7154 stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
7155 /* Set the connected flag so we can queue data */
7158 SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
7159 (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
7161 /* initialize authentication parameters for the assoc */
7162 sctp_initialize_auth_params(inp, stcb);
7164 sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
7165 SCTP_TCB_UNLOCK(stcb);
7167 if (create_lock_on) {
7168 SCTP_ASOC_CREATE_UNLOCK(inp);
7171 SCTP_INP_DECR_REF(inp);
7176 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
7177 #if __FreeBSD_version >= 700000
7178 sctp_listen(struct socket *so, int backlog, struct thread *p)
7180 sctp_listen(struct socket *so, struct thread *p)
7182 #elif defined(__Windows__)
7183 sctp_listen(struct socket *so, int backlog, PKTHREAD p)
7184 #elif defined(__Userspace__)
7185 sctp_listen(struct socket *so, int backlog, struct proc *p)
7187 sctp_listen(struct socket *so, struct proc *p)
7191 * Note this module depends on the protocol processing being called
7192 * AFTER any socket level flags and backlog are applied to the
7193 * socket. The traditional way that the socket flags are applied is
7194 * AFTER protocol processing. We have made a change to the
7195 * sys/kern/uipc_socket.c module to reverse this but this MUST be in
7196 * place if the socket API for SCTP is to work properly.
7200 struct sctp_inpcb *inp;
7202 inp = (struct sctp_inpcb *)so->so_pcb;
7204 /* I made the same as TCP since we are not setup? */
7205 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7206 return (ECONNRESET);
7208 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) {
7209 /* See if we have a listener */
7210 struct sctp_inpcb *tinp;
7211 union sctp_sockstore store, *sp;
7214 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
7216 struct sctp_laddr *laddr;
7218 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
7219 memcpy(&store, &laddr->ifa->address, sizeof(store));
7220 switch (sp->sa.sa_family) {
7223 sp->sin.sin_port = inp->sctp_lport;
7228 sp->sin6.sin6_port = inp->sctp_lport;
7231 #if defined(__Userspace__)
7233 sp->sconn.sconn_port = inp->sctp_lport;
7239 tinp = sctp_pcb_findep(&sp->sa, 0, 0, inp->def_vrf_id);
7240 if (tinp && (tinp != inp) &&
7241 ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
7242 ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
7243 (tinp->sctp_socket->so_qlimit)) {
7244 /* we have a listener already and its not this inp. */
7245 SCTP_INP_DECR_REF(tinp);
7246 return (EADDRINUSE);
7248 SCTP_INP_DECR_REF(tinp);
7252 /* Setup a local addr bound all */
7253 memset(&store, 0, sizeof(store));
7254 switch (sp->sa.sa_family) {
7257 store.sin.sin_port = inp->sctp_lport;
7262 sp->sin6.sin6_port = inp->sctp_lport;
7265 #if defined(__Userspace__)
7267 sp->sconn.sconn_port = inp->sctp_lport;
7274 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
7275 store.sa.sa_family = AF_INET6;
7277 store.sa.sa_len = sizeof(struct sockaddr_in6);
7282 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
7283 store.sa.sa_family = AF_INET;
7285 store.sa.sa_len = sizeof(struct sockaddr_in);
7289 tinp = sctp_pcb_findep(&sp->sa, 0, 0, inp->def_vrf_id);
7290 if (tinp && (tinp != inp) &&
7291 ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
7292 ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
7293 (tinp->sctp_socket->so_qlimit)) {
7294 /* we have a listener already and its not this inp. */
7295 SCTP_INP_DECR_REF(tinp);
7296 return (EADDRINUSE);
7298 SCTP_INP_DECR_REF(inp);
7302 SCTP_INP_RLOCK(inp);
7303 #ifdef SCTP_LOCK_LOGGING
7304 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) {
7305 sctp_log_lock(inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_SOCK);
7309 #if (defined(__FreeBSD__) && __FreeBSD_version > 500000) || defined(__Userspace__)
7310 error = solisten_proto_check(so);
7313 SCTP_INP_RUNLOCK(inp);
7317 if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) &&
7318 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
7320 * - We are in the tcp pool with this guy.
7321 * - Someone else is in the main inp slot.
7322 * - We must move this guy (the listener) to the main slot
7323 * - We must then move the guy that was listener to the TCP Pool.
7325 if (sctp_swap_inpcb_for_listen(inp)) {
7330 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
7331 (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
7332 /* We are already connected AND the TCP model */
7334 SCTP_INP_RUNLOCK(inp);
7336 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
7337 return (EADDRINUSE);
7339 SCTP_INP_RUNLOCK(inp);
7340 if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
7341 /* We must do a bind. */
7343 if ((error = sctp_inpcb_bind(so, NULL, NULL, p))) {
7344 /* bind error, probably perm */
7349 #if (defined(__FreeBSD__) && __FreeBSD_version > 500000) || defined(__Windows__) || defined(__Userspace__)
7350 #if __FreeBSD_version >= 700000 || defined(__Windows__) || defined(__Userspace__)
7351 /* It appears for 7.0 and on, we must always call this. */
7352 solisten_proto(so, backlog);
7354 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) == 0) {
7359 if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
7360 /* remove the ACCEPTCONN flag for one-to-many sockets */
7361 #if defined(__Userspace__)
7362 so->so_options &= ~SCTP_SO_ACCEPTCONN;
7364 so->so_options &= ~SO_ACCEPTCONN;
7368 #if __FreeBSD_version >= 700000 || defined(__Windows__) || defined(__Userspace__)
7370 /* turning off listen */
7371 #if defined(__Userspace__)
7372 so->so_options &= ~SCTP_SO_ACCEPTCONN;
7374 so->so_options &= ~SO_ACCEPTCONN;
7382 static int sctp_defered_wakeup_cnt = 0;
7385 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
7386 sctp_accept(struct socket *so, struct sockaddr **addr)
7388 #elif defined(__Panda__)
7389 sctp_accept(struct socket *so, struct sockaddr *addr, int *namelen,
7390 void *accept_info, int *accept_info_len)
7393 sctp_accept(struct socket *so, struct mbuf *nam)
7395 struct sockaddr *addr = mtod(nam, struct sockaddr *);
7397 struct sctp_tcb *stcb;
7398 struct sctp_inpcb *inp;
7399 union sctp_sockstore store;
7403 #endif /* SCTP_KAME */
7405 inp = (struct sctp_inpcb *)so->so_pcb;
7408 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7409 return (ECONNRESET);
7411 SCTP_INP_RLOCK(inp);
7412 if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
7413 SCTP_INP_RUNLOCK(inp);
7414 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
7415 return (EOPNOTSUPP);
7417 if (so->so_state & SS_ISDISCONNECTED) {
7418 SCTP_INP_RUNLOCK(inp);
7419 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ECONNABORTED);
7420 return (ECONNABORTED);
7422 stcb = LIST_FIRST(&inp->sctp_asoc_list);
7424 SCTP_INP_RUNLOCK(inp);
7425 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7426 return (ECONNRESET);
7428 SCTP_TCB_LOCK(stcb);
7429 SCTP_INP_RUNLOCK(inp);
7430 store = stcb->asoc.primary_destination->ro._l_addr;
7431 stcb->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE;
7432 SCTP_TCB_UNLOCK(stcb);
7433 switch (store.sa.sa_family) {
7437 struct sockaddr_in *sin;
7439 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
7440 SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
7444 sin = (struct sockaddr_in *)addr;
7445 bzero((caddr_t)sin, sizeof(*sin));
7447 sin->sin_family = AF_INET;
7449 sin->sin_len = sizeof(*sin);
7451 sin->sin_port = store.sin.sin_port;
7452 sin->sin_addr = store.sin.sin_addr;
7453 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
7454 *addr = (struct sockaddr *)sin;
7455 #elif !defined(__Panda__)
7456 SCTP_BUF_LEN(nam) = sizeof(*sin);
7464 struct sockaddr_in6 *sin6;
7466 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
7467 SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
7471 sin6 = (struct sockaddr_in6 *)addr;
7472 bzero((caddr_t)sin6, sizeof(*sin6));
7474 sin6->sin6_family = AF_INET6;
7475 #ifdef HAVE_SIN6_LEN
7476 sin6->sin6_len = sizeof(*sin6);
7478 sin6->sin6_port = store.sin6.sin6_port;
7479 sin6->sin6_addr = store.sin6.sin6_addr;
7480 #if defined(SCTP_EMBEDDED_V6_SCOPE)
7482 if ((error = sa6_recoverscope(sin6)) != 0) {
7483 SCTP_FREE_SONAME(sin6);
7487 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
7489 * sin6->sin6_scope_id =
7490 * ntohs(sin6->sin6_addr.s6_addr16[1]);
7492 in6_recoverscope(sin6, &sin6->sin6_addr, NULL); /* skip ifp check */
7494 sin6->sin6_scope_id = 0; /* XXX */
7495 #endif /* SCTP_KAME */
7496 #endif /* SCTP_EMBEDDED_V6_SCOPE */
7497 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
7498 *addr = (struct sockaddr *)sin6;
7499 #elif !defined(__Panda__)
7500 SCTP_BUF_LEN(nam) = sizeof(*sin6);
7505 #if defined(__Userspace__)
7508 struct sockaddr_conn *sconn;
7510 SCTP_MALLOC_SONAME(sconn, struct sockaddr_conn *, sizeof(struct sockaddr_conn));
7511 if (sconn == NULL) {
7514 sconn->sconn_family = AF_CONN;
7515 #ifdef HAVE_SCONN_LEN
7516 sconn->sconn_len = sizeof(struct sockaddr_conn);
7518 sconn->sconn_port = store.sconn.sconn_port;
7519 sconn->sconn_addr = store.sconn.sconn_addr;
7520 *addr = (struct sockaddr *)sconn;
7528 /* Wake any delayed sleep action */
7529 if (inp->sctp_flags & SCTP_PCB_FLAGS_DONT_WAKE) {
7530 SCTP_INP_WLOCK(inp);
7531 inp->sctp_flags &= ~SCTP_PCB_FLAGS_DONT_WAKE;
7532 if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEOUTPUT) {
7533 inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEOUTPUT;
7534 SCTP_INP_WUNLOCK(inp);
7535 SOCKBUF_LOCK(&inp->sctp_socket->so_snd);
7536 if (sowriteable(inp->sctp_socket)) {
7537 #if defined(__Userspace__)
7538 /*__Userspace__ calling sowwakup_locked because of SOCKBUF_LOCK above. */
7540 #if defined(__FreeBSD__) || defined(__Windows__) || defined(__Userspace__)
7541 sowwakeup_locked(inp->sctp_socket);
7543 #if defined(__APPLE__)
7544 /* socket is locked */
7546 sowwakeup(inp->sctp_socket);
7549 SOCKBUF_UNLOCK(&inp->sctp_socket->so_snd);
7551 SCTP_INP_WLOCK(inp);
7553 if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEINPUT) {
7554 inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEINPUT;
7555 SCTP_INP_WUNLOCK(inp);
7556 SOCKBUF_LOCK(&inp->sctp_socket->so_rcv);
7557 if (soreadable(inp->sctp_socket)) {
7558 sctp_defered_wakeup_cnt++;
7559 #if defined(__Userspace__)
7560 /*__Userspace__ calling sorwakup_locked because of SOCKBUF_LOCK above */
7562 #if defined(__FreeBSD__) || defined(__Windows__) || defined(__Userspace__)
7563 sorwakeup_locked(inp->sctp_socket);
7565 #if defined(__APPLE__)
7566 /* socket is locked */
7568 sorwakeup(inp->sctp_socket);
7571 SOCKBUF_UNLOCK(&inp->sctp_socket->so_rcv);
7573 SCTP_INP_WLOCK(inp);
7575 SCTP_INP_WUNLOCK(inp);
7577 if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
7578 SCTP_TCB_LOCK(stcb);
7579 sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_7);
7586 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
7587 sctp_ingetaddr(struct socket *so, struct sockaddr **addr)
7589 struct sockaddr_in *sin;
7590 #elif defined(__Panda__)
7591 sctp_ingetaddr(struct socket *so, struct sockaddr *addr)
7593 struct sockaddr_in *sin = (struct sockaddr_in *)addr;
7595 sctp_ingetaddr(struct socket *so, struct mbuf *nam)
7597 struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
7600 struct sctp_inpcb *inp;
7601 struct sctp_ifa *sctp_ifa;
7604 * Do the malloc first in case it blocks.
7606 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
7607 SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
7610 #elif defined(__Panda__)
7611 bzero(sin, sizeof(*sin));
7613 SCTP_BUF_LEN(nam) = sizeof(*sin);
7614 memset(sin, 0, sizeof(*sin));
7616 sin->sin_family = AF_INET;
7618 sin->sin_len = sizeof(*sin);
7620 inp = (struct sctp_inpcb *)so->so_pcb;
7622 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
7623 SCTP_FREE_SONAME(sin);
7625 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7626 return (ECONNRESET);
7628 SCTP_INP_RLOCK(inp);
7629 sin->sin_port = inp->sctp_lport;
7630 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
7631 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
7632 struct sctp_tcb *stcb;
7633 struct sockaddr_in *sin_a;
7634 struct sctp_nets *net;
7637 stcb = LIST_FIRST(&inp->sctp_asoc_list);
7643 SCTP_TCB_LOCK(stcb);
7644 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
7645 sin_a = (struct sockaddr_in *)&net->ro._l_addr;
7647 /* this will make coverity happy */
7650 if (sin_a->sin_family == AF_INET) {
7655 if ((!fnd) || (sin_a == NULL)) {
7657 SCTP_TCB_UNLOCK(stcb);
7661 vrf_id = inp->def_vrf_id;
7662 sctp_ifa = sctp_source_address_selection(inp,
7664 (sctp_route_t *)&net->ro,
7667 sin->sin_addr = sctp_ifa->address.sin.sin_addr;
7668 sctp_free_ifa(sctp_ifa);
7670 SCTP_TCB_UNLOCK(stcb);
7672 /* For the bound all case you get back 0 */
7674 sin->sin_addr.s_addr = 0;
7678 /* Take the first IPv4 address in the list */
7679 struct sctp_laddr *laddr;
7682 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
7683 if (laddr->ifa->address.sa.sa_family == AF_INET) {
7684 struct sockaddr_in *sin_a;
7686 sin_a = (struct sockaddr_in *)&laddr->ifa->address.sa;
7687 sin->sin_addr = sin_a->sin_addr;
7693 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
7694 SCTP_FREE_SONAME(sin);
7696 SCTP_INP_RUNLOCK(inp);
7697 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
7701 SCTP_INP_RUNLOCK(inp);
7702 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
7703 (*addr) = (struct sockaddr *)sin;
7709 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
7710 sctp_peeraddr(struct socket *so, struct sockaddr **addr)
7712 struct sockaddr_in *sin;
7713 #elif defined(__Panda__)
7714 sctp_peeraddr(struct socket *so, struct sockaddr *addr)
7716 struct sockaddr_in *sin = (struct sockaddr_in *)addr;
7718 sctp_peeraddr(struct socket *so, struct mbuf *nam)
7720 struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
7724 struct sockaddr_in *sin_a;
7725 struct sctp_inpcb *inp;
7726 struct sctp_tcb *stcb;
7727 struct sctp_nets *net;
7729 /* Do the malloc first in case it blocks. */
7730 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
7731 SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
7734 #elif defined(__Panda__)
7735 memset(sin, 0, sizeof(*sin));
7737 SCTP_BUF_LEN(nam) = sizeof(*sin);
7738 memset(sin, 0, sizeof(*sin));
7740 sin->sin_family = AF_INET;
7742 sin->sin_len = sizeof(*sin);
7745 inp = (struct sctp_inpcb *)so->so_pcb;
7746 if ((inp == NULL) ||
7747 ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
7748 /* UDP type and listeners will drop out here */
7749 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
7750 SCTP_FREE_SONAME(sin);
7752 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
7755 SCTP_INP_RLOCK(inp);
7756 stcb = LIST_FIRST(&inp->sctp_asoc_list);
7758 SCTP_TCB_LOCK(stcb);
7760 SCTP_INP_RUNLOCK(inp);
7762 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
7763 SCTP_FREE_SONAME(sin);
7765 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7766 return (ECONNRESET);
7769 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
7770 sin_a = (struct sockaddr_in *)&net->ro._l_addr;
7771 if (sin_a->sin_family == AF_INET) {
7773 sin->sin_port = stcb->rport;
7774 sin->sin_addr = sin_a->sin_addr;
7778 SCTP_TCB_UNLOCK(stcb);
7780 /* No IPv4 address */
7781 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
7782 SCTP_FREE_SONAME(sin);
7784 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
7787 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
7788 (*addr) = (struct sockaddr *)sin;
7793 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
7794 struct pr_usrreqs sctp_usrreqs = {
7795 #if __FreeBSD_version >= 600000
7796 .pru_abort = sctp_abort,
7797 .pru_accept = sctp_accept,
7798 .pru_attach = sctp_attach,
7799 .pru_bind = sctp_bind,
7800 .pru_connect = sctp_connect,
7801 .pru_control = in_control,
7802 #if __FreeBSD_version >= 690000
7803 .pru_close = sctp_close,
7804 .pru_detach = sctp_close,
7805 .pru_sopoll = sopoll_generic,
7806 .pru_flush = sctp_flush,
7808 .pru_detach = sctp_detach,
7809 .pru_sopoll = sopoll,
7811 .pru_disconnect = sctp_disconnect,
7812 .pru_listen = sctp_listen,
7813 .pru_peeraddr = sctp_peeraddr,
7814 .pru_send = sctp_sendm,
7815 .pru_shutdown = sctp_shutdown,
7816 .pru_sockaddr = sctp_ingetaddr,
7817 .pru_sosend = sctp_sosend,
7818 .pru_soreceive = sctp_soreceive
7825 pru_connect2_notsupp,
7826 #if defined(__Windows__)
7838 #if defined(__Windows__)
7845 #if defined(__Windows__)
7851 #if defined(__Windows__)
7860 #elif !defined(__Panda__) && !defined(__Userspace__)
7862 sctp_usrreq(so, req, m, nam, control)
7865 struct mbuf *m, *nam, *control;
7867 struct proc *p = curproc;
7869 struct sctp_vrf *vrf;
7872 struct sctp_inpcb *inp = (struct sctp_inpcb *)so->so_pcb;
7875 family = so->so_proto->pr_domain->dom_family;
7876 if (req == PRU_CONTROL) {
7879 error = in_control(so, (long)m, (caddr_t)nam,
7880 (struct ifnet *)control);
7884 error = in6_control(so, (long)m, (caddr_t)nam,
7885 (struct ifnet *)control, p);
7889 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
7890 error = EAFNOSUPPORT;
7896 error = sctp_attach(so, family, p);
7899 error = sctp_detach(so);
7903 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7906 error = sctp_bind(so, nam, p);
7909 error = sctp_listen(so, p);
7913 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7916 error = sctp_connect(so, nam, p);
7918 case PRU_DISCONNECT:
7919 error = sctp_disconnect(so);
7923 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7926 error = sctp_accept(so, nam);
7929 error = sctp_shutdown(so);
7934 * For Open and Net BSD, this is real ugly. The mbuf *nam
7935 * that is passed (by soreceive()) is the int flags c ast as
7941 /* Flags are ignored */
7943 struct sockaddr *addr;
7948 addr = mtod(nam, struct sockaddr *);
7950 error = sctp_sendm(so, 0, m, addr, control, p);
7954 error = sctp_abort(so);
7961 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
7962 error = EAFNOSUPPORT;
7965 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
7966 error = EAFNOSUPPORT;
7969 error = sctp_peeraddr(so, nam);
7972 error = sctp_ingetaddr(so, nam);
7986 #if defined(__Userspace__)
7988 register_recv_cb(struct socket *so,
7989 int (*receive_cb)(struct socket *sock, union sctp_sockstore addr, void *data,
7990 size_t datalen, struct sctp_rcvinfo, int flags, void *ulp_info))
7992 struct sctp_inpcb *inp;
7994 inp = (struct sctp_inpcb *) so->so_pcb;
7998 SCTP_INP_WLOCK(inp);
7999 inp->recv_callback = receive_cb;
8000 SCTP_INP_WUNLOCK(inp);
8005 register_send_cb(struct socket *so, uint32_t sb_threshold, int (*send_cb)(struct socket *sock, uint32_t sb_free))
8007 struct sctp_inpcb *inp;
8009 inp = (struct sctp_inpcb *) so->so_pcb;
8013 SCTP_INP_WLOCK(inp);
8014 inp->send_callback = send_cb;
8015 inp->send_sb_threshold = sb_threshold;
8016 SCTP_INP_WUNLOCK(inp);
8017 /* FIXME change to current amount free. This will be the full buffer
8018 * the first time this is registered but it could be only a portion
8019 * of the send buffer if this is called a second time e.g. if the
8020 * threshold changes.
8026 register_ulp_info (struct socket *so, void *ulp_info)
8028 struct sctp_inpcb *inp;
8030 inp = (struct sctp_inpcb *) so->so_pcb;
8034 SCTP_INP_WLOCK(inp);
8035 inp->ulp_info = ulp_info;
8036 SCTP_INP_WUNLOCK(inp);