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.
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
36 #include <netinet/sctp_os.h>
38 #include <netinet/sctp_pcb.h>
39 #include <netinet/sctp_header.h>
40 #include <netinet/sctp_var.h>
42 #include <netinet6/sctp6_var.h>
44 #include <netinet/sctp_sysctl.h>
45 #include <netinet/sctp_output.h>
46 #include <netinet/sctp_uio.h>
47 #include <netinet/sctp_asconf.h>
48 #include <netinet/sctputil.h>
49 #include <netinet/sctp_indata.h>
50 #include <netinet/sctp_timer.h>
51 #include <netinet/sctp_auth.h>
52 #include <netinet/sctp_bsd_addr.h>
53 #include <netinet/udp.h>
57 extern const struct sctp_cc_functions sctp_cc_functions[];
58 extern const struct sctp_ss_functions sctp_ss_functions[];
65 /* Initialize and modify the sysctled variables */
67 if ((nmbclusters / 8) > SCTP_ASOC_MAX_CHUNKS_ON_QUEUE)
68 SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue) = (nmbclusters / 8);
70 * Allow a user to take no more than 1/2 the number of clusters or
71 * the SB_MAX whichever is smaller for the send window.
73 sb_max_adj = (u_long)((u_quad_t) (SB_MAX) * MCLBYTES / (MSIZE + MCLBYTES));
74 SCTP_BASE_SYSCTL(sctp_sendspace) = min(sb_max_adj,
75 (((uint32_t) nmbclusters / 2) * SCTP_DEFAULT_MAXSEGMENT));
77 * Now for the recv window, should we take the same amount? or
78 * should I do 1/2 the SB_MAX instead in the SB_MAX min above. For
79 * now I will just copy.
81 SCTP_BASE_SYSCTL(sctp_recvspace) = SCTP_BASE_SYSCTL(sctp_sendspace);
82 SCTP_BASE_VAR(first_time) = 0;
83 SCTP_BASE_VAR(sctp_pcb_initialized) = 0;
85 #if defined(SCTP_PACKET_LOGGING)
86 SCTP_BASE_VAR(packet_log_writers) = 0;
87 SCTP_BASE_VAR(packet_log_end) = 0;
88 bzero(&SCTP_BASE_VAR(packet_log_buffer), SCTP_PACKET_LOG_SIZE);
101 sctp_pathmtu_adjustment(struct sctp_tcb *stcb, uint16_t nxtsz)
103 struct sctp_tmit_chunk *chk;
106 /* Adjust that too */
107 stcb->asoc.smallest_mtu = nxtsz;
108 /* now off to subtract IP_DF flag if needed */
109 overhead = IP_HDR_SIZE;
110 if (sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.peer_auth_chunks)) {
111 overhead += sctp_get_auth_chunk_len(stcb->asoc.peer_hmac_id);
113 TAILQ_FOREACH(chk, &stcb->asoc.send_queue, sctp_next) {
114 if ((chk->send_size + overhead) > nxtsz) {
115 chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
118 TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
119 if ((chk->send_size + overhead) > nxtsz) {
121 * For this guy we also mark for immediate resend
122 * since we sent to big of chunk
124 chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
125 if (chk->sent < SCTP_DATAGRAM_RESEND) {
126 sctp_flight_size_decrease(chk);
127 sctp_total_flight_decrease(stcb, chk);
128 chk->sent = SCTP_DATAGRAM_RESEND;
129 sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
130 chk->rec.data.doing_fast_retransmit = 0;
131 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) {
132 sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_PMTU,
133 chk->whoTo->flight_size,
135 (uint32_t) (uintptr_t) chk->whoTo,
136 chk->rec.data.TSN_seq);
138 /* Clear any time so NO RTT is being done */
147 sctp_notify(struct sctp_inpcb *inp,
148 struct sctp_tcb *stcb,
149 struct sctp_nets *net,
155 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
161 if (icmp_type != ICMP_UNREACH) {
162 /* We only care about unreachable */
163 SCTP_TCB_UNLOCK(stcb);
166 if ((icmp_code == ICMP_UNREACH_NET) ||
167 (icmp_code == ICMP_UNREACH_HOST) ||
168 (icmp_code == ICMP_UNREACH_NET_UNKNOWN) ||
169 (icmp_code == ICMP_UNREACH_HOST_UNKNOWN) ||
170 (icmp_code == ICMP_UNREACH_ISOLATED) ||
171 (icmp_code == ICMP_UNREACH_NET_PROHIB) ||
172 (icmp_code == ICMP_UNREACH_HOST_PROHIB) ||
173 (icmp_code == ICMP_UNREACH_FILTER_PROHIB)) {
176 * Hmm reachablity problems we must examine closely. If its
177 * not reachable, we may have lost a network. Or if there is
178 * NO protocol at the other end named SCTP. well we consider
181 if (net->dest_state & SCTP_ADDR_REACHABLE) {
182 /* OK, that destination is NOT reachable. */
183 net->dest_state &= ~SCTP_ADDR_REACHABLE;
184 net->dest_state &= ~SCTP_ADDR_PF;
185 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
187 (void *)net, SCTP_SO_NOT_LOCKED);
189 SCTP_TCB_UNLOCK(stcb);
190 } else if ((icmp_code == ICMP_UNREACH_PROTOCOL) ||
191 (icmp_code == ICMP_UNREACH_PORT)) {
193 * Here the peer is either playing tricks on us, including
194 * an address that belongs to someone who does not support
195 * SCTP OR was a userland implementation that shutdown and
196 * now is dead. In either case treat it like a OOTB abort
199 sctp_abort_notification(stcb, 1, 0, NULL, SCTP_SO_NOT_LOCKED);
200 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
201 so = SCTP_INP_SO(inp);
202 atomic_add_int(&stcb->asoc.refcnt, 1);
203 SCTP_TCB_UNLOCK(stcb);
204 SCTP_SOCKET_LOCK(so, 1);
206 atomic_subtract_int(&stcb->asoc.refcnt, 1);
208 (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
209 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_2);
210 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
211 SCTP_SOCKET_UNLOCK(so, 1);
212 /* SCTP_TCB_UNLOCK(stcb); MT: I think this is not needed. */
214 /* no need to unlock here, since the TCB is gone */
215 } else if (icmp_code == ICMP_UNREACH_NEEDFRAG) {
216 /* Find the next (smaller) MTU */
219 * Old type router that does not tell us what the
220 * next MTU is. Rats we will have to guess (in a
221 * educated fashion of course).
223 next_mtu = sctp_get_prev_mtu(ip_len);
225 /* Stop the PMTU timer. */
226 if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
228 sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
229 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_1);
233 /* Update the path MTU. */
234 if (net->mtu > next_mtu) {
237 net->mtu -= sizeof(struct udphdr);
240 /* Update the association MTU */
241 if (stcb->asoc.smallest_mtu > next_mtu) {
242 sctp_pathmtu_adjustment(stcb, next_mtu);
244 /* Finally, start the PMTU timer if it was running before. */
246 sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
248 SCTP_TCB_UNLOCK(stcb);
250 SCTP_TCB_UNLOCK(stcb);
255 sctp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
262 /* FIX, for non-bsd is this right? */
263 vrf_id = SCTP_DEFAULT_VRFID;
264 if (sa->sa_family != AF_INET ||
265 ((struct sockaddr_in *)sa)->sin_addr.s_addr == INADDR_ANY) {
268 if (PRC_IS_REDIRECT(cmd)) {
270 } else if ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0) {
274 struct sctp_inpcb *inp = NULL;
275 struct sctp_tcb *stcb = NULL;
276 struct sctp_nets *net = NULL;
277 struct sockaddr_in to, from;
279 icmph = (struct icmp *)((caddr_t)ip - (sizeof(struct icmp) -
282 sh = (struct sctphdr *)((caddr_t)ip + (ip->ip_hl << 2));
283 bzero(&to, sizeof(to));
284 bzero(&from, sizeof(from));
285 from.sin_family = to.sin_family = AF_INET;
286 from.sin_len = to.sin_len = sizeof(to);
287 from.sin_port = sh->src_port;
288 from.sin_addr = ip->ip_src;
289 to.sin_port = sh->dest_port;
290 to.sin_addr = ip->ip_dst;
292 * 'to' holds the dest of the packet that failed to be sent.
293 * 'from' holds our local endpoint address. Thus we reverse
294 * the to and the from in the lookup.
296 stcb = sctp_findassociation_addr_sa((struct sockaddr *)&to,
297 (struct sockaddr *)&from,
298 &inp, &net, 1, vrf_id);
299 if ((stcb != NULL) &&
302 (inp->sctp_socket != NULL)) {
303 /* Check the verification tag */
304 if (ntohl(sh->v_tag) != 0) {
306 * This must be the verification tag used
307 * for sending out packets. We don't
308 * consider packets reflecting the
311 if (ntohl(sh->v_tag) != stcb->asoc.peer_vtag) {
312 SCTP_TCB_UNLOCK(stcb);
317 * In this case we could check if we got an
318 * INIT chunk and if the initiate tag
319 * matches. But this is not there yet...
321 SCTP_TCB_UNLOCK(stcb);
324 sctp_notify(inp, stcb, net,
328 ntohs(icmph->icmp_nextmtu));
330 if ((stcb == NULL) && (inp != NULL)) {
331 /* reduce ref-count */
333 SCTP_INP_DECR_REF(inp);
334 SCTP_INP_WUNLOCK(inp);
337 SCTP_TCB_UNLOCK(stcb);
347 sctp_getcred(SYSCTL_HANDLER_ARGS)
350 struct sockaddr_in addrs[2];
351 struct sctp_inpcb *inp;
352 struct sctp_nets *net;
353 struct sctp_tcb *stcb;
357 /* FIX, for non-bsd is this right? */
358 vrf_id = SCTP_DEFAULT_VRFID;
360 error = priv_check(req->td, PRIV_NETINET_GETCRED);
365 error = SYSCTL_IN(req, addrs, sizeof(addrs));
369 stcb = sctp_findassociation_addr_sa(sintosa(&addrs[1]),
371 &inp, &net, 1, vrf_id);
372 if (stcb == NULL || inp == NULL || inp->sctp_socket == NULL) {
373 if ((inp != NULL) && (stcb == NULL)) {
374 /* reduce ref-count */
376 SCTP_INP_DECR_REF(inp);
379 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
383 SCTP_TCB_UNLOCK(stcb);
385 * We use the write lock here, only since in the error leg we need
386 * it. If we used RLOCK, then we would have to
387 * wlock/decr/unlock/rlock. Which in theory could create a hole.
388 * Better to use higher wlock.
392 error = cr_canseesocket(req->td->td_ucred, inp->sctp_socket);
394 SCTP_INP_WUNLOCK(inp);
397 cru2x(inp->sctp_socket->so_cred, &xuc);
398 SCTP_INP_WUNLOCK(inp);
399 error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
404 SYSCTL_PROC(_net_inet_sctp, OID_AUTO, getcred, CTLTYPE_OPAQUE | CTLFLAG_RW,
405 0, 0, sctp_getcred, "S,ucred", "Get the ucred of a SCTP connection");
410 sctp_abort(struct socket *so)
412 struct sctp_inpcb *inp;
415 inp = (struct sctp_inpcb *)so->so_pcb;
420 flags = inp->sctp_flags;
421 #ifdef SCTP_LOG_CLOSING
422 sctp_log_closing(inp, NULL, 17);
424 if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
425 (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
426 #ifdef SCTP_LOG_CLOSING
427 sctp_log_closing(inp, NULL, 16);
429 sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
430 SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
432 SCTP_SB_CLEAR(so->so_snd);
434 * same for the rcv ones, they are only here for the
437 SCTP_SB_CLEAR(so->so_rcv);
439 /* Now null out the reference, we are completely detached. */
443 flags = inp->sctp_flags;
444 if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
445 goto sctp_must_try_again;
452 sctp_attach(struct socket *so, int proto SCTP_UNUSED, struct thread *p SCTP_UNUSED)
454 struct sctp_inpcb *inp;
455 struct inpcb *ip_inp;
457 uint32_t vrf_id = SCTP_DEFAULT_VRFID;
459 inp = (struct sctp_inpcb *)so->so_pcb;
461 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
464 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
465 error = SCTP_SORESERVE(so, SCTP_BASE_SYSCTL(sctp_sendspace), SCTP_BASE_SYSCTL(sctp_recvspace));
470 error = sctp_inpcb_alloc(so, vrf_id);
474 inp = (struct sctp_inpcb *)so->so_pcb;
476 inp->sctp_flags &= ~SCTP_PCB_FLAGS_BOUND_V6; /* I'm not v6! */
477 ip_inp = &inp->ip_inp.inp;
478 ip_inp->inp_vflag |= INP_IPV4;
479 ip_inp->inp_ip_ttl = MODULE_GLOBAL(ip_defttl);
480 SCTP_INP_WUNLOCK(inp);
485 sctp_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
487 struct sctp_inpcb *inp;
489 inp = (struct sctp_inpcb *)so->so_pcb;
491 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
495 if ((addr->sa_family != AF_INET) ||
496 (addr->sa_len != sizeof(struct sockaddr_in))) {
497 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
501 return (sctp_inpcb_bind(so, addr, NULL, p));
506 sctp_close(struct socket *so)
508 struct sctp_inpcb *inp;
511 inp = (struct sctp_inpcb *)so->so_pcb;
516 * Inform all the lower layer assoc that we are done.
519 flags = inp->sctp_flags;
520 #ifdef SCTP_LOG_CLOSING
521 sctp_log_closing(inp, NULL, 17);
523 if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
524 (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
525 if (((so->so_options & SO_LINGER) && (so->so_linger == 0)) ||
526 (so->so_rcv.sb_cc > 0)) {
527 #ifdef SCTP_LOG_CLOSING
528 sctp_log_closing(inp, NULL, 13);
530 sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
531 SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
533 #ifdef SCTP_LOG_CLOSING
534 sctp_log_closing(inp, NULL, 14);
536 sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_GRACEFUL_CLOSE,
537 SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
540 * The socket is now detached, no matter what the state of
541 * the SCTP association.
544 SCTP_SB_CLEAR(so->so_snd);
546 * same for the rcv ones, they are only here for the
549 SCTP_SB_CLEAR(so->so_rcv);
551 /* Now null out the reference, we are completely detached. */
555 flags = inp->sctp_flags;
556 if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
557 goto sctp_must_try_again;
565 sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
566 struct mbuf *control, struct thread *p);
570 sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
571 struct mbuf *control, struct thread *p)
573 struct sctp_inpcb *inp;
576 inp = (struct sctp_inpcb *)so->so_pcb;
579 sctp_m_freem(control);
582 SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
586 /* Got to have an to address if we are NOT a connected socket */
587 if ((addr == NULL) &&
588 ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) ||
589 (inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE))) {
591 } else if (addr == NULL) {
592 SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EDESTADDRREQ);
593 error = EDESTADDRREQ;
596 sctp_m_freem(control);
602 if (addr->sa_family != AF_INET) {
603 /* must be a v4 address! */
604 SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EDESTADDRREQ);
607 sctp_m_freem(control);
610 error = EDESTADDRREQ;
615 /* now what about control */
618 SCTP_PRINTF("huh? control set?\n");
619 sctp_m_freem(inp->control);
622 inp->control = control;
626 SCTP_BUF_NEXT(inp->pkt_last) = m;
629 inp->pkt_last = inp->pkt = m;
632 /* FreeBSD uses a flag passed */
633 ((flags & PRUS_MORETOCOME) == 0)
636 * note with the current version this code will only be used
637 * by OpenBSD-- NetBSD, FreeBSD, and MacOS have methods for
638 * re-defining sosend to use the sctp_sosend. One can
639 * optionally switch back to this code (by changing back the
640 * definitions) but this is not advisable. This code is used
641 * by FreeBSD when sending a file with sendfile() though.
645 ret = sctp_output(inp, inp->pkt, addr, inp->control, p, flags);
655 sctp_disconnect(struct socket *so)
657 struct sctp_inpcb *inp;
659 inp = (struct sctp_inpcb *)so->so_pcb;
661 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
665 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
666 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
667 if (LIST_EMPTY(&inp->sctp_asoc_list)) {
669 SCTP_INP_RUNLOCK(inp);
672 struct sctp_association *asoc;
673 struct sctp_tcb *stcb;
675 stcb = LIST_FIRST(&inp->sctp_asoc_list);
677 SCTP_INP_RUNLOCK(inp);
678 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
683 if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
684 /* We are about to be freed, out of here */
685 SCTP_TCB_UNLOCK(stcb);
686 SCTP_INP_RUNLOCK(inp);
689 if (((so->so_options & SO_LINGER) &&
690 (so->so_linger == 0)) ||
691 (so->so_rcv.sb_cc > 0)) {
692 if (SCTP_GET_STATE(asoc) !=
693 SCTP_STATE_COOKIE_WAIT) {
694 /* Left with Data unread */
697 err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), 0, M_NOWAIT, 1, MT_DATA);
703 struct sctp_paramhdr *ph;
705 ph = mtod(err, struct sctp_paramhdr *);
706 SCTP_BUF_LEN(err) = sizeof(struct sctp_paramhdr);
707 ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
708 ph->param_length = htons(SCTP_BUF_LEN(err));
710 sctp_send_abort_tcb(stcb, err, SCTP_SO_LOCKED);
711 SCTP_STAT_INCR_COUNTER32(sctps_aborted);
713 SCTP_INP_RUNLOCK(inp);
714 if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
715 (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
716 SCTP_STAT_DECR_GAUGE32(sctps_currestab);
718 (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
719 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_3);
720 /* No unlock tcb assoc is gone */
723 if (TAILQ_EMPTY(&asoc->send_queue) &&
724 TAILQ_EMPTY(&asoc->sent_queue) &&
725 (asoc->stream_queue_cnt == 0)) {
726 /* there is nothing queued to send, so done */
727 if (asoc->locked_on_sending) {
730 if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) &&
731 (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
732 /* only send SHUTDOWN 1st time thru */
733 struct sctp_nets *netp;
735 if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
736 (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
737 SCTP_STAT_DECR_GAUGE32(sctps_currestab);
739 SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
740 SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
741 sctp_stop_timers_for_shutdown(stcb);
742 if (stcb->asoc.alternate) {
743 netp = stcb->asoc.alternate;
745 netp = stcb->asoc.primary_destination;
747 sctp_send_shutdown(stcb, netp);
748 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
749 stcb->sctp_ep, stcb, netp);
750 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
751 stcb->sctp_ep, stcb, netp);
752 sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_LOCKED);
756 * we still got (or just got) data to send,
757 * so set SHUTDOWN_PENDING
760 * XXX sockets draft says that SCTP_EOF
761 * should be sent with no data. currently,
762 * we will allow user data to be sent first
763 * and move to SHUTDOWN-PENDING
765 struct sctp_nets *netp;
767 if (stcb->asoc.alternate) {
768 netp = stcb->asoc.alternate;
770 netp = stcb->asoc.primary_destination;
773 asoc->state |= SCTP_STATE_SHUTDOWN_PENDING;
774 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb,
776 if (asoc->locked_on_sending) {
777 /* Locked to send out the data */
778 struct sctp_stream_queue_pending *sp;
780 sp = TAILQ_LAST(&asoc->locked_on_sending->outqueue, sctp_streamhead);
782 SCTP_PRINTF("Error, sp is NULL, locked on sending is non-null strm:%d\n",
783 asoc->locked_on_sending->stream_no);
785 if ((sp->length == 0) && (sp->msg_is_complete == 0))
786 asoc->state |= SCTP_STATE_PARTIAL_MSG_LEFT;
789 if (TAILQ_EMPTY(&asoc->send_queue) &&
790 TAILQ_EMPTY(&asoc->sent_queue) &&
791 (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
795 op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
796 stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_4;
797 sctp_send_abort_tcb(stcb, op_err, SCTP_SO_LOCKED);
798 SCTP_STAT_INCR_COUNTER32(sctps_aborted);
799 if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
800 (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
801 SCTP_STAT_DECR_GAUGE32(sctps_currestab);
803 SCTP_INP_RUNLOCK(inp);
804 (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
805 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_5);
808 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
811 soisdisconnecting(so);
812 SCTP_TCB_UNLOCK(stcb);
813 SCTP_INP_RUNLOCK(inp);
818 /* UDP model does not support this */
819 SCTP_INP_RUNLOCK(inp);
820 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
826 sctp_flush(struct socket *so, int how)
829 * We will just clear out the values and let subsequent close clear
830 * out the data, if any. Note if the user did a shutdown(SHUT_RD)
831 * they will not be able to read the data, the socket will block
832 * that from happening.
834 struct sctp_inpcb *inp;
836 inp = (struct sctp_inpcb *)so->so_pcb;
838 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
842 /* For the 1 to many model this does nothing */
843 if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
844 SCTP_INP_RUNLOCK(inp);
847 SCTP_INP_RUNLOCK(inp);
848 if ((how == PRU_FLUSH_RD) || (how == PRU_FLUSH_RDWR)) {
850 * First make sure the sb will be happy, we don't use these
851 * except maybe the count
854 SCTP_INP_READ_LOCK(inp);
855 inp->sctp_flags |= SCTP_PCB_FLAGS_SOCKET_CANT_READ;
856 SCTP_INP_READ_UNLOCK(inp);
857 SCTP_INP_WUNLOCK(inp);
858 so->so_rcv.sb_cc = 0;
859 so->so_rcv.sb_mbcnt = 0;
860 so->so_rcv.sb_mb = NULL;
862 if ((how == PRU_FLUSH_WR) || (how == PRU_FLUSH_RDWR)) {
864 * First make sure the sb will be happy, we don't use these
865 * except maybe the count
867 so->so_snd.sb_cc = 0;
868 so->so_snd.sb_mbcnt = 0;
869 so->so_snd.sb_mb = NULL;
876 sctp_shutdown(struct socket *so)
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);
886 /* For UDP model this is a invalid call */
887 if (!((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
888 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) {
889 /* Restore the flags that the soshutdown took away. */
890 SOCKBUF_LOCK(&so->so_rcv);
891 so->so_rcv.sb_state &= ~SBS_CANTRCVMORE;
892 SOCKBUF_UNLOCK(&so->so_rcv);
893 /* This proc will wakeup for read and do nothing (I hope) */
894 SCTP_INP_RUNLOCK(inp);
895 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
899 * Ok, if we reach here its the TCP model and it is either a
900 * SHUT_WR or SHUT_RDWR. This means we put the shutdown flag
903 struct sctp_tcb *stcb;
904 struct sctp_association *asoc;
905 struct sctp_nets *netp;
908 (SS_ISCONNECTED | SS_ISCONNECTING | SS_ISDISCONNECTING)) == 0) {
909 SCTP_INP_RUNLOCK(inp);
914 stcb = LIST_FIRST(&inp->sctp_asoc_list);
917 * Ok, we hit the case that the shutdown call was
918 * made after an abort or something. Nothing to do
921 SCTP_INP_RUNLOCK(inp);
926 if (asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) {
927 SCTP_TCB_UNLOCK(stcb);
928 SCTP_INP_RUNLOCK(inp);
931 if ((SCTP_GET_STATE(asoc) != SCTP_STATE_COOKIE_WAIT) &&
932 (SCTP_GET_STATE(asoc) != SCTP_STATE_COOKIE_ECHOED) &&
933 (SCTP_GET_STATE(asoc) != SCTP_STATE_OPEN)) {
935 * If we are not in or before ESTABLISHED, there is
936 * no protocol action required.
938 SCTP_TCB_UNLOCK(stcb);
939 SCTP_INP_RUNLOCK(inp);
942 if (stcb->asoc.alternate) {
943 netp = stcb->asoc.alternate;
945 netp = stcb->asoc.primary_destination;
947 if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) &&
948 TAILQ_EMPTY(&asoc->send_queue) &&
949 TAILQ_EMPTY(&asoc->sent_queue) &&
950 (asoc->stream_queue_cnt == 0)) {
951 if (asoc->locked_on_sending) {
954 /* there is nothing queued to send, so I'm done... */
955 SCTP_STAT_DECR_GAUGE32(sctps_currestab);
956 SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
957 SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
958 sctp_stop_timers_for_shutdown(stcb);
959 sctp_send_shutdown(stcb, netp);
960 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
961 stcb->sctp_ep, stcb, netp);
964 * We still got (or just got) data to send, so set
967 SCTP_ADD_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
968 if (asoc->locked_on_sending) {
969 /* Locked to send out the data */
970 struct sctp_stream_queue_pending *sp;
972 sp = TAILQ_LAST(&asoc->locked_on_sending->outqueue, sctp_streamhead);
974 SCTP_PRINTF("Error, sp is NULL, locked on sending is non-null strm:%d\n",
975 asoc->locked_on_sending->stream_no);
977 if ((sp->length == 0) && (sp->msg_is_complete == 0)) {
978 SCTP_ADD_SUBSTATE(asoc, SCTP_STATE_PARTIAL_MSG_LEFT);
982 if (TAILQ_EMPTY(&asoc->send_queue) &&
983 TAILQ_EMPTY(&asoc->sent_queue) &&
984 (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
988 op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
989 stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6;
990 sctp_abort_an_association(stcb->sctp_ep, stcb,
991 op_err, SCTP_SO_LOCKED);
992 SCTP_INP_RUNLOCK(inp);
996 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb, netp);
998 * XXX: Why do this in the case where we have still data
1001 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
1002 SCTP_TCB_UNLOCK(stcb);
1003 SCTP_INP_RUNLOCK(inp);
1009 * copies a "user" presentable address and removes embedded scope, etc.
1010 * returns 0 on success, 1 on error
1013 sctp_fill_user_address(struct sockaddr_storage *ss, struct sockaddr *sa)
1016 struct sockaddr_in6 lsa6;
1018 sa = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)sa,
1021 memcpy(ss, sa, sa->sa_len);
1028 * NOTE: assumes addr lock is held
1031 sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp,
1032 struct sctp_tcb *stcb,
1034 struct sockaddr_storage *sas,
1037 struct sctp_ifn *sctp_ifn;
1038 struct sctp_ifa *sctp_ifa;
1043 int ipv4_local_scope, ipv4_addr_legal;
1047 int local_scope, site_scope, ipv6_addr_legal;
1050 struct sctp_vrf *vrf;
1057 /* Turn on all the appropriate scope */
1058 loopback_scope = stcb->asoc.scope.loopback_scope;
1060 ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope;
1061 ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal;
1064 local_scope = stcb->asoc.scope.local_scope;
1065 site_scope = stcb->asoc.scope.site_scope;
1066 ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal;
1069 /* Use generic values for endpoints. */
1072 ipv4_local_scope = 1;
1078 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
1080 ipv6_addr_legal = 1;
1083 if (SCTP_IPV6_V6ONLY(inp)) {
1084 ipv4_addr_legal = 0;
1086 ipv4_addr_legal = 1;
1091 ipv6_addr_legal = 0;
1094 ipv4_addr_legal = 1;
1098 vrf = sctp_find_vrf(vrf_id);
1102 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
1103 LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
1104 if ((loopback_scope == 0) &&
1105 SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
1106 /* Skip loopback if loopback_scope not set */
1109 LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
1112 * For the BOUND-ALL case, the list
1113 * associated with a TCB is Always
1114 * considered a reverse list.. i.e.
1115 * it lists addresses that are NOT
1116 * part of the association. If this
1117 * is one of those we must skip it.
1119 if (sctp_is_addr_restricted(stcb,
1124 switch (sctp_ifa->address.sa.sa_family) {
1127 if (ipv4_addr_legal) {
1128 struct sockaddr_in *sin;
1130 sin = &sctp_ifa->address.sin;
1131 if (sin->sin_addr.s_addr == 0) {
1139 if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
1140 &sin->sin_addr) != 0) {
1143 if ((ipv4_local_scope == 0) &&
1144 (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) {
1148 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
1149 in6_sin_2_v4mapsin6(sin, (struct sockaddr_in6 *)sas);
1150 ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
1151 sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(struct sockaddr_in6));
1152 actual += sizeof(struct sockaddr_in6);
1155 memcpy(sas, sin, sizeof(*sin));
1156 ((struct sockaddr_in *)sas)->sin_port = inp->sctp_lport;
1157 sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(*sin));
1158 actual += sizeof(*sin);
1162 if (actual >= limit) {
1172 if (ipv6_addr_legal) {
1173 struct sockaddr_in6 *sin6;
1175 sin6 = &sctp_ifa->address.sin6;
1176 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
1184 if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
1185 &sin6->sin6_addr) != 0) {
1188 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
1189 if (local_scope == 0)
1191 if (sin6->sin6_scope_id == 0) {
1192 if (sa6_recoverscope(sin6) != 0)
1210 if ((site_scope == 0) &&
1211 (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) {
1214 memcpy(sas, sin6, sizeof(*sin6));
1215 ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
1216 sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(*sin6));
1217 actual += sizeof(*sin6);
1218 if (actual >= limit) {
1233 struct sctp_laddr *laddr;
1235 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
1237 if (sctp_is_addr_restricted(stcb, laddr->ifa)) {
1241 if (sctp_fill_user_address(sas, &laddr->ifa->address.sa))
1243 switch (laddr->ifa->address.sa.sa_family) {
1246 ((struct sockaddr_in *)sas)->sin_port = inp->sctp_lport;
1251 ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
1258 sas = (struct sockaddr_storage *)((caddr_t)sas +
1259 laddr->ifa->address.sa.sa_len);
1260 actual += laddr->ifa->address.sa.sa_len;
1261 if (actual >= limit) {
1270 sctp_fill_up_addresses(struct sctp_inpcb *inp,
1271 struct sctp_tcb *stcb,
1273 struct sockaddr_storage *sas)
1277 SCTP_IPI_ADDR_RLOCK();
1278 /* fill up addresses for the endpoint's default vrf */
1279 size = sctp_fill_up_addresses_vrf(inp, stcb, limit, sas,
1281 SCTP_IPI_ADDR_RUNLOCK();
1286 * NOTE: assumes addr lock is held
1289 sctp_count_max_addresses_vrf(struct sctp_inpcb *inp, uint32_t vrf_id)
1292 struct sctp_vrf *vrf = NULL;
1295 * In both sub-set bound an bound_all cases we return the MAXIMUM
1296 * number of addresses that you COULD get. In reality the sub-set
1297 * bound may have an exclusion list for a given TCB OR in the
1298 * bound-all case a TCB may NOT include the loopback or other
1299 * addresses as well.
1301 vrf = sctp_find_vrf(vrf_id);
1305 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
1306 struct sctp_ifn *sctp_ifn;
1307 struct sctp_ifa *sctp_ifa;
1309 LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
1310 LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
1311 /* Count them if they are the right type */
1312 switch (sctp_ifa->address.sa.sa_family) {
1316 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4))
1317 cnt += sizeof(struct sockaddr_in6);
1319 cnt += sizeof(struct sockaddr_in);
1321 cnt += sizeof(struct sockaddr_in);
1327 cnt += sizeof(struct sockaddr_in6);
1336 struct sctp_laddr *laddr;
1338 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
1339 switch (laddr->ifa->address.sa.sa_family) {
1343 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4))
1344 cnt += sizeof(struct sockaddr_in6);
1346 cnt += sizeof(struct sockaddr_in);
1348 cnt += sizeof(struct sockaddr_in);
1354 cnt += sizeof(struct sockaddr_in6);
1366 sctp_count_max_addresses(struct sctp_inpcb *inp)
1370 SCTP_IPI_ADDR_RLOCK();
1371 /* count addresses for the endpoint's default VRF */
1372 cnt = sctp_count_max_addresses_vrf(inp, inp->def_vrf_id);
1373 SCTP_IPI_ADDR_RUNLOCK();
1378 sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
1379 size_t optsize, void *p, int delay)
1382 int creat_lock_on = 0;
1383 struct sctp_tcb *stcb = NULL;
1384 struct sockaddr *sa;
1385 unsigned int num_v6 = 0, num_v4 = 0, *totaddrp, totaddr;
1387 int bad_addresses = 0;
1390 SCTPDBG(SCTP_DEBUG_PCB1, "Connectx called\n");
1392 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
1393 (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
1394 /* We are already connected AND the TCP model */
1395 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
1396 return (EADDRINUSE);
1398 if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
1399 (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
1400 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1403 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
1404 SCTP_INP_RLOCK(inp);
1405 stcb = LIST_FIRST(&inp->sctp_asoc_list);
1406 SCTP_INP_RUNLOCK(inp);
1409 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
1412 SCTP_INP_INCR_REF(inp);
1413 SCTP_ASOC_CREATE_LOCK(inp);
1415 if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
1416 (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
1417 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
1421 totaddrp = (unsigned int *)optval;
1422 totaddr = *totaddrp;
1423 sa = (struct sockaddr *)(totaddrp + 1);
1424 stcb = sctp_connectx_helper_find(inp, sa, &totaddr, &num_v4, &num_v6, &error, (unsigned int)(optsize - sizeof(int)), &bad_addresses);
1425 if ((stcb != NULL) || bad_addresses) {
1426 /* Already have or am bring up an association */
1427 SCTP_ASOC_CREATE_UNLOCK(inp);
1430 SCTP_TCB_UNLOCK(stcb);
1431 if (bad_addresses == 0) {
1432 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
1438 if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
1443 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
1445 struct in6pcb *inp6;
1447 inp6 = (struct in6pcb *)inp;
1448 if (SCTP_IPV6_V6ONLY(inp6)) {
1450 * if IPV6_V6ONLY flag, ignore connections destined
1451 * to a v4 addr or v4-mapped addr
1453 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1459 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
1460 SCTP_PCB_FLAGS_UNBOUND) {
1461 /* Bind a ephemeral port */
1462 error = sctp_inpcb_bind(so, NULL, NULL, p);
1467 /* FIX ME: do we want to pass in a vrf on the connect call? */
1468 vrf_id = inp->def_vrf_id;
1471 /* We are GOOD to go */
1472 stcb = sctp_aloc_assoc(inp, sa, &error, 0, vrf_id,
1473 inp->sctp_ep.pre_open_stream_count,
1477 /* Gak! no memory */
1480 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
1481 stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
1482 /* Set the connected flag so we can queue data */
1485 SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
1486 /* move to second address */
1487 switch (sa->sa_family) {
1490 sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in));
1495 sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in6));
1503 sctp_connectx_helper_add(stcb, sa, (totaddr - 1), &error);
1504 /* Fill in the return id */
1506 (void)sctp_free_assoc(inp, stcb, SCTP_PCBFREE_FORCE,
1507 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_7);
1510 a_id = (sctp_assoc_t *) optval;
1511 *a_id = sctp_get_associd(stcb);
1513 /* initialize authentication parameters for the assoc */
1514 sctp_initialize_auth_params(inp, stcb);
1517 /* doing delayed connection */
1518 stcb->asoc.delayed_connection = 1;
1519 sctp_timer_start(SCTP_TIMER_TYPE_INIT, inp, stcb, stcb->asoc.primary_destination);
1521 (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
1522 sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
1524 SCTP_TCB_UNLOCK(stcb);
1525 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
1526 stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
1527 /* Set the connected flag so we can queue data */
1531 if (creat_lock_on) {
1532 SCTP_ASOC_CREATE_UNLOCK(inp);
1534 SCTP_INP_DECR_REF(inp);
1538 #define SCTP_FIND_STCB(inp, stcb, assoc_id) { \
1539 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||\
1540 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { \
1541 SCTP_INP_RLOCK(inp); \
1542 stcb = LIST_FIRST(&inp->sctp_asoc_list); \
1544 SCTP_TCB_LOCK(stcb); \
1546 SCTP_INP_RUNLOCK(inp); \
1547 } else if (assoc_id > SCTP_ALL_ASSOC) { \
1548 stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1); \
1549 if (stcb == NULL) { \
1550 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT); \
1560 #define SCTP_CHECK_AND_CAST(destp, srcp, type, size) {\
1561 if (size < sizeof(type)) { \
1562 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); \
1566 destp = (type *)srcp; \
1571 sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
1574 struct sctp_inpcb *inp = NULL;
1576 struct sctp_tcb *stcb = NULL;
1578 if (optval == NULL) {
1579 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1582 inp = (struct sctp_inpcb *)so->so_pcb;
1584 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1591 case SCTP_AUTOCLOSE:
1592 case SCTP_EXPLICIT_EOR:
1593 case SCTP_AUTO_ASCONF:
1594 case SCTP_DISABLE_FRAGMENTS:
1595 case SCTP_I_WANT_MAPPED_V4_ADDR:
1596 case SCTP_USE_EXT_RCVINFO:
1597 SCTP_INP_RLOCK(inp);
1599 case SCTP_DISABLE_FRAGMENTS:
1600 val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NO_FRAGMENT);
1602 case SCTP_I_WANT_MAPPED_V4_ADDR:
1603 val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4);
1605 case SCTP_AUTO_ASCONF:
1606 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
1607 /* only valid for bound all sockets */
1608 val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTO_ASCONF);
1610 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1615 case SCTP_EXPLICIT_EOR:
1616 val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR);
1619 val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NODELAY);
1621 case SCTP_USE_EXT_RCVINFO:
1622 val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO);
1624 case SCTP_AUTOCLOSE:
1625 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE))
1626 val = TICKS_TO_SEC(inp->sctp_ep.auto_close_time);
1632 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
1633 error = ENOPROTOOPT;
1634 } /* end switch (sopt->sopt_name) */
1635 if (*optsize < sizeof(val)) {
1636 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1640 SCTP_INP_RUNLOCK(inp);
1642 /* return the option value */
1643 *(int *)optval = val;
1644 *optsize = sizeof(val);
1647 case SCTP_GET_PACKET_LOG:
1649 #ifdef SCTP_PACKET_LOGGING
1653 SCTP_CHECK_AND_CAST(target, optval, uint8_t, *optsize);
1654 ret = sctp_copy_out_packet_log(target, (int)*optsize);
1657 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
1662 case SCTP_REUSE_PORT:
1666 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
1667 /* Can't do this for a 1-m socket */
1671 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
1672 *value = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE);
1673 *optsize = sizeof(uint32_t);
1676 case SCTP_PARTIAL_DELIVERY_POINT:
1680 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
1681 *value = inp->partial_delivery_point;
1682 *optsize = sizeof(uint32_t);
1685 case SCTP_FRAGMENT_INTERLEAVE:
1689 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
1690 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE)) {
1691 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS)) {
1692 *value = SCTP_FRAG_LEVEL_2;
1694 *value = SCTP_FRAG_LEVEL_1;
1697 *value = SCTP_FRAG_LEVEL_0;
1699 *optsize = sizeof(uint32_t);
1702 case SCTP_INTERLEAVING_SUPPORTED:
1704 struct sctp_assoc_value *av;
1706 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
1707 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
1710 av->assoc_value = stcb->asoc.idata_supported;
1711 SCTP_TCB_UNLOCK(stcb);
1713 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1714 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
1715 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
1716 SCTP_INP_RLOCK(inp);
1717 if (inp->idata_supported) {
1718 av->assoc_value = 1;
1720 av->assoc_value = 0;
1722 SCTP_INP_RUNLOCK(inp);
1724 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1729 *optsize = sizeof(struct sctp_assoc_value);
1733 case SCTP_CMT_ON_OFF:
1735 struct sctp_assoc_value *av;
1737 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
1738 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
1740 av->assoc_value = stcb->asoc.sctp_cmt_on_off;
1741 SCTP_TCB_UNLOCK(stcb);
1743 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1744 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
1745 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
1746 SCTP_INP_RLOCK(inp);
1747 av->assoc_value = inp->sctp_cmt_on_off;
1748 SCTP_INP_RUNLOCK(inp);
1750 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1755 *optsize = sizeof(struct sctp_assoc_value);
1759 case SCTP_PLUGGABLE_CC:
1761 struct sctp_assoc_value *av;
1763 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
1764 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
1766 av->assoc_value = stcb->asoc.congestion_control_module;
1767 SCTP_TCB_UNLOCK(stcb);
1769 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1770 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
1771 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
1772 SCTP_INP_RLOCK(inp);
1773 av->assoc_value = inp->sctp_ep.sctp_default_cc_module;
1774 SCTP_INP_RUNLOCK(inp);
1776 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1781 *optsize = sizeof(struct sctp_assoc_value);
1785 case SCTP_CC_OPTION:
1787 struct sctp_cc_option *cc_opt;
1789 SCTP_CHECK_AND_CAST(cc_opt, optval, struct sctp_cc_option, *optsize);
1790 SCTP_FIND_STCB(inp, stcb, cc_opt->aid_value.assoc_id);
1794 if (stcb->asoc.cc_functions.sctp_cwnd_socket_option == NULL) {
1797 error = (*stcb->asoc.cc_functions.sctp_cwnd_socket_option) (stcb, 0, cc_opt);
1798 *optsize = sizeof(struct sctp_cc_option);
1800 SCTP_TCB_UNLOCK(stcb);
1804 case SCTP_PLUGGABLE_SS:
1806 struct sctp_assoc_value *av;
1808 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
1809 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
1811 av->assoc_value = stcb->asoc.stream_scheduling_module;
1812 SCTP_TCB_UNLOCK(stcb);
1814 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1815 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
1816 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
1817 SCTP_INP_RLOCK(inp);
1818 av->assoc_value = inp->sctp_ep.sctp_default_ss_module;
1819 SCTP_INP_RUNLOCK(inp);
1821 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1826 *optsize = sizeof(struct sctp_assoc_value);
1832 struct sctp_stream_value *av;
1834 SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, *optsize);
1835 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
1837 if ((av->stream_id >= stcb->asoc.streamoutcnt) ||
1838 (stcb->asoc.ss_functions.sctp_ss_get_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id],
1839 &av->stream_value) < 0)) {
1840 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1843 *optsize = sizeof(struct sctp_stream_value);
1845 SCTP_TCB_UNLOCK(stcb);
1848 * Can't get stream value without
1851 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1856 case SCTP_GET_ADDR_LEN:
1858 struct sctp_assoc_value *av;
1860 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
1863 if (av->assoc_value == AF_INET) {
1864 av->assoc_value = sizeof(struct sockaddr_in);
1869 if (av->assoc_value == AF_INET6) {
1870 av->assoc_value = sizeof(struct sockaddr_in6);
1875 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
1877 *optsize = sizeof(struct sctp_assoc_value);
1881 case SCTP_GET_ASSOC_NUMBER:
1883 uint32_t *value, cnt;
1885 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
1886 SCTP_INP_RLOCK(inp);
1887 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1888 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
1889 /* Can't do this for a 1-1 socket */
1891 SCTP_INP_RUNLOCK(inp);
1895 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
1898 SCTP_INP_RUNLOCK(inp);
1900 *optsize = sizeof(uint32_t);
1903 case SCTP_GET_ASSOC_ID_LIST:
1905 struct sctp_assoc_ids *ids;
1909 SCTP_CHECK_AND_CAST(ids, optval, struct sctp_assoc_ids, *optsize);
1910 SCTP_INP_RLOCK(inp);
1911 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1912 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
1913 /* Can't do this for a 1-1 socket */
1915 SCTP_INP_RUNLOCK(inp);
1919 limit = (*optsize - sizeof(uint32_t)) / sizeof(sctp_assoc_t);
1920 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
1922 ids->gaids_assoc_id[at++] = sctp_get_associd(stcb);
1925 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
1930 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
1934 SCTP_INP_RUNLOCK(inp);
1936 ids->gaids_number_of_ids = at;
1937 *optsize = ((at * sizeof(sctp_assoc_t)) + sizeof(uint32_t));
1943 struct sctp_assoc_value *av;
1945 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
1946 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
1949 av->assoc_value = stcb->asoc.context;
1950 SCTP_TCB_UNLOCK(stcb);
1952 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1953 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
1954 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
1955 SCTP_INP_RLOCK(inp);
1956 av->assoc_value = inp->sctp_context;
1957 SCTP_INP_RUNLOCK(inp);
1959 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1964 *optsize = sizeof(struct sctp_assoc_value);
1970 uint32_t *default_vrfid;
1972 SCTP_CHECK_AND_CAST(default_vrfid, optval, uint32_t, *optsize);
1973 *default_vrfid = inp->def_vrf_id;
1974 *optsize = sizeof(uint32_t);
1977 case SCTP_GET_ASOC_VRF:
1979 struct sctp_assoc_value *id;
1981 SCTP_CHECK_AND_CAST(id, optval, struct sctp_assoc_value, *optsize);
1982 SCTP_FIND_STCB(inp, stcb, id->assoc_id);
1985 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
1987 id->assoc_value = stcb->asoc.vrf_id;
1988 *optsize = sizeof(struct sctp_assoc_value);
1992 case SCTP_GET_VRF_IDS:
1994 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
1998 case SCTP_GET_NONCE_VALUES:
2000 struct sctp_get_nonce_values *gnv;
2002 SCTP_CHECK_AND_CAST(gnv, optval, struct sctp_get_nonce_values, *optsize);
2003 SCTP_FIND_STCB(inp, stcb, gnv->gn_assoc_id);
2006 gnv->gn_peers_tag = stcb->asoc.peer_vtag;
2007 gnv->gn_local_tag = stcb->asoc.my_vtag;
2008 SCTP_TCB_UNLOCK(stcb);
2009 *optsize = sizeof(struct sctp_get_nonce_values);
2011 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
2016 case SCTP_DELAYED_SACK:
2018 struct sctp_sack_info *sack;
2020 SCTP_CHECK_AND_CAST(sack, optval, struct sctp_sack_info, *optsize);
2021 SCTP_FIND_STCB(inp, stcb, sack->sack_assoc_id);
2023 sack->sack_delay = stcb->asoc.delayed_ack;
2024 sack->sack_freq = stcb->asoc.sack_freq;
2025 SCTP_TCB_UNLOCK(stcb);
2027 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2028 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2029 (sack->sack_assoc_id == SCTP_FUTURE_ASSOC)) {
2030 SCTP_INP_RLOCK(inp);
2031 sack->sack_delay = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
2032 sack->sack_freq = inp->sctp_ep.sctp_sack_freq;
2033 SCTP_INP_RUNLOCK(inp);
2035 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2040 *optsize = sizeof(struct sctp_sack_info);
2044 case SCTP_GET_SNDBUF_USE:
2046 struct sctp_sockstat *ss;
2048 SCTP_CHECK_AND_CAST(ss, optval, struct sctp_sockstat, *optsize);
2049 SCTP_FIND_STCB(inp, stcb, ss->ss_assoc_id);
2052 ss->ss_total_sndbuf = stcb->asoc.total_output_queue_size;
2053 ss->ss_total_recv_buf = (stcb->asoc.size_on_reasm_queue +
2054 stcb->asoc.size_on_all_streams);
2055 SCTP_TCB_UNLOCK(stcb);
2056 *optsize = sizeof(struct sctp_sockstat);
2058 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
2063 case SCTP_MAX_BURST:
2065 struct sctp_assoc_value *av;
2067 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2068 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2071 av->assoc_value = stcb->asoc.max_burst;
2072 SCTP_TCB_UNLOCK(stcb);
2074 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2075 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2076 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
2077 SCTP_INP_RLOCK(inp);
2078 av->assoc_value = inp->sctp_ep.max_burst;
2079 SCTP_INP_RUNLOCK(inp);
2081 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2086 *optsize = sizeof(struct sctp_assoc_value);
2092 struct sctp_assoc_value *av;
2095 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2096 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2099 av->assoc_value = sctp_get_frag_point(stcb, &stcb->asoc);
2100 SCTP_TCB_UNLOCK(stcb);
2102 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2103 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2104 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
2105 SCTP_INP_RLOCK(inp);
2106 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
2107 ovh = SCTP_MED_OVERHEAD;
2109 ovh = SCTP_MED_V4_OVERHEAD;
2111 if (inp->sctp_frag_point >= SCTP_DEFAULT_MAXSEGMENT)
2112 av->assoc_value = 0;
2114 av->assoc_value = inp->sctp_frag_point - ovh;
2115 SCTP_INP_RUNLOCK(inp);
2117 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2122 *optsize = sizeof(struct sctp_assoc_value);
2126 case SCTP_GET_STAT_LOG:
2127 error = sctp_fill_stat_log(optval, optsize);
2131 struct sctp_event_subscribe *events;
2133 SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, *optsize);
2134 memset(events, 0, sizeof(struct sctp_event_subscribe));
2135 SCTP_INP_RLOCK(inp);
2136 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT))
2137 events->sctp_data_io_event = 1;
2139 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT))
2140 events->sctp_association_event = 1;
2142 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVPADDREVNT))
2143 events->sctp_address_event = 1;
2145 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT))
2146 events->sctp_send_failure_event = 1;
2148 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVPEERERR))
2149 events->sctp_peer_error_event = 1;
2151 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT))
2152 events->sctp_shutdown_event = 1;
2154 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT))
2155 events->sctp_partial_delivery_event = 1;
2157 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT))
2158 events->sctp_adaptation_layer_event = 1;
2160 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT))
2161 events->sctp_authentication_event = 1;
2163 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT))
2164 events->sctp_sender_dry_event = 1;
2166 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT))
2167 events->sctp_stream_reset_event = 1;
2168 SCTP_INP_RUNLOCK(inp);
2169 *optsize = sizeof(struct sctp_event_subscribe);
2172 case SCTP_ADAPTATION_LAYER:
2176 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2178 SCTP_INP_RLOCK(inp);
2179 *value = inp->sctp_ep.adaptation_layer_indicator;
2180 SCTP_INP_RUNLOCK(inp);
2181 *optsize = sizeof(uint32_t);
2184 case SCTP_SET_INITIAL_DBG_SEQ:
2188 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2189 SCTP_INP_RLOCK(inp);
2190 *value = inp->sctp_ep.initial_sequence_debug;
2191 SCTP_INP_RUNLOCK(inp);
2192 *optsize = sizeof(uint32_t);
2195 case SCTP_GET_LOCAL_ADDR_SIZE:
2199 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2200 SCTP_INP_RLOCK(inp);
2201 *value = sctp_count_max_addresses(inp);
2202 SCTP_INP_RUNLOCK(inp);
2203 *optsize = sizeof(uint32_t);
2206 case SCTP_GET_REMOTE_ADDR_SIZE:
2210 struct sctp_nets *net;
2212 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2213 /* FIXME MT: change to sctp_assoc_value? */
2214 SCTP_FIND_STCB(inp, stcb, (sctp_assoc_t) * value);
2218 /* Count the sizes */
2219 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
2220 switch (net->ro._l_addr.sa.sa_family) {
2224 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
2225 size += sizeof(struct sockaddr_in6);
2227 size += sizeof(struct sockaddr_in);
2230 size += sizeof(struct sockaddr_in);
2236 size += sizeof(struct sockaddr_in6);
2243 SCTP_TCB_UNLOCK(stcb);
2244 *value = (uint32_t) size;
2245 *optsize = sizeof(uint32_t);
2247 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
2252 case SCTP_GET_PEER_ADDRESSES:
2254 * Get the address information, an array is passed in to
2255 * fill up we pack it.
2259 struct sockaddr_storage *sas;
2260 struct sctp_nets *net;
2261 struct sctp_getaddresses *saddr;
2263 SCTP_CHECK_AND_CAST(saddr, optval, struct sctp_getaddresses, *optsize);
2264 SCTP_FIND_STCB(inp, stcb, saddr->sget_assoc_id);
2267 left = (*optsize) - sizeof(struct sctp_getaddresses);
2268 *optsize = sizeof(struct sctp_getaddresses);
2269 sas = (struct sockaddr_storage *)&saddr->addr[0];
2271 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
2272 switch (net->ro._l_addr.sa.sa_family) {
2276 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
2277 cpsz = sizeof(struct sockaddr_in6);
2279 cpsz = sizeof(struct sockaddr_in);
2282 cpsz = sizeof(struct sockaddr_in);
2288 cpsz = sizeof(struct sockaddr_in6);
2299 /* not enough room. */
2302 #if defined(INET) && defined(INET6)
2303 if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) &&
2304 (net->ro._l_addr.sa.sa_family == AF_INET)) {
2305 /* Must map the address */
2306 in6_sin_2_v4mapsin6(&net->ro._l_addr.sin,
2307 (struct sockaddr_in6 *)sas);
2309 memcpy(sas, &net->ro._l_addr, cpsz);
2312 memcpy(sas, &net->ro._l_addr, cpsz);
2314 ((struct sockaddr_in *)sas)->sin_port = stcb->rport;
2316 sas = (struct sockaddr_storage *)((caddr_t)sas + cpsz);
2320 SCTP_TCB_UNLOCK(stcb);
2322 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
2327 case SCTP_GET_LOCAL_ADDRESSES:
2329 size_t limit, actual;
2330 struct sockaddr_storage *sas;
2331 struct sctp_getaddresses *saddr;
2333 SCTP_CHECK_AND_CAST(saddr, optval, struct sctp_getaddresses, *optsize);
2334 SCTP_FIND_STCB(inp, stcb, saddr->sget_assoc_id);
2336 sas = (struct sockaddr_storage *)&saddr->addr[0];
2337 limit = *optsize - sizeof(sctp_assoc_t);
2338 actual = sctp_fill_up_addresses(inp, stcb, limit, sas);
2340 SCTP_TCB_UNLOCK(stcb);
2342 *optsize = sizeof(struct sockaddr_storage) + actual;
2345 case SCTP_PEER_ADDR_PARAMS:
2347 struct sctp_paddrparams *paddrp;
2348 struct sctp_nets *net;
2349 struct sockaddr *addr;
2351 #if defined(INET) && defined(INET6)
2352 struct sockaddr_in sin_store;
2356 SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, *optsize);
2357 SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
2359 #if defined(INET) && defined(INET6)
2360 if (paddrp->spp_address.ss_family == AF_INET6) {
2361 struct sockaddr_in6 *sin6;
2363 sin6 = (struct sockaddr_in6 *)&paddrp->spp_address;
2364 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
2365 in6_sin6_2_sin(&sin_store, sin6);
2366 addr = (struct sockaddr *)&sin_store;
2368 addr = (struct sockaddr *)&paddrp->spp_address;
2371 addr = (struct sockaddr *)&paddrp->spp_address;
2374 addr = (struct sockaddr *)&paddrp->spp_address;
2377 net = sctp_findnet(stcb, addr);
2380 * We increment here since
2381 * sctp_findassociation_ep_addr() wil do a
2382 * decrement if it finds the stcb as long as
2383 * the locked tcb (last argument) is NOT a
2387 SCTP_INP_INCR_REF(inp);
2388 stcb = sctp_findassociation_ep_addr(&inp, addr, &net, NULL, NULL);
2390 SCTP_INP_DECR_REF(inp);
2393 if ((stcb != NULL) && (net == NULL)) {
2395 if (addr->sa_family == AF_INET) {
2396 struct sockaddr_in *sin;
2398 sin = (struct sockaddr_in *)addr;
2399 if (sin->sin_addr.s_addr != INADDR_ANY) {
2401 SCTP_TCB_UNLOCK(stcb);
2402 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2408 if (addr->sa_family == AF_INET6) {
2409 struct sockaddr_in6 *sin6;
2411 sin6 = (struct sockaddr_in6 *)addr;
2412 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
2414 SCTP_TCB_UNLOCK(stcb);
2415 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2421 error = EAFNOSUPPORT;
2422 SCTP_TCB_UNLOCK(stcb);
2423 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2428 /* Applies to the specific association */
2429 paddrp->spp_flags = 0;
2431 paddrp->spp_hbinterval = net->heart_beat_delay;
2432 paddrp->spp_pathmaxrxt = net->failure_threshold;
2433 paddrp->spp_pathmtu = net->mtu;
2434 switch (net->ro._l_addr.sa.sa_family) {
2437 paddrp->spp_pathmtu -= SCTP_MIN_V4_OVERHEAD;
2442 paddrp->spp_pathmtu -= SCTP_MIN_V4_OVERHEAD;
2448 /* get flags for HB */
2449 if (net->dest_state & SCTP_ADDR_NOHB) {
2450 paddrp->spp_flags |= SPP_HB_DISABLE;
2452 paddrp->spp_flags |= SPP_HB_ENABLE;
2454 /* get flags for PMTU */
2455 if (net->dest_state & SCTP_ADDR_NO_PMTUD) {
2456 paddrp->spp_flags |= SPP_PMTUD_DISABLE;
2458 paddrp->spp_flags |= SPP_PMTUD_ENABLE;
2460 if (net->dscp & 0x01) {
2461 paddrp->spp_dscp = net->dscp & 0xfc;
2462 paddrp->spp_flags |= SPP_DSCP;
2465 if ((net->ro._l_addr.sa.sa_family == AF_INET6) &&
2466 (net->flowlabel & 0x80000000)) {
2467 paddrp->spp_ipv6_flowlabel = net->flowlabel & 0x000fffff;
2468 paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
2473 * No destination so return default
2476 paddrp->spp_pathmaxrxt = stcb->asoc.def_net_failure;
2477 paddrp->spp_pathmtu = 0;
2478 if (stcb->asoc.default_dscp & 0x01) {
2479 paddrp->spp_dscp = stcb->asoc.default_dscp & 0xfc;
2480 paddrp->spp_flags |= SPP_DSCP;
2483 if (stcb->asoc.default_flowlabel & 0x80000000) {
2484 paddrp->spp_ipv6_flowlabel = stcb->asoc.default_flowlabel & 0x000fffff;
2485 paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
2488 /* default settings should be these */
2489 if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
2490 paddrp->spp_flags |= SPP_HB_DISABLE;
2492 paddrp->spp_flags |= SPP_HB_ENABLE;
2494 if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD)) {
2495 paddrp->spp_flags |= SPP_PMTUD_DISABLE;
2497 paddrp->spp_flags |= SPP_PMTUD_ENABLE;
2499 paddrp->spp_hbinterval = stcb->asoc.heart_beat_delay;
2501 paddrp->spp_assoc_id = sctp_get_associd(stcb);
2502 SCTP_TCB_UNLOCK(stcb);
2504 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2505 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2506 (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC)) {
2507 /* Use endpoint defaults */
2508 SCTP_INP_RLOCK(inp);
2509 paddrp->spp_pathmaxrxt = inp->sctp_ep.def_net_failure;
2510 paddrp->spp_hbinterval = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]);
2511 paddrp->spp_assoc_id = SCTP_FUTURE_ASSOC;
2512 /* get inp's default */
2513 if (inp->sctp_ep.default_dscp & 0x01) {
2514 paddrp->spp_dscp = inp->sctp_ep.default_dscp & 0xfc;
2515 paddrp->spp_flags |= SPP_DSCP;
2518 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
2519 (inp->sctp_ep.default_flowlabel & 0x80000000)) {
2520 paddrp->spp_ipv6_flowlabel = inp->sctp_ep.default_flowlabel & 0x000fffff;
2521 paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
2524 /* can't return this */
2525 paddrp->spp_pathmtu = 0;
2527 if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
2528 paddrp->spp_flags |= SPP_HB_ENABLE;
2530 paddrp->spp_flags |= SPP_HB_DISABLE;
2532 if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD)) {
2533 paddrp->spp_flags |= SPP_PMTUD_ENABLE;
2535 paddrp->spp_flags |= SPP_PMTUD_DISABLE;
2537 SCTP_INP_RUNLOCK(inp);
2539 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2544 *optsize = sizeof(struct sctp_paddrparams);
2548 case SCTP_GET_PEER_ADDR_INFO:
2550 struct sctp_paddrinfo *paddri;
2551 struct sctp_nets *net;
2552 struct sockaddr *addr;
2554 #if defined(INET) && defined(INET6)
2555 struct sockaddr_in sin_store;
2559 SCTP_CHECK_AND_CAST(paddri, optval, struct sctp_paddrinfo, *optsize);
2560 SCTP_FIND_STCB(inp, stcb, paddri->spinfo_assoc_id);
2562 #if defined(INET) && defined(INET6)
2563 if (paddri->spinfo_address.ss_family == AF_INET6) {
2564 struct sockaddr_in6 *sin6;
2566 sin6 = (struct sockaddr_in6 *)&paddri->spinfo_address;
2567 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
2568 in6_sin6_2_sin(&sin_store, sin6);
2569 addr = (struct sockaddr *)&sin_store;
2571 addr = (struct sockaddr *)&paddri->spinfo_address;
2574 addr = (struct sockaddr *)&paddri->spinfo_address;
2577 addr = (struct sockaddr *)&paddri->spinfo_address;
2580 net = sctp_findnet(stcb, addr);
2583 * We increment here since
2584 * sctp_findassociation_ep_addr() wil do a
2585 * decrement if it finds the stcb as long as
2586 * the locked tcb (last argument) is NOT a
2590 SCTP_INP_INCR_REF(inp);
2591 stcb = sctp_findassociation_ep_addr(&inp, addr, &net, NULL, NULL);
2593 SCTP_INP_DECR_REF(inp);
2597 if ((stcb != NULL) && (net != NULL)) {
2598 if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
2599 /* It's unconfirmed */
2600 paddri->spinfo_state = SCTP_UNCONFIRMED;
2601 } else if (net->dest_state & SCTP_ADDR_REACHABLE) {
2603 paddri->spinfo_state = SCTP_ACTIVE;
2606 paddri->spinfo_state = SCTP_INACTIVE;
2608 paddri->spinfo_cwnd = net->cwnd;
2609 paddri->spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT;
2610 paddri->spinfo_rto = net->RTO;
2611 paddri->spinfo_assoc_id = sctp_get_associd(stcb);
2612 paddri->spinfo_mtu = net->mtu;
2613 switch (addr->sa_family) {
2616 paddri->spinfo_mtu -= SCTP_MIN_V4_OVERHEAD;
2621 paddri->spinfo_mtu -= SCTP_MIN_OVERHEAD;
2627 SCTP_TCB_UNLOCK(stcb);
2628 *optsize = sizeof(struct sctp_paddrinfo);
2631 SCTP_TCB_UNLOCK(stcb);
2633 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
2638 case SCTP_PCB_STATUS:
2640 struct sctp_pcbinfo *spcb;
2642 SCTP_CHECK_AND_CAST(spcb, optval, struct sctp_pcbinfo, *optsize);
2643 sctp_fill_pcbinfo(spcb);
2644 *optsize = sizeof(struct sctp_pcbinfo);
2649 struct sctp_nets *net;
2650 struct sctp_status *sstat;
2652 SCTP_CHECK_AND_CAST(sstat, optval, struct sctp_status, *optsize);
2653 SCTP_FIND_STCB(inp, stcb, sstat->sstat_assoc_id);
2656 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2660 sstat->sstat_state = sctp_map_assoc_state(stcb->asoc.state);
2661 sstat->sstat_assoc_id = sctp_get_associd(stcb);
2662 sstat->sstat_rwnd = stcb->asoc.peers_rwnd;
2663 sstat->sstat_unackdata = stcb->asoc.sent_queue_cnt;
2665 * We can't include chunks that have been passed to
2666 * the socket layer. Only things in queue.
2668 sstat->sstat_penddata = (stcb->asoc.cnt_on_reasm_queue +
2669 stcb->asoc.cnt_on_all_streams);
2672 sstat->sstat_instrms = stcb->asoc.streamincnt;
2673 sstat->sstat_outstrms = stcb->asoc.streamoutcnt;
2674 sstat->sstat_fragmentation_point = sctp_get_frag_point(stcb, &stcb->asoc);
2675 memcpy(&sstat->sstat_primary.spinfo_address,
2676 &stcb->asoc.primary_destination->ro._l_addr,
2677 ((struct sockaddr *)(&stcb->asoc.primary_destination->ro._l_addr))->sa_len);
2678 net = stcb->asoc.primary_destination;
2679 ((struct sockaddr_in *)&sstat->sstat_primary.spinfo_address)->sin_port = stcb->rport;
2681 * Again the user can get info from sctp_constants.h
2682 * for what the state of the network is.
2684 if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
2685 /* It's unconfirmed */
2686 sstat->sstat_primary.spinfo_state = SCTP_UNCONFIRMED;
2687 } else if (net->dest_state & SCTP_ADDR_REACHABLE) {
2689 sstat->sstat_primary.spinfo_state = SCTP_ACTIVE;
2692 sstat->sstat_primary.spinfo_state = SCTP_INACTIVE;
2694 sstat->sstat_primary.spinfo_cwnd = net->cwnd;
2695 sstat->sstat_primary.spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT;
2696 sstat->sstat_primary.spinfo_rto = net->RTO;
2697 sstat->sstat_primary.spinfo_mtu = net->mtu;
2698 switch (stcb->asoc.primary_destination->ro._l_addr.sa.sa_family) {
2701 sstat->sstat_primary.spinfo_mtu -= SCTP_MIN_V4_OVERHEAD;
2706 sstat->sstat_primary.spinfo_mtu -= SCTP_MIN_OVERHEAD;
2712 sstat->sstat_primary.spinfo_assoc_id = sctp_get_associd(stcb);
2713 SCTP_TCB_UNLOCK(stcb);
2714 *optsize = sizeof(struct sctp_status);
2719 struct sctp_rtoinfo *srto;
2721 SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, *optsize);
2722 SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
2725 srto->srto_initial = stcb->asoc.initial_rto;
2726 srto->srto_max = stcb->asoc.maxrto;
2727 srto->srto_min = stcb->asoc.minrto;
2728 SCTP_TCB_UNLOCK(stcb);
2730 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2731 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2732 (srto->srto_assoc_id == SCTP_FUTURE_ASSOC)) {
2733 SCTP_INP_RLOCK(inp);
2734 srto->srto_initial = inp->sctp_ep.initial_rto;
2735 srto->srto_max = inp->sctp_ep.sctp_maxrto;
2736 srto->srto_min = inp->sctp_ep.sctp_minrto;
2737 SCTP_INP_RUNLOCK(inp);
2739 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2744 *optsize = sizeof(struct sctp_rtoinfo);
2750 struct sctp_timeouts *stimo;
2752 SCTP_CHECK_AND_CAST(stimo, optval, struct sctp_timeouts, *optsize);
2753 SCTP_FIND_STCB(inp, stcb, stimo->stimo_assoc_id);
2756 stimo->stimo_init = stcb->asoc.timoinit;
2757 stimo->stimo_data = stcb->asoc.timodata;
2758 stimo->stimo_sack = stcb->asoc.timosack;
2759 stimo->stimo_shutdown = stcb->asoc.timoshutdown;
2760 stimo->stimo_heartbeat = stcb->asoc.timoheartbeat;
2761 stimo->stimo_cookie = stcb->asoc.timocookie;
2762 stimo->stimo_shutdownack = stcb->asoc.timoshutdownack;
2763 SCTP_TCB_UNLOCK(stcb);
2764 *optsize = sizeof(struct sctp_timeouts);
2766 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2771 case SCTP_ASSOCINFO:
2773 struct sctp_assocparams *sasoc;
2775 SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, *optsize);
2776 SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
2779 sasoc->sasoc_cookie_life = TICKS_TO_MSEC(stcb->asoc.cookie_life);
2780 sasoc->sasoc_asocmaxrxt = stcb->asoc.max_send_times;
2781 sasoc->sasoc_number_peer_destinations = stcb->asoc.numnets;
2782 sasoc->sasoc_peer_rwnd = stcb->asoc.peers_rwnd;
2783 sasoc->sasoc_local_rwnd = stcb->asoc.my_rwnd;
2784 SCTP_TCB_UNLOCK(stcb);
2786 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2787 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2788 (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC)) {
2789 SCTP_INP_RLOCK(inp);
2790 sasoc->sasoc_cookie_life = TICKS_TO_MSEC(inp->sctp_ep.def_cookie_life);
2791 sasoc->sasoc_asocmaxrxt = inp->sctp_ep.max_send_times;
2792 sasoc->sasoc_number_peer_destinations = 0;
2793 sasoc->sasoc_peer_rwnd = 0;
2794 sasoc->sasoc_local_rwnd = sbspace(&inp->sctp_socket->so_rcv);
2795 SCTP_INP_RUNLOCK(inp);
2797 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2802 *optsize = sizeof(struct sctp_assocparams);
2806 case SCTP_DEFAULT_SEND_PARAM:
2808 struct sctp_sndrcvinfo *s_info;
2810 SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, *optsize);
2811 SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
2814 memcpy(s_info, &stcb->asoc.def_send, sizeof(stcb->asoc.def_send));
2815 SCTP_TCB_UNLOCK(stcb);
2817 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2818 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2819 (s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC)) {
2820 SCTP_INP_RLOCK(inp);
2821 memcpy(s_info, &inp->def_send, sizeof(inp->def_send));
2822 SCTP_INP_RUNLOCK(inp);
2824 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2829 *optsize = sizeof(struct sctp_sndrcvinfo);
2835 struct sctp_initmsg *sinit;
2837 SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, *optsize);
2838 SCTP_INP_RLOCK(inp);
2839 sinit->sinit_num_ostreams = inp->sctp_ep.pre_open_stream_count;
2840 sinit->sinit_max_instreams = inp->sctp_ep.max_open_streams_intome;
2841 sinit->sinit_max_attempts = inp->sctp_ep.max_init_times;
2842 sinit->sinit_max_init_timeo = inp->sctp_ep.initial_init_rto_max;
2843 SCTP_INP_RUNLOCK(inp);
2844 *optsize = sizeof(struct sctp_initmsg);
2847 case SCTP_PRIMARY_ADDR:
2848 /* we allow a "get" operation on this */
2850 struct sctp_setprim *ssp;
2852 SCTP_CHECK_AND_CAST(ssp, optval, struct sctp_setprim, *optsize);
2853 SCTP_FIND_STCB(inp, stcb, ssp->ssp_assoc_id);
2856 union sctp_sockstore *addr;
2858 addr = &stcb->asoc.primary_destination->ro._l_addr;
2859 switch (addr->sa.sa_family) {
2863 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
2864 in6_sin_2_v4mapsin6(&addr->sin,
2865 (struct sockaddr_in6 *)&ssp->ssp_addr);
2867 memcpy(&ssp->ssp_addr, &addr->sin, sizeof(struct sockaddr_in));
2870 memcpy(&ssp->ssp_addr, &addr->sin, sizeof(struct sockaddr_in));
2876 memcpy(&ssp->ssp_addr, &addr->sin6, sizeof(struct sockaddr_in6));
2882 SCTP_TCB_UNLOCK(stcb);
2883 *optsize = sizeof(struct sctp_setprim);
2885 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2890 case SCTP_HMAC_IDENT:
2892 struct sctp_hmacalgo *shmac;
2893 sctp_hmaclist_t *hmaclist;
2897 SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, *optsize);
2899 SCTP_INP_RLOCK(inp);
2900 hmaclist = inp->sctp_ep.local_hmacs;
2901 if (hmaclist == NULL) {
2902 /* no HMACs to return */
2903 *optsize = sizeof(*shmac);
2904 SCTP_INP_RUNLOCK(inp);
2907 /* is there room for all of the hmac ids? */
2908 size = sizeof(*shmac) + (hmaclist->num_algo *
2909 sizeof(shmac->shmac_idents[0]));
2910 if ((size_t)(*optsize) < size) {
2911 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2913 SCTP_INP_RUNLOCK(inp);
2916 /* copy in the list */
2917 shmac->shmac_number_of_idents = hmaclist->num_algo;
2918 for (i = 0; i < hmaclist->num_algo; i++) {
2919 shmac->shmac_idents[i] = hmaclist->hmac[i];
2921 SCTP_INP_RUNLOCK(inp);
2925 case SCTP_AUTH_ACTIVE_KEY:
2927 struct sctp_authkeyid *scact;
2929 SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, *optsize);
2930 SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id);
2933 /* get the active key on the assoc */
2934 scact->scact_keynumber = stcb->asoc.authinfo.active_keyid;
2935 SCTP_TCB_UNLOCK(stcb);
2937 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2938 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2939 (scact->scact_assoc_id == SCTP_FUTURE_ASSOC)) {
2940 /* get the endpoint active key */
2941 SCTP_INP_RLOCK(inp);
2942 scact->scact_keynumber = inp->sctp_ep.default_keyid;
2943 SCTP_INP_RUNLOCK(inp);
2945 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2950 *optsize = sizeof(struct sctp_authkeyid);
2954 case SCTP_LOCAL_AUTH_CHUNKS:
2956 struct sctp_authchunks *sac;
2957 sctp_auth_chklist_t *chklist = NULL;
2960 SCTP_CHECK_AND_CAST(sac, optval, struct sctp_authchunks, *optsize);
2961 SCTP_FIND_STCB(inp, stcb, sac->gauth_assoc_id);
2964 /* get off the assoc */
2965 chklist = stcb->asoc.local_auth_chunks;
2966 /* is there enough space? */
2967 size = sctp_auth_get_chklist_size(chklist);
2968 if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
2970 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2972 /* copy in the chunks */
2973 (void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
2974 sac->gauth_number_of_chunks = (uint32_t) size;
2975 *optsize = sizeof(struct sctp_authchunks) + size;
2977 SCTP_TCB_UNLOCK(stcb);
2979 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2980 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2981 (sac->gauth_assoc_id == SCTP_FUTURE_ASSOC)) {
2982 /* get off the endpoint */
2983 SCTP_INP_RLOCK(inp);
2984 chklist = inp->sctp_ep.local_auth_chunks;
2985 /* is there enough space? */
2986 size = sctp_auth_get_chklist_size(chklist);
2987 if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
2989 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2991 /* copy in the chunks */
2992 (void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
2993 sac->gauth_number_of_chunks = (uint32_t) size;
2994 *optsize = sizeof(struct sctp_authchunks) + size;
2996 SCTP_INP_RUNLOCK(inp);
2998 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3004 case SCTP_PEER_AUTH_CHUNKS:
3006 struct sctp_authchunks *sac;
3007 sctp_auth_chklist_t *chklist = NULL;
3010 SCTP_CHECK_AND_CAST(sac, optval, struct sctp_authchunks, *optsize);
3011 SCTP_FIND_STCB(inp, stcb, sac->gauth_assoc_id);
3014 /* get off the assoc */
3015 chklist = stcb->asoc.peer_auth_chunks;
3016 /* is there enough space? */
3017 size = sctp_auth_get_chklist_size(chklist);
3018 if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
3020 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3022 /* copy in the chunks */
3023 (void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
3024 sac->gauth_number_of_chunks = (uint32_t) size;
3025 *optsize = sizeof(struct sctp_authchunks) + size;
3027 SCTP_TCB_UNLOCK(stcb);
3029 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
3036 struct sctp_event *event;
3037 uint32_t event_type;
3039 SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, *optsize);
3040 SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
3042 switch (event->se_type) {
3043 case SCTP_ASSOC_CHANGE:
3044 event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
3046 case SCTP_PEER_ADDR_CHANGE:
3047 event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
3049 case SCTP_REMOTE_ERROR:
3050 event_type = SCTP_PCB_FLAGS_RECVPEERERR;
3052 case SCTP_SEND_FAILED:
3053 event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
3055 case SCTP_SHUTDOWN_EVENT:
3056 event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
3058 case SCTP_ADAPTATION_INDICATION:
3059 event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
3061 case SCTP_PARTIAL_DELIVERY_EVENT:
3062 event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
3064 case SCTP_AUTHENTICATION_EVENT:
3065 event_type = SCTP_PCB_FLAGS_AUTHEVNT;
3067 case SCTP_STREAM_RESET_EVENT:
3068 event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
3070 case SCTP_SENDER_DRY_EVENT:
3071 event_type = SCTP_PCB_FLAGS_DRYEVNT;
3073 case SCTP_NOTIFICATIONS_STOPPED_EVENT:
3075 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
3078 case SCTP_ASSOC_RESET_EVENT:
3079 event_type = SCTP_PCB_FLAGS_ASSOC_RESETEVNT;
3081 case SCTP_STREAM_CHANGE_EVENT:
3082 event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT;
3084 case SCTP_SEND_FAILED_EVENT:
3085 event_type = SCTP_PCB_FLAGS_RECVNSENDFAILEVNT;
3089 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3093 if (event_type > 0) {
3095 event->se_on = sctp_stcb_is_feature_on(inp, stcb, event_type);
3096 SCTP_TCB_UNLOCK(stcb);
3098 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3099 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3100 (event->se_assoc_id == SCTP_FUTURE_ASSOC)) {
3101 SCTP_INP_RLOCK(inp);
3102 event->se_on = sctp_is_feature_on(inp, event_type);
3103 SCTP_INP_RUNLOCK(inp);
3105 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3111 *optsize = sizeof(struct sctp_event);
3115 case SCTP_RECVRCVINFO:
3119 if (*optsize < sizeof(int)) {
3120 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3123 SCTP_INP_RLOCK(inp);
3124 onoff = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
3125 SCTP_INP_RUNLOCK(inp);
3128 /* return the option value */
3129 *(int *)optval = onoff;
3130 *optsize = sizeof(int);
3134 case SCTP_RECVNXTINFO:
3138 if (*optsize < sizeof(int)) {
3139 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3142 SCTP_INP_RLOCK(inp);
3143 onoff = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
3144 SCTP_INP_RUNLOCK(inp);
3147 /* return the option value */
3148 *(int *)optval = onoff;
3149 *optsize = sizeof(int);
3153 case SCTP_DEFAULT_SNDINFO:
3155 struct sctp_sndinfo *info;
3157 SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, *optsize);
3158 SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
3161 info->snd_sid = stcb->asoc.def_send.sinfo_stream;
3162 info->snd_flags = stcb->asoc.def_send.sinfo_flags;
3163 info->snd_flags &= 0xfff0;
3164 info->snd_ppid = stcb->asoc.def_send.sinfo_ppid;
3165 info->snd_context = stcb->asoc.def_send.sinfo_context;
3166 SCTP_TCB_UNLOCK(stcb);
3168 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3169 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3170 (info->snd_assoc_id == SCTP_FUTURE_ASSOC)) {
3171 SCTP_INP_RLOCK(inp);
3172 info->snd_sid = inp->def_send.sinfo_stream;
3173 info->snd_flags = inp->def_send.sinfo_flags;
3174 info->snd_flags &= 0xfff0;
3175 info->snd_ppid = inp->def_send.sinfo_ppid;
3176 info->snd_context = inp->def_send.sinfo_context;
3177 SCTP_INP_RUNLOCK(inp);
3179 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3184 *optsize = sizeof(struct sctp_sndinfo);
3188 case SCTP_DEFAULT_PRINFO:
3190 struct sctp_default_prinfo *info;
3192 SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, *optsize);
3193 SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
3196 info->pr_policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
3197 info->pr_value = stcb->asoc.def_send.sinfo_timetolive;
3198 SCTP_TCB_UNLOCK(stcb);
3200 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3201 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3202 (info->pr_assoc_id == SCTP_FUTURE_ASSOC)) {
3203 SCTP_INP_RLOCK(inp);
3204 info->pr_policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
3205 info->pr_value = inp->def_send.sinfo_timetolive;
3206 SCTP_INP_RUNLOCK(inp);
3208 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3213 *optsize = sizeof(struct sctp_default_prinfo);
3217 case SCTP_PEER_ADDR_THLDS:
3219 struct sctp_paddrthlds *thlds;
3220 struct sctp_nets *net;
3221 struct sockaddr *addr;
3223 #if defined(INET) && defined(INET6)
3224 struct sockaddr_in sin_store;
3228 SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, *optsize);
3229 SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
3231 #if defined(INET) && defined(INET6)
3232 if (thlds->spt_address.ss_family == AF_INET6) {
3233 struct sockaddr_in6 *sin6;
3235 sin6 = (struct sockaddr_in6 *)&thlds->spt_address;
3236 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
3237 in6_sin6_2_sin(&sin_store, sin6);
3238 addr = (struct sockaddr *)&sin_store;
3240 addr = (struct sockaddr *)&thlds->spt_address;
3243 addr = (struct sockaddr *)&thlds->spt_address;
3246 addr = (struct sockaddr *)&thlds->spt_address;
3249 net = sctp_findnet(stcb, addr);
3252 * We increment here since
3253 * sctp_findassociation_ep_addr() wil do a
3254 * decrement if it finds the stcb as long as
3255 * the locked tcb (last argument) is NOT a
3259 SCTP_INP_INCR_REF(inp);
3260 stcb = sctp_findassociation_ep_addr(&inp, addr, &net, NULL, NULL);
3262 SCTP_INP_DECR_REF(inp);
3265 if ((stcb != NULL) && (net == NULL)) {
3267 if (addr->sa_family == AF_INET) {
3268 struct sockaddr_in *sin;
3270 sin = (struct sockaddr_in *)addr;
3271 if (sin->sin_addr.s_addr != INADDR_ANY) {
3273 SCTP_TCB_UNLOCK(stcb);
3274 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3280 if (addr->sa_family == AF_INET6) {
3281 struct sockaddr_in6 *sin6;
3283 sin6 = (struct sockaddr_in6 *)addr;
3284 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
3286 SCTP_TCB_UNLOCK(stcb);
3287 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3293 error = EAFNOSUPPORT;
3294 SCTP_TCB_UNLOCK(stcb);
3295 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3301 thlds->spt_pathmaxrxt = net->failure_threshold;
3302 thlds->spt_pathpfthld = net->pf_threshold;
3304 thlds->spt_pathmaxrxt = stcb->asoc.def_net_failure;
3305 thlds->spt_pathpfthld = stcb->asoc.def_net_pf_threshold;
3307 thlds->spt_assoc_id = sctp_get_associd(stcb);
3308 SCTP_TCB_UNLOCK(stcb);
3310 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3311 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3312 (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC)) {
3313 /* Use endpoint defaults */
3314 SCTP_INP_RLOCK(inp);
3315 thlds->spt_pathmaxrxt = inp->sctp_ep.def_net_failure;
3316 thlds->spt_pathpfthld = inp->sctp_ep.def_net_pf_threshold;
3317 SCTP_INP_RUNLOCK(inp);
3319 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3324 *optsize = sizeof(struct sctp_paddrthlds);
3328 case SCTP_REMOTE_UDP_ENCAPS_PORT:
3330 struct sctp_udpencaps *encaps;
3331 struct sctp_nets *net;
3332 struct sockaddr *addr;
3334 #if defined(INET) && defined(INET6)
3335 struct sockaddr_in sin_store;
3339 SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, *optsize);
3340 SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
3342 #if defined(INET) && defined(INET6)
3343 if (encaps->sue_address.ss_family == AF_INET6) {
3344 struct sockaddr_in6 *sin6;
3346 sin6 = (struct sockaddr_in6 *)&encaps->sue_address;
3347 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
3348 in6_sin6_2_sin(&sin_store, sin6);
3349 addr = (struct sockaddr *)&sin_store;
3351 addr = (struct sockaddr *)&encaps->sue_address;
3354 addr = (struct sockaddr *)&encaps->sue_address;
3357 addr = (struct sockaddr *)&encaps->sue_address;
3360 net = sctp_findnet(stcb, addr);
3363 * We increment here since
3364 * sctp_findassociation_ep_addr() wil do a
3365 * decrement if it finds the stcb as long as
3366 * the locked tcb (last argument) is NOT a
3370 SCTP_INP_INCR_REF(inp);
3371 stcb = sctp_findassociation_ep_addr(&inp, addr, &net, NULL, NULL);
3373 SCTP_INP_DECR_REF(inp);
3376 if ((stcb != NULL) && (net == NULL)) {
3378 if (addr->sa_family == AF_INET) {
3379 struct sockaddr_in *sin;
3381 sin = (struct sockaddr_in *)addr;
3382 if (sin->sin_addr.s_addr != INADDR_ANY) {
3384 SCTP_TCB_UNLOCK(stcb);
3385 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3391 if (addr->sa_family == AF_INET6) {
3392 struct sockaddr_in6 *sin6;
3394 sin6 = (struct sockaddr_in6 *)addr;
3395 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
3397 SCTP_TCB_UNLOCK(stcb);
3398 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3404 error = EAFNOSUPPORT;
3405 SCTP_TCB_UNLOCK(stcb);
3406 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3412 encaps->sue_port = net->port;
3414 encaps->sue_port = stcb->asoc.port;
3416 SCTP_TCB_UNLOCK(stcb);
3418 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3419 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3420 (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC)) {
3421 SCTP_INP_RLOCK(inp);
3422 encaps->sue_port = inp->sctp_ep.port;
3423 SCTP_INP_RUNLOCK(inp);
3425 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3430 *optsize = sizeof(struct sctp_udpencaps);
3434 case SCTP_ECN_SUPPORTED:
3436 struct sctp_assoc_value *av;
3438 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
3439 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3442 av->assoc_value = stcb->asoc.ecn_supported;
3443 SCTP_TCB_UNLOCK(stcb);
3445 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3446 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3447 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
3448 SCTP_INP_RLOCK(inp);
3449 av->assoc_value = inp->ecn_supported;
3450 SCTP_INP_RUNLOCK(inp);
3452 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3457 *optsize = sizeof(struct sctp_assoc_value);
3461 case SCTP_PR_SUPPORTED:
3463 struct sctp_assoc_value *av;
3465 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
3466 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3469 av->assoc_value = stcb->asoc.prsctp_supported;
3470 SCTP_TCB_UNLOCK(stcb);
3472 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3473 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3474 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
3475 SCTP_INP_RLOCK(inp);
3476 av->assoc_value = inp->prsctp_supported;
3477 SCTP_INP_RUNLOCK(inp);
3479 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3484 *optsize = sizeof(struct sctp_assoc_value);
3488 case SCTP_AUTH_SUPPORTED:
3490 struct sctp_assoc_value *av;
3492 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
3493 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3496 av->assoc_value = stcb->asoc.auth_supported;
3497 SCTP_TCB_UNLOCK(stcb);
3499 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3500 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3501 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
3502 SCTP_INP_RLOCK(inp);
3503 av->assoc_value = inp->auth_supported;
3504 SCTP_INP_RUNLOCK(inp);
3506 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3511 *optsize = sizeof(struct sctp_assoc_value);
3515 case SCTP_ASCONF_SUPPORTED:
3517 struct sctp_assoc_value *av;
3519 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
3520 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3523 av->assoc_value = stcb->asoc.asconf_supported;
3524 SCTP_TCB_UNLOCK(stcb);
3526 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3527 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3528 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
3529 SCTP_INP_RLOCK(inp);
3530 av->assoc_value = inp->asconf_supported;
3531 SCTP_INP_RUNLOCK(inp);
3533 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3538 *optsize = sizeof(struct sctp_assoc_value);
3542 case SCTP_RECONFIG_SUPPORTED:
3544 struct sctp_assoc_value *av;
3546 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
3547 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3550 av->assoc_value = stcb->asoc.reconfig_supported;
3551 SCTP_TCB_UNLOCK(stcb);
3553 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3554 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3555 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
3556 SCTP_INP_RLOCK(inp);
3557 av->assoc_value = inp->reconfig_supported;
3558 SCTP_INP_RUNLOCK(inp);
3560 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3565 *optsize = sizeof(struct sctp_assoc_value);
3569 case SCTP_NRSACK_SUPPORTED:
3571 struct sctp_assoc_value *av;
3573 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
3574 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3577 av->assoc_value = stcb->asoc.nrsack_supported;
3578 SCTP_TCB_UNLOCK(stcb);
3580 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3581 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3582 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
3583 SCTP_INP_RLOCK(inp);
3584 av->assoc_value = inp->nrsack_supported;
3585 SCTP_INP_RUNLOCK(inp);
3587 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3592 *optsize = sizeof(struct sctp_assoc_value);
3596 case SCTP_PKTDROP_SUPPORTED:
3598 struct sctp_assoc_value *av;
3600 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
3601 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3604 av->assoc_value = stcb->asoc.pktdrop_supported;
3605 SCTP_TCB_UNLOCK(stcb);
3607 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3608 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3609 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
3610 SCTP_INP_RLOCK(inp);
3611 av->assoc_value = inp->pktdrop_supported;
3612 SCTP_INP_RUNLOCK(inp);
3614 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3619 *optsize = sizeof(struct sctp_assoc_value);
3623 case SCTP_ENABLE_STREAM_RESET:
3625 struct sctp_assoc_value *av;
3627 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
3628 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3631 av->assoc_value = (uint32_t) stcb->asoc.local_strreset_support;
3632 SCTP_TCB_UNLOCK(stcb);
3634 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3635 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3636 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
3637 SCTP_INP_RLOCK(inp);
3638 av->assoc_value = (uint32_t) inp->local_strreset_support;
3639 SCTP_INP_RUNLOCK(inp);
3641 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3646 *optsize = sizeof(struct sctp_assoc_value);
3650 case SCTP_PR_STREAM_STATUS:
3652 struct sctp_prstatus *sprstat;
3656 SCTP_CHECK_AND_CAST(sprstat, optval, struct sctp_prstatus, *optsize);
3657 SCTP_FIND_STCB(inp, stcb, sprstat->sprstat_assoc_id);
3659 sid = sprstat->sprstat_sid;
3660 policy = sprstat->sprstat_policy;
3661 #if defined(SCTP_DETAILED_STR_STATS)
3662 if ((stcb != NULL) &&
3663 (sid < stcb->asoc.streamoutcnt) &&
3664 (policy != SCTP_PR_SCTP_NONE) &&
3665 ((policy <= SCTP_PR_SCTP_MAX) ||
3666 (policy == SCTP_PR_SCTP_ALL))) {
3667 if (policy == SCTP_PR_SCTP_ALL) {
3668 sprstat->sprstat_abandoned_unsent = stcb->asoc.strmout[sid].abandoned_unsent[0];
3669 sprstat->sprstat_abandoned_sent = stcb->asoc.strmout[sid].abandoned_sent[0];
3671 sprstat->sprstat_abandoned_unsent = stcb->asoc.strmout[sid].abandoned_unsent[policy];
3672 sprstat->sprstat_abandoned_sent = stcb->asoc.strmout[sid].abandoned_sent[policy];
3675 if ((stcb != NULL) &&
3676 (sid < stcb->asoc.streamoutcnt) &&
3677 (policy == SCTP_PR_SCTP_ALL)) {
3678 sprstat->sprstat_abandoned_unsent = stcb->asoc.strmout[sid].abandoned_unsent[0];
3679 sprstat->sprstat_abandoned_sent = stcb->asoc.strmout[sid].abandoned_sent[0];
3681 SCTP_TCB_UNLOCK(stcb);
3682 *optsize = sizeof(struct sctp_prstatus);
3684 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3689 case SCTP_PR_ASSOC_STATUS:
3691 struct sctp_prstatus *sprstat;
3694 SCTP_CHECK_AND_CAST(sprstat, optval, struct sctp_prstatus, *optsize);
3695 SCTP_FIND_STCB(inp, stcb, sprstat->sprstat_assoc_id);
3697 policy = sprstat->sprstat_policy;
3698 if ((stcb != NULL) &&
3699 (policy != SCTP_PR_SCTP_NONE) &&
3700 ((policy <= SCTP_PR_SCTP_MAX) ||
3701 (policy == SCTP_PR_SCTP_ALL))) {
3702 if (policy == SCTP_PR_SCTP_ALL) {
3703 sprstat->sprstat_abandoned_unsent = stcb->asoc.abandoned_unsent[0];
3704 sprstat->sprstat_abandoned_sent = stcb->asoc.abandoned_sent[0];
3706 sprstat->sprstat_abandoned_unsent = stcb->asoc.abandoned_unsent[policy];
3707 sprstat->sprstat_abandoned_sent = stcb->asoc.abandoned_sent[policy];
3709 SCTP_TCB_UNLOCK(stcb);
3710 *optsize = sizeof(struct sctp_prstatus);
3712 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3719 struct sctp_assoc_value *av;
3721 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
3722 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3725 av->assoc_value = stcb->asoc.max_cwnd;
3726 SCTP_TCB_UNLOCK(stcb);
3728 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3729 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3730 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
3731 SCTP_INP_RLOCK(inp);
3732 av->assoc_value = inp->max_cwnd;
3733 SCTP_INP_RUNLOCK(inp);
3735 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3740 *optsize = sizeof(struct sctp_assoc_value);
3745 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
3746 error = ENOPROTOOPT;
3748 } /* end switch (sopt->sopt_name) */
3756 sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
3761 struct sctp_tcb *stcb = NULL;
3762 struct sctp_inpcb *inp = NULL;
3765 if (optval == NULL) {
3766 SCTP_PRINTF("optval is NULL\n");
3767 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3770 inp = (struct sctp_inpcb *)so->so_pcb;
3772 SCTP_PRINTF("inp is NULL?\n");
3773 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3776 vrf_id = inp->def_vrf_id;
3781 case SCTP_AUTOCLOSE:
3782 case SCTP_AUTO_ASCONF:
3783 case SCTP_EXPLICIT_EOR:
3784 case SCTP_DISABLE_FRAGMENTS:
3785 case SCTP_USE_EXT_RCVINFO:
3786 case SCTP_I_WANT_MAPPED_V4_ADDR:
3787 /* copy in the option value */
3788 SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
3793 case SCTP_DISABLE_FRAGMENTS:
3794 set_opt = SCTP_PCB_FLAGS_NO_FRAGMENT;
3796 case SCTP_AUTO_ASCONF:
3798 * NOTE: we don't really support this flag
3800 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
3801 /* only valid for bound all sockets */
3802 if ((SCTP_BASE_SYSCTL(sctp_auto_asconf) == 0) &&
3804 /* forbidden by admin */
3805 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EPERM);
3808 set_opt = SCTP_PCB_FLAGS_AUTO_ASCONF;
3810 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3814 case SCTP_EXPLICIT_EOR:
3815 set_opt = SCTP_PCB_FLAGS_EXPLICIT_EOR;
3817 case SCTP_USE_EXT_RCVINFO:
3818 set_opt = SCTP_PCB_FLAGS_EXT_RCVINFO;
3820 case SCTP_I_WANT_MAPPED_V4_ADDR:
3821 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
3822 set_opt = SCTP_PCB_FLAGS_NEEDS_MAPPED_V4;
3824 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3829 set_opt = SCTP_PCB_FLAGS_NODELAY;
3831 case SCTP_AUTOCLOSE:
3832 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3833 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
3834 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3837 set_opt = SCTP_PCB_FLAGS_AUTOCLOSE;
3839 * The value is in ticks. Note this does not effect
3840 * old associations, only new ones.
3842 inp->sctp_ep.auto_close_time = SEC_TO_TICKS(*mopt);
3845 SCTP_INP_WLOCK(inp);
3847 sctp_feature_on(inp, set_opt);
3849 sctp_feature_off(inp, set_opt);
3851 SCTP_INP_WUNLOCK(inp);
3853 case SCTP_REUSE_PORT:
3855 SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
3856 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) {
3857 /* Can't set it after we are bound */
3861 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
3862 /* Can't do this for a 1-m socket */
3867 sctp_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE);
3869 sctp_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE);
3872 case SCTP_PARTIAL_DELIVERY_POINT:
3876 SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
3877 if (*value > SCTP_SB_LIMIT_RCV(so)) {
3878 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3882 inp->partial_delivery_point = *value;
3885 case SCTP_FRAGMENT_INTERLEAVE:
3886 /* not yet until we re-write sctp_recvmsg() */
3890 SCTP_CHECK_AND_CAST(level, optval, uint32_t, optsize);
3891 if (*level == SCTP_FRAG_LEVEL_2) {
3892 sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
3893 sctp_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
3894 } else if (*level == SCTP_FRAG_LEVEL_1) {
3895 sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
3896 sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
3897 } else if (*level == SCTP_FRAG_LEVEL_0) {
3898 sctp_feature_off(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
3899 sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
3902 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3907 case SCTP_INTERLEAVING_SUPPORTED:
3909 struct sctp_assoc_value *av;
3911 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
3912 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3915 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3917 SCTP_TCB_UNLOCK(stcb);
3919 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3920 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3921 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
3922 SCTP_INP_WLOCK(inp);
3923 if (av->assoc_value == 0) {
3924 inp->idata_supported = 0;
3926 if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE)) &&
3927 (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS))) {
3928 inp->idata_supported = 1;
3936 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3940 SCTP_INP_WUNLOCK(inp);
3942 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3948 case SCTP_CMT_ON_OFF:
3949 if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
3950 struct sctp_assoc_value *av;
3952 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
3953 if (av->assoc_value > SCTP_CMT_MAX) {
3954 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3958 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3960 stcb->asoc.sctp_cmt_on_off = av->assoc_value;
3961 SCTP_TCB_UNLOCK(stcb);
3963 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3964 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3965 (av->assoc_id == SCTP_FUTURE_ASSOC) ||
3966 (av->assoc_id == SCTP_ALL_ASSOC)) {
3967 SCTP_INP_WLOCK(inp);
3968 inp->sctp_cmt_on_off = av->assoc_value;
3969 SCTP_INP_WUNLOCK(inp);
3971 if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
3972 (av->assoc_id == SCTP_ALL_ASSOC)) {
3973 SCTP_INP_RLOCK(inp);
3974 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3975 SCTP_TCB_LOCK(stcb);
3976 stcb->asoc.sctp_cmt_on_off = av->assoc_value;
3977 SCTP_TCB_UNLOCK(stcb);
3979 SCTP_INP_RUNLOCK(inp);
3983 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
3984 error = ENOPROTOOPT;
3987 case SCTP_PLUGGABLE_CC:
3989 struct sctp_assoc_value *av;
3990 struct sctp_nets *net;
3992 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
3993 if ((av->assoc_value != SCTP_CC_RFC2581) &&
3994 (av->assoc_value != SCTP_CC_HSTCP) &&
3995 (av->assoc_value != SCTP_CC_HTCP) &&
3996 (av->assoc_value != SCTP_CC_RTCC)) {
3997 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4001 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4003 stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
4004 stcb->asoc.congestion_control_module = av->assoc_value;
4005 if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
4006 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4007 stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
4010 SCTP_TCB_UNLOCK(stcb);
4012 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4013 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4014 (av->assoc_id == SCTP_FUTURE_ASSOC) ||
4015 (av->assoc_id == SCTP_ALL_ASSOC)) {
4016 SCTP_INP_WLOCK(inp);
4017 inp->sctp_ep.sctp_default_cc_module = av->assoc_value;
4018 SCTP_INP_WUNLOCK(inp);
4020 if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4021 (av->assoc_id == SCTP_ALL_ASSOC)) {
4022 SCTP_INP_RLOCK(inp);
4023 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4024 SCTP_TCB_LOCK(stcb);
4025 stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
4026 stcb->asoc.congestion_control_module = av->assoc_value;
4027 if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
4028 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4029 stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
4032 SCTP_TCB_UNLOCK(stcb);
4034 SCTP_INP_RUNLOCK(inp);
4039 case SCTP_CC_OPTION:
4041 struct sctp_cc_option *cc_opt;
4043 SCTP_CHECK_AND_CAST(cc_opt, optval, struct sctp_cc_option, optsize);
4044 SCTP_FIND_STCB(inp, stcb, cc_opt->aid_value.assoc_id);
4046 if (cc_opt->aid_value.assoc_id == SCTP_CURRENT_ASSOC) {
4047 SCTP_INP_RLOCK(inp);
4048 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4049 SCTP_TCB_LOCK(stcb);
4050 if (stcb->asoc.cc_functions.sctp_cwnd_socket_option) {
4051 (*stcb->asoc.cc_functions.sctp_cwnd_socket_option) (stcb, 1, cc_opt);
4053 SCTP_TCB_UNLOCK(stcb);
4055 SCTP_INP_RUNLOCK(inp);
4060 if (stcb->asoc.cc_functions.sctp_cwnd_socket_option == NULL) {
4063 error = (*stcb->asoc.cc_functions.sctp_cwnd_socket_option) (stcb, 1,
4066 SCTP_TCB_UNLOCK(stcb);
4070 case SCTP_PLUGGABLE_SS:
4072 struct sctp_assoc_value *av;
4074 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4075 if ((av->assoc_value != SCTP_SS_DEFAULT) &&
4076 (av->assoc_value != SCTP_SS_ROUND_ROBIN) &&
4077 (av->assoc_value != SCTP_SS_ROUND_ROBIN_PACKET) &&
4078 (av->assoc_value != SCTP_SS_PRIORITY) &&
4079 (av->assoc_value != SCTP_SS_FAIR_BANDWITH) &&
4080 (av->assoc_value != SCTP_SS_FIRST_COME)) {
4081 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4085 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4087 stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1);
4088 stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
4089 stcb->asoc.stream_scheduling_module = av->assoc_value;
4090 stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
4091 SCTP_TCB_UNLOCK(stcb);
4093 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4094 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4095 (av->assoc_id == SCTP_FUTURE_ASSOC) ||
4096 (av->assoc_id == SCTP_ALL_ASSOC)) {
4097 SCTP_INP_WLOCK(inp);
4098 inp->sctp_ep.sctp_default_ss_module = av->assoc_value;
4099 SCTP_INP_WUNLOCK(inp);
4101 if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4102 (av->assoc_id == SCTP_ALL_ASSOC)) {
4103 SCTP_INP_RLOCK(inp);
4104 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4105 SCTP_TCB_LOCK(stcb);
4106 stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1);
4107 stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
4108 stcb->asoc.stream_scheduling_module = av->assoc_value;
4109 stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
4110 SCTP_TCB_UNLOCK(stcb);
4112 SCTP_INP_RUNLOCK(inp);
4119 struct sctp_stream_value *av;
4121 SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, optsize);
4122 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4124 if ((av->stream_id >= stcb->asoc.streamoutcnt) ||
4125 (stcb->asoc.ss_functions.sctp_ss_set_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id],
4126 av->stream_value) < 0)) {
4127 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4130 SCTP_TCB_UNLOCK(stcb);
4132 if (av->assoc_id == SCTP_CURRENT_ASSOC) {
4133 SCTP_INP_RLOCK(inp);
4134 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4135 SCTP_TCB_LOCK(stcb);
4136 if (av->stream_id < stcb->asoc.streamoutcnt) {
4137 stcb->asoc.ss_functions.sctp_ss_set_value(stcb,
4139 &stcb->asoc.strmout[av->stream_id],
4142 SCTP_TCB_UNLOCK(stcb);
4144 SCTP_INP_RUNLOCK(inp);
4147 * Can't set stream value without
4150 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4156 case SCTP_CLR_STAT_LOG:
4157 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4162 struct sctp_assoc_value *av;
4164 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4165 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4168 stcb->asoc.context = av->assoc_value;
4169 SCTP_TCB_UNLOCK(stcb);
4171 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4172 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4173 (av->assoc_id == SCTP_FUTURE_ASSOC) ||
4174 (av->assoc_id == SCTP_ALL_ASSOC)) {
4175 SCTP_INP_WLOCK(inp);
4176 inp->sctp_context = av->assoc_value;
4177 SCTP_INP_WUNLOCK(inp);
4179 if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4180 (av->assoc_id == SCTP_ALL_ASSOC)) {
4181 SCTP_INP_RLOCK(inp);
4182 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4183 SCTP_TCB_LOCK(stcb);
4184 stcb->asoc.context = av->assoc_value;
4185 SCTP_TCB_UNLOCK(stcb);
4187 SCTP_INP_RUNLOCK(inp);
4194 uint32_t *default_vrfid;
4196 SCTP_CHECK_AND_CAST(default_vrfid, optval, uint32_t, optsize);
4197 if (*default_vrfid > SCTP_MAX_VRF_ID) {
4198 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4202 inp->def_vrf_id = *default_vrfid;
4205 case SCTP_DEL_VRF_ID:
4207 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4211 case SCTP_ADD_VRF_ID:
4213 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4217 case SCTP_DELAYED_SACK:
4219 struct sctp_sack_info *sack;
4221 SCTP_CHECK_AND_CAST(sack, optval, struct sctp_sack_info, optsize);
4222 SCTP_FIND_STCB(inp, stcb, sack->sack_assoc_id);
4223 if (sack->sack_delay) {
4224 if (sack->sack_delay > SCTP_MAX_SACK_DELAY)
4225 sack->sack_delay = SCTP_MAX_SACK_DELAY;
4226 if (MSEC_TO_TICKS(sack->sack_delay) < 1) {
4227 sack->sack_delay = TICKS_TO_MSEC(1);
4231 if (sack->sack_delay) {
4232 stcb->asoc.delayed_ack = sack->sack_delay;
4234 if (sack->sack_freq) {
4235 stcb->asoc.sack_freq = sack->sack_freq;
4237 SCTP_TCB_UNLOCK(stcb);
4239 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4240 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4241 (sack->sack_assoc_id == SCTP_FUTURE_ASSOC) ||
4242 (sack->sack_assoc_id == SCTP_ALL_ASSOC)) {
4243 SCTP_INP_WLOCK(inp);
4244 if (sack->sack_delay) {
4245 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV] = MSEC_TO_TICKS(sack->sack_delay);
4247 if (sack->sack_freq) {
4248 inp->sctp_ep.sctp_sack_freq = sack->sack_freq;
4250 SCTP_INP_WUNLOCK(inp);
4252 if ((sack->sack_assoc_id == SCTP_CURRENT_ASSOC) ||
4253 (sack->sack_assoc_id == SCTP_ALL_ASSOC)) {
4254 SCTP_INP_RLOCK(inp);
4255 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4256 SCTP_TCB_LOCK(stcb);
4257 if (sack->sack_delay) {
4258 stcb->asoc.delayed_ack = sack->sack_delay;
4260 if (sack->sack_freq) {
4261 stcb->asoc.sack_freq = sack->sack_freq;
4263 SCTP_TCB_UNLOCK(stcb);
4265 SCTP_INP_RUNLOCK(inp);
4270 case SCTP_AUTH_CHUNK:
4272 struct sctp_authchunk *sauth;
4274 SCTP_CHECK_AND_CAST(sauth, optval, struct sctp_authchunk, optsize);
4276 SCTP_INP_WLOCK(inp);
4277 if (sctp_auth_add_chunk(sauth->sauth_chunk, inp->sctp_ep.local_auth_chunks)) {
4278 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4281 SCTP_INP_WUNLOCK(inp);
4286 struct sctp_authkey *sca;
4287 struct sctp_keyhead *shared_keys;
4288 sctp_sharedkey_t *shared_key;
4289 sctp_key_t *key = NULL;
4292 SCTP_CHECK_AND_CAST(sca, optval, struct sctp_authkey, optsize);
4293 if (sca->sca_keylength == 0) {
4294 size = optsize - sizeof(struct sctp_authkey);
4296 if (sca->sca_keylength + sizeof(struct sctp_authkey) <= optsize) {
4297 size = sca->sca_keylength;
4299 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4304 SCTP_FIND_STCB(inp, stcb, sca->sca_assoc_id);
4307 shared_keys = &stcb->asoc.shared_keys;
4308 /* clear the cached keys for this key id */
4309 sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
4311 * create the new shared key and
4315 key = sctp_set_key(sca->sca_key, (uint32_t) size);
4317 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4319 SCTP_TCB_UNLOCK(stcb);
4323 shared_key = sctp_alloc_sharedkey();
4324 if (shared_key == NULL) {
4326 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4328 SCTP_TCB_UNLOCK(stcb);
4331 shared_key->key = key;
4332 shared_key->keyid = sca->sca_keynumber;
4333 error = sctp_insert_sharedkey(shared_keys, shared_key);
4334 SCTP_TCB_UNLOCK(stcb);
4336 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4337 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4338 (sca->sca_assoc_id == SCTP_FUTURE_ASSOC) ||
4339 (sca->sca_assoc_id == SCTP_ALL_ASSOC)) {
4340 SCTP_INP_WLOCK(inp);
4341 shared_keys = &inp->sctp_ep.shared_keys;
4343 * clear the cached keys on all
4344 * assocs for this key id
4346 sctp_clear_cachedkeys_ep(inp, sca->sca_keynumber);
4348 * create the new shared key and
4352 key = sctp_set_key(sca->sca_key, (uint32_t) size);
4354 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4356 SCTP_INP_WUNLOCK(inp);
4360 shared_key = sctp_alloc_sharedkey();
4361 if (shared_key == NULL) {
4363 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4365 SCTP_INP_WUNLOCK(inp);
4368 shared_key->key = key;
4369 shared_key->keyid = sca->sca_keynumber;
4370 error = sctp_insert_sharedkey(shared_keys, shared_key);
4371 SCTP_INP_WUNLOCK(inp);
4373 if ((sca->sca_assoc_id == SCTP_CURRENT_ASSOC) ||
4374 (sca->sca_assoc_id == SCTP_ALL_ASSOC)) {
4375 SCTP_INP_RLOCK(inp);
4376 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4377 SCTP_TCB_LOCK(stcb);
4378 shared_keys = &stcb->asoc.shared_keys;
4380 * clear the cached keys for
4383 sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
4385 * create the new shared key
4386 * and insert/replace it
4389 key = sctp_set_key(sca->sca_key, (uint32_t) size);
4391 SCTP_TCB_UNLOCK(stcb);
4395 shared_key = sctp_alloc_sharedkey();
4396 if (shared_key == NULL) {
4398 SCTP_TCB_UNLOCK(stcb);
4401 shared_key->key = key;
4402 shared_key->keyid = sca->sca_keynumber;
4403 error = sctp_insert_sharedkey(shared_keys, shared_key);
4404 SCTP_TCB_UNLOCK(stcb);
4406 SCTP_INP_RUNLOCK(inp);
4411 case SCTP_HMAC_IDENT:
4413 struct sctp_hmacalgo *shmac;
4414 sctp_hmaclist_t *hmaclist;
4418 SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, optsize);
4419 if ((optsize < sizeof(struct sctp_hmacalgo) + shmac->shmac_number_of_idents * sizeof(uint16_t)) ||
4420 (shmac->shmac_number_of_idents > 0xffff)) {
4421 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4425 hmaclist = sctp_alloc_hmaclist((uint16_t) shmac->shmac_number_of_idents);
4426 if (hmaclist == NULL) {
4427 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4431 for (i = 0; i < shmac->shmac_number_of_idents; i++) {
4432 hmacid = shmac->shmac_idents[i];
4433 if (sctp_auth_add_hmacid(hmaclist, hmacid)) {
4434 /* invalid HMACs were found */ ;
4435 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4437 sctp_free_hmaclist(hmaclist);
4438 goto sctp_set_hmac_done;
4441 for (i = 0; i < hmaclist->num_algo; i++) {
4442 if (hmaclist->hmac[i] == SCTP_AUTH_HMAC_ID_SHA1) {
4443 /* already in list */
4447 if (i == hmaclist->num_algo) {
4448 /* not found in list */
4449 sctp_free_hmaclist(hmaclist);
4450 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4454 /* set it on the endpoint */
4455 SCTP_INP_WLOCK(inp);
4456 if (inp->sctp_ep.local_hmacs)
4457 sctp_free_hmaclist(inp->sctp_ep.local_hmacs);
4458 inp->sctp_ep.local_hmacs = hmaclist;
4459 SCTP_INP_WUNLOCK(inp);
4463 case SCTP_AUTH_ACTIVE_KEY:
4465 struct sctp_authkeyid *scact;
4467 SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, optsize);
4468 SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id);
4470 /* set the active key on the right place */
4472 /* set the active key on the assoc */
4473 if (sctp_auth_setactivekey(stcb,
4474 scact->scact_keynumber)) {
4475 SCTP_LTRACE_ERR_RET(inp, NULL, NULL,
4476 SCTP_FROM_SCTP_USRREQ,
4480 SCTP_TCB_UNLOCK(stcb);
4482 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4483 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4484 (scact->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
4485 (scact->scact_assoc_id == SCTP_ALL_ASSOC)) {
4486 SCTP_INP_WLOCK(inp);
4487 if (sctp_auth_setactivekey_ep(inp, scact->scact_keynumber)) {
4488 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4491 SCTP_INP_WUNLOCK(inp);
4493 if ((scact->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
4494 (scact->scact_assoc_id == SCTP_ALL_ASSOC)) {
4495 SCTP_INP_RLOCK(inp);
4496 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4497 SCTP_TCB_LOCK(stcb);
4498 sctp_auth_setactivekey(stcb, scact->scact_keynumber);
4499 SCTP_TCB_UNLOCK(stcb);
4501 SCTP_INP_RUNLOCK(inp);
4506 case SCTP_AUTH_DELETE_KEY:
4508 struct sctp_authkeyid *scdel;
4510 SCTP_CHECK_AND_CAST(scdel, optval, struct sctp_authkeyid, optsize);
4511 SCTP_FIND_STCB(inp, stcb, scdel->scact_assoc_id);
4513 /* delete the key from the right place */
4515 if (sctp_delete_sharedkey(stcb, scdel->scact_keynumber)) {
4516 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4519 SCTP_TCB_UNLOCK(stcb);
4521 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4522 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4523 (scdel->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
4524 (scdel->scact_assoc_id == SCTP_ALL_ASSOC)) {
4525 SCTP_INP_WLOCK(inp);
4526 if (sctp_delete_sharedkey_ep(inp, scdel->scact_keynumber)) {
4527 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4530 SCTP_INP_WUNLOCK(inp);
4532 if ((scdel->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
4533 (scdel->scact_assoc_id == SCTP_ALL_ASSOC)) {
4534 SCTP_INP_RLOCK(inp);
4535 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4536 SCTP_TCB_LOCK(stcb);
4537 sctp_delete_sharedkey(stcb, scdel->scact_keynumber);
4538 SCTP_TCB_UNLOCK(stcb);
4540 SCTP_INP_RUNLOCK(inp);
4545 case SCTP_AUTH_DEACTIVATE_KEY:
4547 struct sctp_authkeyid *keyid;
4549 SCTP_CHECK_AND_CAST(keyid, optval, struct sctp_authkeyid, optsize);
4550 SCTP_FIND_STCB(inp, stcb, keyid->scact_assoc_id);
4552 /* deactivate the key from the right place */
4554 if (sctp_deact_sharedkey(stcb, keyid->scact_keynumber)) {
4555 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4558 SCTP_TCB_UNLOCK(stcb);
4560 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4561 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4562 (keyid->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
4563 (keyid->scact_assoc_id == SCTP_ALL_ASSOC)) {
4564 SCTP_INP_WLOCK(inp);
4565 if (sctp_deact_sharedkey_ep(inp, keyid->scact_keynumber)) {
4566 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4569 SCTP_INP_WUNLOCK(inp);
4571 if ((keyid->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
4572 (keyid->scact_assoc_id == SCTP_ALL_ASSOC)) {
4573 SCTP_INP_RLOCK(inp);
4574 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4575 SCTP_TCB_LOCK(stcb);
4576 sctp_deact_sharedkey(stcb, keyid->scact_keynumber);
4577 SCTP_TCB_UNLOCK(stcb);
4579 SCTP_INP_RUNLOCK(inp);
4584 case SCTP_ENABLE_STREAM_RESET:
4586 struct sctp_assoc_value *av;
4588 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4589 if (av->assoc_value & (~SCTP_ENABLE_VALUE_MASK)) {
4590 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4594 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4596 stcb->asoc.local_strreset_support = (uint8_t) av->assoc_value;
4597 SCTP_TCB_UNLOCK(stcb);
4599 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4600 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4601 (av->assoc_id == SCTP_FUTURE_ASSOC) ||
4602 (av->assoc_id == SCTP_ALL_ASSOC)) {
4603 SCTP_INP_WLOCK(inp);
4604 inp->local_strreset_support = (uint8_t) av->assoc_value;
4605 SCTP_INP_WUNLOCK(inp);
4607 if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4608 (av->assoc_id == SCTP_ALL_ASSOC)) {
4609 SCTP_INP_RLOCK(inp);
4610 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4611 SCTP_TCB_LOCK(stcb);
4612 stcb->asoc.local_strreset_support = (uint8_t) av->assoc_value;
4613 SCTP_TCB_UNLOCK(stcb);
4615 SCTP_INP_RUNLOCK(inp);
4620 case SCTP_RESET_STREAMS:
4622 struct sctp_reset_streams *strrst;
4623 int i, send_out = 0;
4626 SCTP_CHECK_AND_CAST(strrst, optval, struct sctp_reset_streams, optsize);
4627 SCTP_FIND_STCB(inp, stcb, strrst->srs_assoc_id);
4629 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4633 if (stcb->asoc.reconfig_supported == 0) {
4635 * Peer does not support the chunk type.
4637 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4639 SCTP_TCB_UNLOCK(stcb);
4642 if (sizeof(struct sctp_reset_streams) +
4643 strrst->srs_number_streams * sizeof(uint16_t) > optsize) {
4645 SCTP_TCB_UNLOCK(stcb);
4648 if (strrst->srs_flags & SCTP_STREAM_RESET_INCOMING) {
4650 if (stcb->asoc.stream_reset_outstanding) {
4651 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4653 SCTP_TCB_UNLOCK(stcb);
4657 if (strrst->srs_flags & SCTP_STREAM_RESET_OUTGOING) {
4660 if ((strrst->srs_number_streams > SCTP_MAX_STREAMS_AT_ONCE_RESET) && send_in) {
4661 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4663 SCTP_TCB_UNLOCK(stcb);
4666 if ((send_in == 0) && (send_out == 0)) {
4667 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4669 SCTP_TCB_UNLOCK(stcb);
4672 for (i = 0; i < strrst->srs_number_streams; i++) {
4674 (strrst->srs_stream_list[i] > stcb->asoc.streamincnt)) {
4675 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4680 (strrst->srs_stream_list[i] > stcb->asoc.streamoutcnt)) {
4681 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4687 SCTP_TCB_UNLOCK(stcb);
4694 if (strrst->srs_number_streams) {
4695 for (i = 0, cnt = 0; i < strrst->srs_number_streams; i++) {
4696 strm = strrst->srs_stream_list[i];
4697 if (stcb->asoc.strmout[strm].state == SCTP_STREAM_OPEN) {
4698 stcb->asoc.strmout[strm].state = SCTP_STREAM_RESET_PENDING;
4704 for (i = 0, cnt = 0; i < stcb->asoc.streamoutcnt; i++) {
4705 if (stcb->asoc.strmout[i].state == SCTP_STREAM_OPEN) {
4706 stcb->asoc.strmout[i].state = SCTP_STREAM_RESET_PENDING;
4713 error = sctp_send_str_reset_req(stcb, strrst->srs_number_streams,
4714 strrst->srs_stream_list,
4715 send_in, 0, 0, 0, 0, 0);
4717 error = sctp_send_stream_reset_out_if_possible(stcb, SCTP_SO_LOCKED);
4720 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
4723 * For outgoing streams don't report any
4724 * problems in sending the request to the
4725 * application. XXX: Double check resetting
4730 SCTP_TCB_UNLOCK(stcb);
4733 case SCTP_ADD_STREAMS:
4735 struct sctp_add_streams *stradd;
4736 uint8_t addstream = 0;
4737 uint16_t add_o_strmcnt = 0;
4738 uint16_t add_i_strmcnt = 0;
4740 SCTP_CHECK_AND_CAST(stradd, optval, struct sctp_add_streams, optsize);
4741 SCTP_FIND_STCB(inp, stcb, stradd->sas_assoc_id);
4743 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4747 if (stcb->asoc.reconfig_supported == 0) {
4749 * Peer does not support the chunk type.
4751 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4753 SCTP_TCB_UNLOCK(stcb);
4756 if (stcb->asoc.stream_reset_outstanding) {
4757 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4759 SCTP_TCB_UNLOCK(stcb);
4762 if ((stradd->sas_outstrms == 0) &&
4763 (stradd->sas_instrms == 0)) {
4767 if (stradd->sas_outstrms) {
4769 /* We allocate here */
4770 add_o_strmcnt = stradd->sas_outstrms;
4771 if ((((int)add_o_strmcnt) + ((int)stcb->asoc.streamoutcnt)) > 0x0000ffff) {
4772 /* You can't have more than 64k */
4777 if (stradd->sas_instrms) {
4782 * We allocate inside
4783 * sctp_send_str_reset_req()
4785 add_i_strmcnt = stradd->sas_instrms;
4786 cnt = add_i_strmcnt;
4787 cnt += stcb->asoc.streamincnt;
4788 if (cnt > 0x0000ffff) {
4789 /* You can't have more than 64k */
4793 if (cnt > (int)stcb->asoc.max_inbound_streams) {
4794 /* More than you are allowed */
4799 error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, addstream, add_o_strmcnt, add_i_strmcnt, 0);
4800 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
4802 SCTP_TCB_UNLOCK(stcb);
4805 case SCTP_RESET_ASSOC:
4810 SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
4811 SCTP_FIND_STCB(inp, stcb, (sctp_assoc_t) * value);
4813 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4817 if (stcb->asoc.reconfig_supported == 0) {
4819 * Peer does not support the chunk type.
4821 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4823 SCTP_TCB_UNLOCK(stcb);
4826 if (stcb->asoc.stream_reset_outstanding) {
4827 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4829 SCTP_TCB_UNLOCK(stcb);
4833 * Is there any data pending in the send or sent
4836 if (!TAILQ_EMPTY(&stcb->asoc.send_queue) ||
4837 !TAILQ_EMPTY(&stcb->asoc.sent_queue)) {
4840 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
4841 SCTP_TCB_UNLOCK(stcb);
4844 /* Do any streams have data queued? */
4845 for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
4846 if (!TAILQ_EMPTY(&stcb->asoc.strmout[i].outqueue)) {
4850 error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 1, 0, 0, 0, 0);
4851 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
4852 SCTP_TCB_UNLOCK(stcb);
4855 case SCTP_CONNECT_X:
4856 if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
4857 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4861 error = sctp_do_connect_x(so, inp, optval, optsize, p, 0);
4863 case SCTP_CONNECT_X_DELAYED:
4864 if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
4865 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4869 error = sctp_do_connect_x(so, inp, optval, optsize, p, 1);
4871 case SCTP_CONNECT_X_COMPLETE:
4873 struct sockaddr *sa;
4875 /* FIXME MT: check correct? */
4876 SCTP_CHECK_AND_CAST(sa, optval, struct sockaddr, optsize);
4879 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
4880 SCTP_INP_RLOCK(inp);
4881 stcb = LIST_FIRST(&inp->sctp_asoc_list);
4883 SCTP_TCB_LOCK(stcb);
4885 SCTP_INP_RUNLOCK(inp);
4888 * We increment here since
4889 * sctp_findassociation_ep_addr() wil do a
4890 * decrement if it finds the stcb as long as
4891 * the locked tcb (last argument) is NOT a
4894 SCTP_INP_INCR_REF(inp);
4895 stcb = sctp_findassociation_ep_addr(&inp, sa, NULL, NULL, NULL);
4897 SCTP_INP_DECR_REF(inp);
4902 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4906 if (stcb->asoc.delayed_connection == 1) {
4907 stcb->asoc.delayed_connection = 0;
4908 (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
4909 sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb,
4910 stcb->asoc.primary_destination,
4911 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_8);
4912 sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
4915 * already expired or did not use delayed
4918 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4921 SCTP_TCB_UNLOCK(stcb);
4924 case SCTP_MAX_BURST:
4926 struct sctp_assoc_value *av;
4928 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4929 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4932 stcb->asoc.max_burst = av->assoc_value;
4933 SCTP_TCB_UNLOCK(stcb);
4935 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4936 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4937 (av->assoc_id == SCTP_FUTURE_ASSOC) ||
4938 (av->assoc_id == SCTP_ALL_ASSOC)) {
4939 SCTP_INP_WLOCK(inp);
4940 inp->sctp_ep.max_burst = av->assoc_value;
4941 SCTP_INP_WUNLOCK(inp);
4943 if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4944 (av->assoc_id == SCTP_ALL_ASSOC)) {
4945 SCTP_INP_RLOCK(inp);
4946 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4947 SCTP_TCB_LOCK(stcb);
4948 stcb->asoc.max_burst = av->assoc_value;
4949 SCTP_TCB_UNLOCK(stcb);
4951 SCTP_INP_RUNLOCK(inp);
4958 struct sctp_assoc_value *av;
4961 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4962 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4964 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
4965 ovh = SCTP_MED_OVERHEAD;
4967 ovh = SCTP_MED_V4_OVERHEAD;
4970 if (av->assoc_value) {
4971 stcb->asoc.sctp_frag_point = (av->assoc_value + ovh);
4973 stcb->asoc.sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
4975 SCTP_TCB_UNLOCK(stcb);
4977 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4978 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4979 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
4980 SCTP_INP_WLOCK(inp);
4982 * FIXME MT: I think this is not in
4983 * tune with the API ID
4985 if (av->assoc_value) {
4986 inp->sctp_frag_point = (av->assoc_value + ovh);
4988 inp->sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
4990 SCTP_INP_WUNLOCK(inp);
4992 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5000 struct sctp_event_subscribe *events;
5002 SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, optsize);
5004 SCTP_INP_WLOCK(inp);
5005 if (events->sctp_data_io_event) {
5006 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
5008 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
5011 if (events->sctp_association_event) {
5012 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
5014 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
5017 if (events->sctp_address_event) {
5018 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
5020 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
5023 if (events->sctp_send_failure_event) {
5024 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
5026 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
5029 if (events->sctp_peer_error_event) {
5030 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPEERERR);
5032 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPEERERR);
5035 if (events->sctp_shutdown_event) {
5036 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
5038 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
5041 if (events->sctp_partial_delivery_event) {
5042 sctp_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
5044 sctp_feature_off(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
5047 if (events->sctp_adaptation_layer_event) {
5048 sctp_feature_on(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
5050 sctp_feature_off(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
5053 if (events->sctp_authentication_event) {
5054 sctp_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT);
5056 sctp_feature_off(inp, SCTP_PCB_FLAGS_AUTHEVNT);
5059 if (events->sctp_sender_dry_event) {
5060 sctp_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT);
5062 sctp_feature_off(inp, SCTP_PCB_FLAGS_DRYEVNT);
5065 if (events->sctp_stream_reset_event) {
5066 sctp_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
5068 sctp_feature_off(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
5070 SCTP_INP_WUNLOCK(inp);
5072 SCTP_INP_RLOCK(inp);
5073 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5074 SCTP_TCB_LOCK(stcb);
5075 if (events->sctp_association_event) {
5076 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
5078 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
5080 if (events->sctp_address_event) {
5081 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
5083 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
5085 if (events->sctp_send_failure_event) {
5086 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
5088 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
5090 if (events->sctp_peer_error_event) {
5091 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
5093 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
5095 if (events->sctp_shutdown_event) {
5096 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
5098 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
5100 if (events->sctp_partial_delivery_event) {
5101 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
5103 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
5105 if (events->sctp_adaptation_layer_event) {
5106 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
5108 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
5110 if (events->sctp_authentication_event) {
5111 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
5113 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
5115 if (events->sctp_sender_dry_event) {
5116 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
5118 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
5120 if (events->sctp_stream_reset_event) {
5121 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
5123 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
5125 SCTP_TCB_UNLOCK(stcb);
5128 * Send up the sender dry event only for 1-to-1
5131 if (events->sctp_sender_dry_event) {
5132 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5133 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
5134 stcb = LIST_FIRST(&inp->sctp_asoc_list);
5136 SCTP_TCB_LOCK(stcb);
5137 if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
5138 TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
5139 (stcb->asoc.stream_queue_cnt == 0)) {
5140 sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_LOCKED);
5142 SCTP_TCB_UNLOCK(stcb);
5146 SCTP_INP_RUNLOCK(inp);
5149 case SCTP_ADAPTATION_LAYER:
5151 struct sctp_setadaptation *adap_bits;
5153 SCTP_CHECK_AND_CAST(adap_bits, optval, struct sctp_setadaptation, optsize);
5154 SCTP_INP_WLOCK(inp);
5155 inp->sctp_ep.adaptation_layer_indicator = adap_bits->ssb_adaptation_ind;
5156 inp->sctp_ep.adaptation_layer_indicator_provided = 1;
5157 SCTP_INP_WUNLOCK(inp);
5161 case SCTP_SET_INITIAL_DBG_SEQ:
5165 SCTP_CHECK_AND_CAST(vvv, optval, uint32_t, optsize);
5166 SCTP_INP_WLOCK(inp);
5167 inp->sctp_ep.initial_sequence_debug = *vvv;
5168 SCTP_INP_WUNLOCK(inp);
5172 case SCTP_DEFAULT_SEND_PARAM:
5174 struct sctp_sndrcvinfo *s_info;
5176 SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, optsize);
5177 SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
5180 if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
5181 memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
5183 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5186 SCTP_TCB_UNLOCK(stcb);
5188 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5189 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5190 (s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC) ||
5191 (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)) {
5192 SCTP_INP_WLOCK(inp);
5193 memcpy(&inp->def_send, s_info, min(optsize, sizeof(inp->def_send)));
5194 SCTP_INP_WUNLOCK(inp);
5196 if ((s_info->sinfo_assoc_id == SCTP_CURRENT_ASSOC) ||
5197 (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)) {
5198 SCTP_INP_RLOCK(inp);
5199 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5200 SCTP_TCB_LOCK(stcb);
5201 if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
5202 memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
5204 SCTP_TCB_UNLOCK(stcb);
5206 SCTP_INP_RUNLOCK(inp);
5211 case SCTP_PEER_ADDR_PARAMS:
5213 struct sctp_paddrparams *paddrp;
5214 struct sctp_nets *net;
5215 struct sockaddr *addr;
5217 #if defined(INET) && defined(INET6)
5218 struct sockaddr_in sin_store;
5222 SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, optsize);
5223 SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
5225 #if defined(INET) && defined(INET6)
5226 if (paddrp->spp_address.ss_family == AF_INET6) {
5227 struct sockaddr_in6 *sin6;
5229 sin6 = (struct sockaddr_in6 *)&paddrp->spp_address;
5230 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
5231 in6_sin6_2_sin(&sin_store, sin6);
5232 addr = (struct sockaddr *)&sin_store;
5234 addr = (struct sockaddr *)&paddrp->spp_address;
5237 addr = (struct sockaddr *)&paddrp->spp_address;
5240 addr = (struct sockaddr *)&paddrp->spp_address;
5243 net = sctp_findnet(stcb, addr);
5246 * We increment here since
5247 * sctp_findassociation_ep_addr() wil do a
5248 * decrement if it finds the stcb as long as
5249 * the locked tcb (last argument) is NOT a
5253 SCTP_INP_INCR_REF(inp);
5254 stcb = sctp_findassociation_ep_addr(&inp, addr,
5257 SCTP_INP_DECR_REF(inp);
5260 if ((stcb != NULL) && (net == NULL)) {
5262 if (addr->sa_family == AF_INET) {
5264 struct sockaddr_in *sin;
5266 sin = (struct sockaddr_in *)addr;
5267 if (sin->sin_addr.s_addr != INADDR_ANY) {
5268 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5269 SCTP_TCB_UNLOCK(stcb);
5276 if (addr->sa_family == AF_INET6) {
5277 struct sockaddr_in6 *sin6;
5279 sin6 = (struct sockaddr_in6 *)addr;
5280 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
5281 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5282 SCTP_TCB_UNLOCK(stcb);
5289 error = EAFNOSUPPORT;
5290 SCTP_TCB_UNLOCK(stcb);
5291 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
5296 if ((paddrp->spp_flags & SPP_HB_ENABLE) && (paddrp->spp_flags & SPP_HB_DISABLE)) {
5298 SCTP_TCB_UNLOCK(stcb);
5299 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5302 if ((paddrp->spp_flags & SPP_PMTUD_ENABLE) && (paddrp->spp_flags & SPP_PMTUD_DISABLE)) {
5304 SCTP_TCB_UNLOCK(stcb);
5305 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5309 /************************TCB SPECIFIC SET ******************/
5311 /************************NET SPECIFIC SET ******************/
5312 if (paddrp->spp_flags & SPP_HB_DISABLE) {
5313 if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
5314 !(net->dest_state & SCTP_ADDR_NOHB)) {
5315 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
5316 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_9);
5318 net->dest_state |= SCTP_ADDR_NOHB;
5320 if (paddrp->spp_flags & SPP_HB_ENABLE) {
5321 if (paddrp->spp_hbinterval) {
5322 net->heart_beat_delay = paddrp->spp_hbinterval;
5323 } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
5324 net->heart_beat_delay = 0;
5326 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
5327 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
5328 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
5329 net->dest_state &= ~SCTP_ADDR_NOHB;
5331 if (paddrp->spp_flags & SPP_HB_DEMAND) {
5333 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5334 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED);
5335 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
5337 if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
5338 if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
5339 sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
5340 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_11);
5342 net->dest_state |= SCTP_ADDR_NO_PMTUD;
5343 net->mtu = paddrp->spp_pathmtu;
5344 switch (net->ro._l_addr.sa.sa_family) {
5347 net->mtu += SCTP_MIN_V4_OVERHEAD;
5352 net->mtu += SCTP_MIN_OVERHEAD;
5358 if (net->mtu < stcb->asoc.smallest_mtu) {
5359 sctp_pathmtu_adjustment(stcb, net->mtu);
5362 if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
5363 if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
5364 sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
5366 net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
5368 if (paddrp->spp_pathmaxrxt) {
5369 if (net->dest_state & SCTP_ADDR_PF) {
5370 if (net->error_count > paddrp->spp_pathmaxrxt) {
5371 net->dest_state &= ~SCTP_ADDR_PF;
5374 if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
5375 (net->error_count > net->pf_threshold)) {
5376 net->dest_state |= SCTP_ADDR_PF;
5377 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5378 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT,
5379 stcb->sctp_ep, stcb, net,
5380 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_12);
5381 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
5384 if (net->dest_state & SCTP_ADDR_REACHABLE) {
5385 if (net->error_count > paddrp->spp_pathmaxrxt) {
5386 net->dest_state &= ~SCTP_ADDR_REACHABLE;
5387 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
5390 if (net->error_count <= paddrp->spp_pathmaxrxt) {
5391 net->dest_state |= SCTP_ADDR_REACHABLE;
5392 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
5395 net->failure_threshold = paddrp->spp_pathmaxrxt;
5397 if (paddrp->spp_flags & SPP_DSCP) {
5398 net->dscp = paddrp->spp_dscp & 0xfc;
5402 if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
5403 if (net->ro._l_addr.sa.sa_family == AF_INET6) {
5404 net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5405 net->flowlabel |= 0x80000000;
5410 /************************ASSOC ONLY -- NO NET SPECIFIC SET ******************/
5411 if (paddrp->spp_pathmaxrxt != 0) {
5412 stcb->asoc.def_net_failure = paddrp->spp_pathmaxrxt;
5413 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5414 if (net->dest_state & SCTP_ADDR_PF) {
5415 if (net->error_count > paddrp->spp_pathmaxrxt) {
5416 net->dest_state &= ~SCTP_ADDR_PF;
5419 if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
5420 (net->error_count > net->pf_threshold)) {
5421 net->dest_state |= SCTP_ADDR_PF;
5422 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5423 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT,
5424 stcb->sctp_ep, stcb, net,
5425 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_13);
5426 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
5429 if (net->dest_state & SCTP_ADDR_REACHABLE) {
5430 if (net->error_count > paddrp->spp_pathmaxrxt) {
5431 net->dest_state &= ~SCTP_ADDR_REACHABLE;
5432 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
5435 if (net->error_count <= paddrp->spp_pathmaxrxt) {
5436 net->dest_state |= SCTP_ADDR_REACHABLE;
5437 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
5440 net->failure_threshold = paddrp->spp_pathmaxrxt;
5443 if (paddrp->spp_flags & SPP_HB_ENABLE) {
5444 if (paddrp->spp_hbinterval != 0) {
5445 stcb->asoc.heart_beat_delay = paddrp->spp_hbinterval;
5446 } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
5447 stcb->asoc.heart_beat_delay = 0;
5449 /* Turn back on the timer */
5450 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5451 if (paddrp->spp_hbinterval != 0) {
5452 net->heart_beat_delay = paddrp->spp_hbinterval;
5453 } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
5454 net->heart_beat_delay = 0;
5456 if (net->dest_state & SCTP_ADDR_NOHB) {
5457 net->dest_state &= ~SCTP_ADDR_NOHB;
5459 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
5460 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_14);
5461 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
5463 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5465 if (paddrp->spp_flags & SPP_HB_DISABLE) {
5466 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5467 if (!(net->dest_state & SCTP_ADDR_NOHB)) {
5468 net->dest_state |= SCTP_ADDR_NOHB;
5469 if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED)) {
5470 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT,
5472 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_15);
5476 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5478 if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
5479 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5480 if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
5481 sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
5482 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_16);
5484 net->dest_state |= SCTP_ADDR_NO_PMTUD;
5485 net->mtu = paddrp->spp_pathmtu;
5486 switch (net->ro._l_addr.sa.sa_family) {
5489 net->mtu += SCTP_MIN_V4_OVERHEAD;
5494 net->mtu += SCTP_MIN_OVERHEAD;
5500 if (net->mtu < stcb->asoc.smallest_mtu) {
5501 sctp_pathmtu_adjustment(stcb, net->mtu);
5504 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5506 if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
5507 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5508 if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
5509 sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
5511 net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
5513 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5515 if (paddrp->spp_flags & SPP_DSCP) {
5516 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5517 net->dscp = paddrp->spp_dscp & 0xfc;
5520 stcb->asoc.default_dscp = paddrp->spp_dscp & 0xfc;
5521 stcb->asoc.default_dscp |= 0x01;
5524 if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
5525 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5526 if (net->ro._l_addr.sa.sa_family == AF_INET6) {
5527 net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5528 net->flowlabel |= 0x80000000;
5531 stcb->asoc.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5532 stcb->asoc.default_flowlabel |= 0x80000000;
5536 SCTP_TCB_UNLOCK(stcb);
5538 /************************NO TCB, SET TO default stuff ******************/
5539 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5540 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5541 (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC)) {
5542 SCTP_INP_WLOCK(inp);
5544 * For the TOS/FLOWLABEL stuff you
5545 * set it with the options on the
5548 if (paddrp->spp_pathmaxrxt != 0) {
5549 inp->sctp_ep.def_net_failure = paddrp->spp_pathmaxrxt;
5551 if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO)
5552 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
5553 else if (paddrp->spp_hbinterval != 0) {
5554 if (paddrp->spp_hbinterval > SCTP_MAX_HB_INTERVAL)
5555 paddrp->spp_hbinterval = SCTP_MAX_HB_INTERVAL;
5556 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
5558 if (paddrp->spp_flags & SPP_HB_ENABLE) {
5559 if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
5560 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
5561 } else if (paddrp->spp_hbinterval) {
5562 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
5564 sctp_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5565 } else if (paddrp->spp_flags & SPP_HB_DISABLE) {
5566 sctp_feature_on(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5568 if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
5569 sctp_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5570 } else if (paddrp->spp_flags & SPP_PMTUD_DISABLE) {
5571 sctp_feature_on(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5573 if (paddrp->spp_flags & SPP_DSCP) {
5574 inp->sctp_ep.default_dscp = paddrp->spp_dscp & 0xfc;
5575 inp->sctp_ep.default_dscp |= 0x01;
5578 if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
5579 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
5580 inp->sctp_ep.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5581 inp->sctp_ep.default_flowlabel |= 0x80000000;
5585 SCTP_INP_WUNLOCK(inp);
5587 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5595 struct sctp_rtoinfo *srto;
5596 uint32_t new_init, new_min, new_max;
5598 SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, optsize);
5599 SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
5602 if (srto->srto_initial)
5603 new_init = srto->srto_initial;
5605 new_init = stcb->asoc.initial_rto;
5607 new_max = srto->srto_max;
5609 new_max = stcb->asoc.maxrto;
5611 new_min = srto->srto_min;
5613 new_min = stcb->asoc.minrto;
5614 if ((new_min <= new_init) && (new_init <= new_max)) {
5615 stcb->asoc.initial_rto = new_init;
5616 stcb->asoc.maxrto = new_max;
5617 stcb->asoc.minrto = new_min;
5619 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5622 SCTP_TCB_UNLOCK(stcb);
5624 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5625 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5626 (srto->srto_assoc_id == SCTP_FUTURE_ASSOC)) {
5627 SCTP_INP_WLOCK(inp);
5628 if (srto->srto_initial)
5629 new_init = srto->srto_initial;
5631 new_init = inp->sctp_ep.initial_rto;
5633 new_max = srto->srto_max;
5635 new_max = inp->sctp_ep.sctp_maxrto;
5637 new_min = srto->srto_min;
5639 new_min = inp->sctp_ep.sctp_minrto;
5640 if ((new_min <= new_init) && (new_init <= new_max)) {
5641 inp->sctp_ep.initial_rto = new_init;
5642 inp->sctp_ep.sctp_maxrto = new_max;
5643 inp->sctp_ep.sctp_minrto = new_min;
5645 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5648 SCTP_INP_WUNLOCK(inp);
5650 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5656 case SCTP_ASSOCINFO:
5658 struct sctp_assocparams *sasoc;
5660 SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, optsize);
5661 SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
5662 if (sasoc->sasoc_cookie_life) {
5663 /* boundary check the cookie life */
5664 if (sasoc->sasoc_cookie_life < 1000)
5665 sasoc->sasoc_cookie_life = 1000;
5666 if (sasoc->sasoc_cookie_life > SCTP_MAX_COOKIE_LIFE) {
5667 sasoc->sasoc_cookie_life = SCTP_MAX_COOKIE_LIFE;
5671 if (sasoc->sasoc_asocmaxrxt)
5672 stcb->asoc.max_send_times = sasoc->sasoc_asocmaxrxt;
5673 if (sasoc->sasoc_cookie_life) {
5674 stcb->asoc.cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
5676 SCTP_TCB_UNLOCK(stcb);
5678 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5679 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5680 (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC)) {
5681 SCTP_INP_WLOCK(inp);
5682 if (sasoc->sasoc_asocmaxrxt)
5683 inp->sctp_ep.max_send_times = sasoc->sasoc_asocmaxrxt;
5684 if (sasoc->sasoc_cookie_life) {
5685 inp->sctp_ep.def_cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
5687 SCTP_INP_WUNLOCK(inp);
5689 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5697 struct sctp_initmsg *sinit;
5699 SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, optsize);
5700 SCTP_INP_WLOCK(inp);
5701 if (sinit->sinit_num_ostreams)
5702 inp->sctp_ep.pre_open_stream_count = sinit->sinit_num_ostreams;
5704 if (sinit->sinit_max_instreams)
5705 inp->sctp_ep.max_open_streams_intome = sinit->sinit_max_instreams;
5707 if (sinit->sinit_max_attempts)
5708 inp->sctp_ep.max_init_times = sinit->sinit_max_attempts;
5710 if (sinit->sinit_max_init_timeo)
5711 inp->sctp_ep.initial_init_rto_max = sinit->sinit_max_init_timeo;
5712 SCTP_INP_WUNLOCK(inp);
5715 case SCTP_PRIMARY_ADDR:
5717 struct sctp_setprim *spa;
5718 struct sctp_nets *net;
5719 struct sockaddr *addr;
5721 #if defined(INET) && defined(INET6)
5722 struct sockaddr_in sin_store;
5726 SCTP_CHECK_AND_CAST(spa, optval, struct sctp_setprim, optsize);
5727 SCTP_FIND_STCB(inp, stcb, spa->ssp_assoc_id);
5729 #if defined(INET) && defined(INET6)
5730 if (spa->ssp_addr.ss_family == AF_INET6) {
5731 struct sockaddr_in6 *sin6;
5733 sin6 = (struct sockaddr_in6 *)&spa->ssp_addr;
5734 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
5735 in6_sin6_2_sin(&sin_store, sin6);
5736 addr = (struct sockaddr *)&sin_store;
5738 addr = (struct sockaddr *)&spa->ssp_addr;
5741 addr = (struct sockaddr *)&spa->ssp_addr;
5744 addr = (struct sockaddr *)&spa->ssp_addr;
5747 net = sctp_findnet(stcb, addr);
5750 * We increment here since
5751 * sctp_findassociation_ep_addr() wil do a
5752 * decrement if it finds the stcb as long as
5753 * the locked tcb (last argument) is NOT a
5757 SCTP_INP_INCR_REF(inp);
5758 stcb = sctp_findassociation_ep_addr(&inp, addr,
5761 SCTP_INP_DECR_REF(inp);
5765 if ((stcb != NULL) && (net != NULL)) {
5766 if (net != stcb->asoc.primary_destination) {
5767 if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED)) {
5768 /* Ok we need to set it */
5769 if (sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net) == 0) {
5770 if ((stcb->asoc.alternate) &&
5771 (!(net->dest_state & SCTP_ADDR_PF)) &&
5772 (net->dest_state & SCTP_ADDR_REACHABLE)) {
5773 sctp_free_remote_addr(stcb->asoc.alternate);
5774 stcb->asoc.alternate = NULL;
5777 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5781 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5786 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5790 SCTP_TCB_UNLOCK(stcb);
5794 case SCTP_SET_DYNAMIC_PRIMARY:
5796 union sctp_sockstore *ss;
5798 error = priv_check(curthread,
5799 PRIV_NETINET_RESERVEDPORT);
5803 SCTP_CHECK_AND_CAST(ss, optval, union sctp_sockstore, optsize);
5804 /* SUPER USER CHECK? */
5805 error = sctp_dynamic_set_primary(&ss->sa, vrf_id);
5808 case SCTP_SET_PEER_PRIMARY_ADDR:
5810 struct sctp_setpeerprim *sspp;
5811 struct sockaddr *addr;
5813 #if defined(INET) && defined(INET6)
5814 struct sockaddr_in sin_store;
5818 SCTP_CHECK_AND_CAST(sspp, optval, struct sctp_setpeerprim, optsize);
5819 SCTP_FIND_STCB(inp, stcb, sspp->sspp_assoc_id);
5821 struct sctp_ifa *ifa;
5823 #if defined(INET) && defined(INET6)
5824 if (sspp->sspp_addr.ss_family == AF_INET6) {
5825 struct sockaddr_in6 *sin6;
5827 sin6 = (struct sockaddr_in6 *)&sspp->sspp_addr;
5828 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
5829 in6_sin6_2_sin(&sin_store, sin6);
5830 addr = (struct sockaddr *)&sin_store;
5832 addr = (struct sockaddr *)&sspp->sspp_addr;
5835 addr = (struct sockaddr *)&sspp->sspp_addr;
5838 addr = (struct sockaddr *)&sspp->sspp_addr;
5840 ifa = sctp_find_ifa_by_addr(addr, stcb->asoc.vrf_id, SCTP_ADDR_NOT_LOCKED);
5842 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5846 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
5848 * Must validate the ifa found is in
5851 struct sctp_laddr *laddr;
5854 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
5855 if (laddr->ifa == NULL) {
5856 SCTPDBG(SCTP_DEBUG_OUTPUT1, "%s: NULL ifa\n",
5860 if ((sctp_is_addr_restricted(stcb, laddr->ifa)) &&
5861 (!sctp_is_addr_pending(stcb, laddr->ifa))) {
5864 if (laddr->ifa == ifa) {
5870 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5875 switch (addr->sa_family) {
5879 struct sockaddr_in *sin;
5881 sin = (struct sockaddr_in *)addr;
5882 if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
5883 &sin->sin_addr) != 0) {
5884 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5894 struct sockaddr_in6 *sin6;
5896 sin6 = (struct sockaddr_in6 *)addr;
5897 if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
5898 &sin6->sin6_addr) != 0) {
5899 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5907 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5912 if (sctp_set_primary_ip_address_sa(stcb, addr) != 0) {
5913 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5916 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED);
5918 SCTP_TCB_UNLOCK(stcb);
5920 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5925 case SCTP_BINDX_ADD_ADDR:
5927 struct sctp_getaddresses *addrs;
5930 td = (struct thread *)p;
5931 SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses,
5934 if (addrs->addr->sa_family == AF_INET) {
5935 if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in)) {
5936 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5940 if (td != NULL && (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)(addrs->addr))->sin_addr)))) {
5941 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
5947 if (addrs->addr->sa_family == AF_INET6) {
5948 if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6)) {
5949 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5953 if (td != NULL && (error = prison_local_ip6(td->td_ucred, &(((struct sockaddr_in6 *)(addrs->addr))->sin6_addr),
5954 (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
5955 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
5961 error = EAFNOSUPPORT;
5964 sctp_bindx_add_address(so, inp, addrs->addr,
5965 addrs->sget_assoc_id, vrf_id,
5969 case SCTP_BINDX_REM_ADDR:
5971 struct sctp_getaddresses *addrs;
5974 td = (struct thread *)p;
5976 SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses, optsize);
5978 if (addrs->addr->sa_family == AF_INET) {
5979 if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in)) {
5980 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5984 if (td != NULL && (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)(addrs->addr))->sin_addr)))) {
5985 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
5991 if (addrs->addr->sa_family == AF_INET6) {
5992 if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6)) {
5993 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5998 (error = prison_local_ip6(td->td_ucred,
5999 &(((struct sockaddr_in6 *)(addrs->addr))->sin6_addr),
6000 (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
6001 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
6007 error = EAFNOSUPPORT;
6010 sctp_bindx_delete_address(inp, addrs->addr,
6011 addrs->sget_assoc_id, vrf_id,
6017 struct sctp_event *event;
6018 uint32_t event_type;
6020 SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, optsize);
6021 SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
6022 switch (event->se_type) {
6023 case SCTP_ASSOC_CHANGE:
6024 event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
6026 case SCTP_PEER_ADDR_CHANGE:
6027 event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
6029 case SCTP_REMOTE_ERROR:
6030 event_type = SCTP_PCB_FLAGS_RECVPEERERR;
6032 case SCTP_SEND_FAILED:
6033 event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
6035 case SCTP_SHUTDOWN_EVENT:
6036 event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
6038 case SCTP_ADAPTATION_INDICATION:
6039 event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
6041 case SCTP_PARTIAL_DELIVERY_EVENT:
6042 event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
6044 case SCTP_AUTHENTICATION_EVENT:
6045 event_type = SCTP_PCB_FLAGS_AUTHEVNT;
6047 case SCTP_STREAM_RESET_EVENT:
6048 event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
6050 case SCTP_SENDER_DRY_EVENT:
6051 event_type = SCTP_PCB_FLAGS_DRYEVNT;
6053 case SCTP_NOTIFICATIONS_STOPPED_EVENT:
6055 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
6058 case SCTP_ASSOC_RESET_EVENT:
6059 event_type = SCTP_PCB_FLAGS_ASSOC_RESETEVNT;
6061 case SCTP_STREAM_CHANGE_EVENT:
6062 event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT;
6064 case SCTP_SEND_FAILED_EVENT:
6065 event_type = SCTP_PCB_FLAGS_RECVNSENDFAILEVNT;
6069 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6073 if (event_type > 0) {
6076 sctp_stcb_feature_on(inp, stcb, event_type);
6077 if (event_type == SCTP_PCB_FLAGS_DRYEVNT) {
6078 if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
6079 TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
6080 (stcb->asoc.stream_queue_cnt == 0)) {
6081 sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_LOCKED);
6085 sctp_stcb_feature_off(inp, stcb, event_type);
6087 SCTP_TCB_UNLOCK(stcb);
6090 * We don't want to send up a storm
6091 * of events, so return an error for
6094 if ((event_type == SCTP_PCB_FLAGS_DRYEVNT) &&
6095 ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) == 0) &&
6096 ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
6097 ((event->se_assoc_id == SCTP_ALL_ASSOC) ||
6098 (event->se_assoc_id == SCTP_CURRENT_ASSOC))) {
6099 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
6103 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6104 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6105 (event->se_assoc_id == SCTP_FUTURE_ASSOC) ||
6106 (event->se_assoc_id == SCTP_ALL_ASSOC)) {
6107 SCTP_INP_WLOCK(inp);
6109 sctp_feature_on(inp, event_type);
6111 sctp_feature_off(inp, event_type);
6113 SCTP_INP_WUNLOCK(inp);
6115 if ((event->se_assoc_id == SCTP_CURRENT_ASSOC) ||
6116 (event->se_assoc_id == SCTP_ALL_ASSOC)) {
6117 SCTP_INP_RLOCK(inp);
6118 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
6119 SCTP_TCB_LOCK(stcb);
6121 sctp_stcb_feature_on(inp, stcb, event_type);
6123 sctp_stcb_feature_off(inp, stcb, event_type);
6125 SCTP_TCB_UNLOCK(stcb);
6127 SCTP_INP_RUNLOCK(inp);
6133 case SCTP_RECVRCVINFO:
6137 SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
6138 SCTP_INP_WLOCK(inp);
6140 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
6142 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
6144 SCTP_INP_WUNLOCK(inp);
6147 case SCTP_RECVNXTINFO:
6151 SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
6152 SCTP_INP_WLOCK(inp);
6154 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
6156 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
6158 SCTP_INP_WUNLOCK(inp);
6161 case SCTP_DEFAULT_SNDINFO:
6163 struct sctp_sndinfo *info;
6166 SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, optsize);
6167 SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
6170 if (info->snd_sid < stcb->asoc.streamoutcnt) {
6171 stcb->asoc.def_send.sinfo_stream = info->snd_sid;
6172 policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
6173 stcb->asoc.def_send.sinfo_flags = info->snd_flags;
6174 stcb->asoc.def_send.sinfo_flags |= policy;
6175 stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
6176 stcb->asoc.def_send.sinfo_context = info->snd_context;
6178 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6181 SCTP_TCB_UNLOCK(stcb);
6183 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6184 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6185 (info->snd_assoc_id == SCTP_FUTURE_ASSOC) ||
6186 (info->snd_assoc_id == SCTP_ALL_ASSOC)) {
6187 SCTP_INP_WLOCK(inp);
6188 inp->def_send.sinfo_stream = info->snd_sid;
6189 policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
6190 inp->def_send.sinfo_flags = info->snd_flags;
6191 inp->def_send.sinfo_flags |= policy;
6192 inp->def_send.sinfo_ppid = info->snd_ppid;
6193 inp->def_send.sinfo_context = info->snd_context;
6194 SCTP_INP_WUNLOCK(inp);
6196 if ((info->snd_assoc_id == SCTP_CURRENT_ASSOC) ||
6197 (info->snd_assoc_id == SCTP_ALL_ASSOC)) {
6198 SCTP_INP_RLOCK(inp);
6199 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
6200 SCTP_TCB_LOCK(stcb);
6201 if (info->snd_sid < stcb->asoc.streamoutcnt) {
6202 stcb->asoc.def_send.sinfo_stream = info->snd_sid;
6203 policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
6204 stcb->asoc.def_send.sinfo_flags = info->snd_flags;
6205 stcb->asoc.def_send.sinfo_flags |= policy;
6206 stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
6207 stcb->asoc.def_send.sinfo_context = info->snd_context;
6209 SCTP_TCB_UNLOCK(stcb);
6211 SCTP_INP_RUNLOCK(inp);
6216 case SCTP_DEFAULT_PRINFO:
6218 struct sctp_default_prinfo *info;
6220 SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, optsize);
6221 SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
6223 if (info->pr_policy > SCTP_PR_SCTP_MAX) {
6224 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6229 stcb->asoc.def_send.sinfo_flags &= 0xfff0;
6230 stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
6231 stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
6232 SCTP_TCB_UNLOCK(stcb);
6234 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6235 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6236 (info->pr_assoc_id == SCTP_FUTURE_ASSOC) ||
6237 (info->pr_assoc_id == SCTP_ALL_ASSOC)) {
6238 SCTP_INP_WLOCK(inp);
6239 inp->def_send.sinfo_flags &= 0xfff0;
6240 inp->def_send.sinfo_flags |= info->pr_policy;
6241 inp->def_send.sinfo_timetolive = info->pr_value;
6242 SCTP_INP_WUNLOCK(inp);
6244 if ((info->pr_assoc_id == SCTP_CURRENT_ASSOC) ||
6245 (info->pr_assoc_id == SCTP_ALL_ASSOC)) {
6246 SCTP_INP_RLOCK(inp);
6247 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
6248 SCTP_TCB_LOCK(stcb);
6249 stcb->asoc.def_send.sinfo_flags &= 0xfff0;
6250 stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
6251 stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
6252 SCTP_TCB_UNLOCK(stcb);
6254 SCTP_INP_RUNLOCK(inp);
6259 case SCTP_PEER_ADDR_THLDS:
6260 /* Applies to the specific association */
6262 struct sctp_paddrthlds *thlds;
6263 struct sctp_nets *net;
6264 struct sockaddr *addr;
6266 #if defined(INET) && defined(INET6)
6267 struct sockaddr_in sin_store;
6271 SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, optsize);
6272 SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
6274 #if defined(INET) && defined(INET6)
6275 if (thlds->spt_address.ss_family == AF_INET6) {
6276 struct sockaddr_in6 *sin6;
6278 sin6 = (struct sockaddr_in6 *)&thlds->spt_address;
6279 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
6280 in6_sin6_2_sin(&sin_store, sin6);
6281 addr = (struct sockaddr *)&sin_store;
6283 addr = (struct sockaddr *)&thlds->spt_address;
6286 addr = (struct sockaddr *)&thlds->spt_address;
6289 addr = (struct sockaddr *)&thlds->spt_address;
6292 net = sctp_findnet(stcb, addr);
6295 * We increment here since
6296 * sctp_findassociation_ep_addr() wil do a
6297 * decrement if it finds the stcb as long as
6298 * the locked tcb (last argument) is NOT a
6302 SCTP_INP_INCR_REF(inp);
6303 stcb = sctp_findassociation_ep_addr(&inp, addr,
6306 SCTP_INP_DECR_REF(inp);
6309 if ((stcb != NULL) && (net == NULL)) {
6311 if (addr->sa_family == AF_INET) {
6313 struct sockaddr_in *sin;
6315 sin = (struct sockaddr_in *)addr;
6316 if (sin->sin_addr.s_addr != INADDR_ANY) {
6317 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6318 SCTP_TCB_UNLOCK(stcb);
6325 if (addr->sa_family == AF_INET6) {
6326 struct sockaddr_in6 *sin6;
6328 sin6 = (struct sockaddr_in6 *)addr;
6329 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
6330 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6331 SCTP_TCB_UNLOCK(stcb);
6338 error = EAFNOSUPPORT;
6339 SCTP_TCB_UNLOCK(stcb);
6340 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6346 net->failure_threshold = thlds->spt_pathmaxrxt;
6347 net->pf_threshold = thlds->spt_pathpfthld;
6348 if (net->dest_state & SCTP_ADDR_PF) {
6349 if ((net->error_count > net->failure_threshold) ||
6350 (net->error_count <= net->pf_threshold)) {
6351 net->dest_state &= ~SCTP_ADDR_PF;
6354 if ((net->error_count > net->pf_threshold) &&
6355 (net->error_count <= net->failure_threshold)) {
6356 net->dest_state |= SCTP_ADDR_PF;
6357 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
6358 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT,
6359 stcb->sctp_ep, stcb, net,
6360 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_17);
6361 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
6364 if (net->dest_state & SCTP_ADDR_REACHABLE) {
6365 if (net->error_count > net->failure_threshold) {
6366 net->dest_state &= ~SCTP_ADDR_REACHABLE;
6367 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
6370 if (net->error_count <= net->failure_threshold) {
6371 net->dest_state |= SCTP_ADDR_REACHABLE;
6372 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
6376 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6377 net->failure_threshold = thlds->spt_pathmaxrxt;
6378 net->pf_threshold = thlds->spt_pathpfthld;
6379 if (net->dest_state & SCTP_ADDR_PF) {
6380 if ((net->error_count > net->failure_threshold) ||
6381 (net->error_count <= net->pf_threshold)) {
6382 net->dest_state &= ~SCTP_ADDR_PF;
6385 if ((net->error_count > net->pf_threshold) &&
6386 (net->error_count <= net->failure_threshold)) {
6387 net->dest_state |= SCTP_ADDR_PF;
6388 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
6389 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT,
6390 stcb->sctp_ep, stcb, net,
6391 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_18);
6392 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
6395 if (net->dest_state & SCTP_ADDR_REACHABLE) {
6396 if (net->error_count > net->failure_threshold) {
6397 net->dest_state &= ~SCTP_ADDR_REACHABLE;
6398 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
6401 if (net->error_count <= net->failure_threshold) {
6402 net->dest_state |= SCTP_ADDR_REACHABLE;
6403 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
6407 stcb->asoc.def_net_failure = thlds->spt_pathmaxrxt;
6408 stcb->asoc.def_net_pf_threshold = thlds->spt_pathpfthld;
6410 SCTP_TCB_UNLOCK(stcb);
6412 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6413 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6414 (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC)) {
6415 SCTP_INP_WLOCK(inp);
6416 inp->sctp_ep.def_net_failure = thlds->spt_pathmaxrxt;
6417 inp->sctp_ep.def_net_pf_threshold = thlds->spt_pathpfthld;
6418 SCTP_INP_WUNLOCK(inp);
6420 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6426 case SCTP_REMOTE_UDP_ENCAPS_PORT:
6428 struct sctp_udpencaps *encaps;
6429 struct sctp_nets *net;
6430 struct sockaddr *addr;
6432 #if defined(INET) && defined(INET6)
6433 struct sockaddr_in sin_store;
6437 SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, optsize);
6438 SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
6440 #if defined(INET) && defined(INET6)
6441 if (encaps->sue_address.ss_family == AF_INET6) {
6442 struct sockaddr_in6 *sin6;
6444 sin6 = (struct sockaddr_in6 *)&encaps->sue_address;
6445 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
6446 in6_sin6_2_sin(&sin_store, sin6);
6447 addr = (struct sockaddr *)&sin_store;
6449 addr = (struct sockaddr *)&encaps->sue_address;
6452 addr = (struct sockaddr *)&encaps->sue_address;
6455 addr = (struct sockaddr *)&encaps->sue_address;
6458 net = sctp_findnet(stcb, addr);
6461 * We increment here since
6462 * sctp_findassociation_ep_addr() wil do a
6463 * decrement if it finds the stcb as long as
6464 * the locked tcb (last argument) is NOT a
6468 SCTP_INP_INCR_REF(inp);
6469 stcb = sctp_findassociation_ep_addr(&inp, addr, &net, NULL, NULL);
6471 SCTP_INP_DECR_REF(inp);
6474 if ((stcb != NULL) && (net == NULL)) {
6476 if (addr->sa_family == AF_INET) {
6478 struct sockaddr_in *sin;
6480 sin = (struct sockaddr_in *)addr;
6481 if (sin->sin_addr.s_addr != INADDR_ANY) {
6482 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6483 SCTP_TCB_UNLOCK(stcb);
6490 if (addr->sa_family == AF_INET6) {
6491 struct sockaddr_in6 *sin6;
6493 sin6 = (struct sockaddr_in6 *)addr;
6494 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
6495 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6496 SCTP_TCB_UNLOCK(stcb);
6503 error = EAFNOSUPPORT;
6504 SCTP_TCB_UNLOCK(stcb);
6505 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6511 net->port = encaps->sue_port;
6513 stcb->asoc.port = encaps->sue_port;
6515 SCTP_TCB_UNLOCK(stcb);
6517 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6518 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6519 (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC)) {
6520 SCTP_INP_WLOCK(inp);
6521 inp->sctp_ep.port = encaps->sue_port;
6522 SCTP_INP_WUNLOCK(inp);
6524 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6530 case SCTP_ECN_SUPPORTED:
6532 struct sctp_assoc_value *av;
6534 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6535 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6538 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6540 SCTP_TCB_UNLOCK(stcb);
6542 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6543 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6544 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
6545 SCTP_INP_WLOCK(inp);
6546 if (av->assoc_value == 0) {
6547 inp->ecn_supported = 0;
6549 inp->ecn_supported = 1;
6551 SCTP_INP_WUNLOCK(inp);
6553 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6559 case SCTP_PR_SUPPORTED:
6561 struct sctp_assoc_value *av;
6563 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6564 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6567 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6569 SCTP_TCB_UNLOCK(stcb);
6571 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6572 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6573 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
6574 SCTP_INP_WLOCK(inp);
6575 if (av->assoc_value == 0) {
6576 inp->prsctp_supported = 0;
6578 inp->prsctp_supported = 1;
6580 SCTP_INP_WUNLOCK(inp);
6582 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6588 case SCTP_AUTH_SUPPORTED:
6590 struct sctp_assoc_value *av;
6592 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6593 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6596 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6598 SCTP_TCB_UNLOCK(stcb);
6600 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6601 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6602 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
6603 if ((av->assoc_value == 0) &&
6604 (inp->asconf_supported == 1)) {
6606 * AUTH is required for
6609 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6612 SCTP_INP_WLOCK(inp);
6613 if (av->assoc_value == 0) {
6614 inp->auth_supported = 0;
6616 inp->auth_supported = 1;
6618 SCTP_INP_WUNLOCK(inp);
6621 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6627 case SCTP_ASCONF_SUPPORTED:
6629 struct sctp_assoc_value *av;
6631 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6632 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6635 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6637 SCTP_TCB_UNLOCK(stcb);
6639 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6640 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6641 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
6642 if ((av->assoc_value != 0) &&
6643 (inp->auth_supported == 0)) {
6645 * AUTH is required for
6648 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6651 SCTP_INP_WLOCK(inp);
6652 if (av->assoc_value == 0) {
6653 inp->asconf_supported = 0;
6654 sctp_auth_delete_chunk(SCTP_ASCONF,
6655 inp->sctp_ep.local_auth_chunks);
6656 sctp_auth_delete_chunk(SCTP_ASCONF_ACK,
6657 inp->sctp_ep.local_auth_chunks);
6659 inp->asconf_supported = 1;
6660 sctp_auth_add_chunk(SCTP_ASCONF,
6661 inp->sctp_ep.local_auth_chunks);
6662 sctp_auth_add_chunk(SCTP_ASCONF_ACK,
6663 inp->sctp_ep.local_auth_chunks);
6665 SCTP_INP_WUNLOCK(inp);
6668 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6674 case SCTP_RECONFIG_SUPPORTED:
6676 struct sctp_assoc_value *av;
6678 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6679 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6682 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6684 SCTP_TCB_UNLOCK(stcb);
6686 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6687 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6688 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
6689 SCTP_INP_WLOCK(inp);
6690 if (av->assoc_value == 0) {
6691 inp->reconfig_supported = 0;
6693 inp->reconfig_supported = 1;
6695 SCTP_INP_WUNLOCK(inp);
6697 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6703 case SCTP_NRSACK_SUPPORTED:
6705 struct sctp_assoc_value *av;
6707 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6708 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6711 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6713 SCTP_TCB_UNLOCK(stcb);
6715 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6716 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6717 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
6718 SCTP_INP_WLOCK(inp);
6719 if (av->assoc_value == 0) {
6720 inp->nrsack_supported = 0;
6722 inp->nrsack_supported = 1;
6724 SCTP_INP_WUNLOCK(inp);
6726 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6732 case SCTP_PKTDROP_SUPPORTED:
6734 struct sctp_assoc_value *av;
6736 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6737 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6740 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6742 SCTP_TCB_UNLOCK(stcb);
6744 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6745 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6746 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
6747 SCTP_INP_WLOCK(inp);
6748 if (av->assoc_value == 0) {
6749 inp->pktdrop_supported = 0;
6751 inp->pktdrop_supported = 1;
6753 SCTP_INP_WUNLOCK(inp);
6755 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6763 struct sctp_assoc_value *av;
6764 struct sctp_nets *net;
6766 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6767 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6770 stcb->asoc.max_cwnd = av->assoc_value;
6771 if (stcb->asoc.max_cwnd > 0) {
6772 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6773 if ((net->cwnd > stcb->asoc.max_cwnd) &&
6774 (net->cwnd > (net->mtu - sizeof(struct sctphdr)))) {
6775 net->cwnd = stcb->asoc.max_cwnd;
6776 if (net->cwnd < (net->mtu - sizeof(struct sctphdr))) {
6777 net->cwnd = net->mtu - sizeof(struct sctphdr);
6782 SCTP_TCB_UNLOCK(stcb);
6784 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6785 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6786 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
6787 SCTP_INP_WLOCK(inp);
6788 inp->max_cwnd = av->assoc_value;
6789 SCTP_INP_WUNLOCK(inp);
6791 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6798 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
6799 error = ENOPROTOOPT;
6801 } /* end switch (opt) */
6806 sctp_ctloutput(struct socket *so, struct sockopt *sopt)
6808 void *optval = NULL;
6812 struct sctp_inpcb *inp;
6814 if ((sopt->sopt_level == SOL_SOCKET) &&
6815 (sopt->sopt_name == SO_SETFIB)) {
6816 inp = (struct sctp_inpcb *)so->so_pcb;
6818 SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS);
6821 SCTP_INP_WLOCK(inp);
6822 inp->fibnum = so->so_fibnum;
6823 SCTP_INP_WUNLOCK(inp);
6826 if (sopt->sopt_level != IPPROTO_SCTP) {
6827 /* wrong proto level... send back up to IP */
6829 if (INP_CHECK_SOCKAF(so, AF_INET6))
6830 error = ip6_ctloutput(so, sopt);
6832 #if defined(INET) && defined(INET6)
6836 error = ip_ctloutput(so, sopt);
6840 optsize = sopt->sopt_valsize;
6842 SCTP_MALLOC(optval, void *, optsize, SCTP_M_SOCKOPT);
6843 if (optval == NULL) {
6844 SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS);
6847 error = sooptcopyin(sopt, optval, optsize, optsize);
6849 SCTP_FREE(optval, SCTP_M_SOCKOPT);
6853 p = (void *)sopt->sopt_td;
6854 if (sopt->sopt_dir == SOPT_SET) {
6855 error = sctp_setopt(so, sopt->sopt_name, optval, optsize, p);
6856 } else if (sopt->sopt_dir == SOPT_GET) {
6857 error = sctp_getopt(so, sopt->sopt_name, optval, &optsize, p);
6859 SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6862 if ((error == 0) && (optval != NULL)) {
6863 error = sooptcopyout(sopt, optval, optsize);
6864 SCTP_FREE(optval, SCTP_M_SOCKOPT);
6865 } else if (optval != NULL) {
6866 SCTP_FREE(optval, SCTP_M_SOCKOPT);
6874 sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
6877 int create_lock_on = 0;
6879 struct sctp_inpcb *inp;
6880 struct sctp_tcb *stcb = NULL;
6882 inp = (struct sctp_inpcb *)so->so_pcb;
6884 /* I made the same as TCP since we are not setup? */
6885 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6886 return (ECONNRESET);
6889 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6892 switch (addr->sa_family) {
6896 struct sockaddr_in6 *sin6p;
6898 if (addr->sa_len != sizeof(struct sockaddr_in6)) {
6899 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6902 sin6p = (struct sockaddr_in6 *)addr;
6903 if (p != NULL && (error = prison_remote_ip6(p->td_ucred, &sin6p->sin6_addr)) != 0) {
6904 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6913 struct sockaddr_in *sinp;
6915 if (addr->sa_len != sizeof(struct sockaddr_in)) {
6916 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6919 sinp = (struct sockaddr_in *)addr;
6920 if (p != NULL && (error = prison_remote_ip4(p->td_ucred, &sinp->sin_addr)) != 0) {
6921 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6928 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
6929 return (EAFNOSUPPORT);
6931 SCTP_INP_INCR_REF(inp);
6932 SCTP_ASOC_CREATE_LOCK(inp);
6936 if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
6937 (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
6938 /* Should I really unlock ? */
6939 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
6944 if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
6945 (addr->sa_family == AF_INET6)) {
6946 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6951 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
6952 SCTP_PCB_FLAGS_UNBOUND) {
6953 /* Bind a ephemeral port */
6954 error = sctp_inpcb_bind(so, NULL, NULL, p);
6959 /* Now do we connect? */
6960 if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
6961 (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
6962 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6966 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
6967 (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
6968 /* We are already connected AND the TCP model */
6969 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
6973 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
6974 SCTP_INP_RLOCK(inp);
6975 stcb = LIST_FIRST(&inp->sctp_asoc_list);
6976 SCTP_INP_RUNLOCK(inp);
6979 * We increment here since sctp_findassociation_ep_addr()
6980 * will do a decrement if it finds the stcb as long as the
6981 * locked tcb (last argument) is NOT a TCB.. aka NULL.
6983 SCTP_INP_INCR_REF(inp);
6984 stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
6986 SCTP_INP_DECR_REF(inp);
6988 SCTP_TCB_UNLOCK(stcb);
6992 /* Already have or am bring up an association */
6993 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
6997 vrf_id = inp->def_vrf_id;
6998 /* We are GOOD to go */
6999 stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, inp->sctp_ep.pre_open_stream_count, p);
7001 /* Gak! no memory */
7004 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
7005 stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
7006 /* Set the connected flag so we can queue data */
7009 SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
7010 (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
7012 /* initialize authentication parameters for the assoc */
7013 sctp_initialize_auth_params(inp, stcb);
7015 sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
7016 SCTP_TCB_UNLOCK(stcb);
7018 if (create_lock_on) {
7019 SCTP_ASOC_CREATE_UNLOCK(inp);
7021 SCTP_INP_DECR_REF(inp);
7028 sctp_listen(struct socket *so, int backlog, struct thread *p)
7031 * Note this module depends on the protocol processing being called
7032 * AFTER any socket level flags and backlog are applied to the
7033 * socket. The traditional way that the socket flags are applied is
7034 * AFTER protocol processing. We have made a change to the
7035 * sys/kern/uipc_socket.c module to reverse this but this MUST be in
7036 * place if the socket API for SCTP is to work properly.
7040 struct sctp_inpcb *inp;
7042 inp = (struct sctp_inpcb *)so->so_pcb;
7044 /* I made the same as TCP since we are not setup? */
7045 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7046 return (ECONNRESET);
7048 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) {
7049 /* See if we have a listener */
7050 struct sctp_inpcb *tinp;
7051 union sctp_sockstore store;
7053 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
7055 struct sctp_laddr *laddr;
7057 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
7058 memcpy(&store, &laddr->ifa->address, sizeof(store));
7059 switch (store.sa.sa_family) {
7062 store.sin.sin_port = inp->sctp_lport;
7067 store.sin6.sin6_port = inp->sctp_lport;
7073 tinp = sctp_pcb_findep(&store.sa, 0, 0, inp->def_vrf_id);
7074 if (tinp && (tinp != inp) &&
7075 ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
7076 ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
7077 (tinp->sctp_socket->so_qlimit)) {
7079 * we have a listener already and
7082 SCTP_INP_DECR_REF(tinp);
7083 return (EADDRINUSE);
7085 SCTP_INP_DECR_REF(tinp);
7089 /* Setup a local addr bound all */
7090 memset(&store, 0, sizeof(store));
7092 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
7093 store.sa.sa_family = AF_INET6;
7094 store.sa.sa_len = sizeof(struct sockaddr_in6);
7098 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
7099 store.sa.sa_family = AF_INET;
7100 store.sa.sa_len = sizeof(struct sockaddr_in);
7103 switch (store.sa.sa_family) {
7106 store.sin.sin_port = inp->sctp_lport;
7111 store.sin6.sin6_port = inp->sctp_lport;
7117 tinp = sctp_pcb_findep(&store.sa, 0, 0, inp->def_vrf_id);
7118 if (tinp && (tinp != inp) &&
7119 ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
7120 ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
7121 (tinp->sctp_socket->so_qlimit)) {
7123 * we have a listener already and its not
7126 SCTP_INP_DECR_REF(tinp);
7127 return (EADDRINUSE);
7129 SCTP_INP_DECR_REF(tinp);
7133 SCTP_INP_RLOCK(inp);
7134 #ifdef SCTP_LOCK_LOGGING
7135 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) {
7136 sctp_log_lock(inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_SOCK);
7140 error = solisten_proto_check(so);
7143 SCTP_INP_RUNLOCK(inp);
7146 if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) &&
7147 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
7149 * The unlucky case - We are in the tcp pool with this guy.
7150 * - Someone else is in the main inp slot. - We must move
7151 * this guy (the listener) to the main slot - We must then
7152 * move the guy that was listener to the TCP Pool.
7154 if (sctp_swap_inpcb_for_listen(inp)) {
7155 SCTP_INP_RUNLOCK(inp);
7156 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
7157 return (EADDRINUSE);
7160 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
7161 (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
7162 /* We are already connected AND the TCP model */
7163 SCTP_INP_RUNLOCK(inp);
7164 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
7165 return (EADDRINUSE);
7167 SCTP_INP_RUNLOCK(inp);
7168 if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
7169 /* We must do a bind. */
7170 if ((error = sctp_inpcb_bind(so, NULL, NULL, p))) {
7171 /* bind error, probably perm */
7176 /* It appears for 7.0 and on, we must always call this. */
7177 solisten_proto(so, backlog);
7178 if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
7179 /* remove the ACCEPTCONN flag for one-to-many sockets */
7180 so->so_options &= ~SO_ACCEPTCONN;
7183 /* turning off listen */
7184 so->so_options &= ~SO_ACCEPTCONN;
7190 static int sctp_defered_wakeup_cnt = 0;
7193 sctp_accept(struct socket *so, struct sockaddr **addr)
7195 struct sctp_tcb *stcb;
7196 struct sctp_inpcb *inp;
7197 union sctp_sockstore store;
7203 inp = (struct sctp_inpcb *)so->so_pcb;
7206 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7207 return (ECONNRESET);
7209 SCTP_INP_RLOCK(inp);
7210 if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
7211 SCTP_INP_RUNLOCK(inp);
7212 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
7213 return (EOPNOTSUPP);
7215 if (so->so_state & SS_ISDISCONNECTED) {
7216 SCTP_INP_RUNLOCK(inp);
7217 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ECONNABORTED);
7218 return (ECONNABORTED);
7220 stcb = LIST_FIRST(&inp->sctp_asoc_list);
7222 SCTP_INP_RUNLOCK(inp);
7223 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7224 return (ECONNRESET);
7226 SCTP_TCB_LOCK(stcb);
7227 SCTP_INP_RUNLOCK(inp);
7228 store = stcb->asoc.primary_destination->ro._l_addr;
7229 stcb->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE;
7230 SCTP_TCB_UNLOCK(stcb);
7231 switch (store.sa.sa_family) {
7235 struct sockaddr_in *sin;
7237 SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
7240 sin->sin_family = AF_INET;
7241 sin->sin_len = sizeof(*sin);
7242 sin->sin_port = store.sin.sin_port;
7243 sin->sin_addr = store.sin.sin_addr;
7244 *addr = (struct sockaddr *)sin;
7251 struct sockaddr_in6 *sin6;
7253 SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
7256 sin6->sin6_family = AF_INET6;
7257 sin6->sin6_len = sizeof(*sin6);
7258 sin6->sin6_port = store.sin6.sin6_port;
7259 sin6->sin6_addr = store.sin6.sin6_addr;
7260 if ((error = sa6_recoverscope(sin6)) != 0) {
7261 SCTP_FREE_SONAME(sin6);
7264 *addr = (struct sockaddr *)sin6;
7272 /* Wake any delayed sleep action */
7273 if (inp->sctp_flags & SCTP_PCB_FLAGS_DONT_WAKE) {
7274 SCTP_INP_WLOCK(inp);
7275 inp->sctp_flags &= ~SCTP_PCB_FLAGS_DONT_WAKE;
7276 if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEOUTPUT) {
7277 inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEOUTPUT;
7278 SCTP_INP_WUNLOCK(inp);
7279 SOCKBUF_LOCK(&inp->sctp_socket->so_snd);
7280 if (sowriteable(inp->sctp_socket)) {
7281 sowwakeup_locked(inp->sctp_socket);
7283 SOCKBUF_UNLOCK(&inp->sctp_socket->so_snd);
7285 SCTP_INP_WLOCK(inp);
7287 if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEINPUT) {
7288 inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEINPUT;
7289 SCTP_INP_WUNLOCK(inp);
7290 SOCKBUF_LOCK(&inp->sctp_socket->so_rcv);
7291 if (soreadable(inp->sctp_socket)) {
7292 sctp_defered_wakeup_cnt++;
7293 sorwakeup_locked(inp->sctp_socket);
7295 SOCKBUF_UNLOCK(&inp->sctp_socket->so_rcv);
7297 SCTP_INP_WLOCK(inp);
7299 SCTP_INP_WUNLOCK(inp);
7301 if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
7302 SCTP_TCB_LOCK(stcb);
7303 sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
7304 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_19);
7311 sctp_ingetaddr(struct socket *so, struct sockaddr **addr)
7313 struct sockaddr_in *sin;
7315 struct sctp_inpcb *inp;
7316 struct sctp_ifa *sctp_ifa;
7319 * Do the malloc first in case it blocks.
7321 SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
7324 sin->sin_family = AF_INET;
7325 sin->sin_len = sizeof(*sin);
7326 inp = (struct sctp_inpcb *)so->so_pcb;
7328 SCTP_FREE_SONAME(sin);
7329 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7330 return (ECONNRESET);
7332 SCTP_INP_RLOCK(inp);
7333 sin->sin_port = inp->sctp_lport;
7334 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
7335 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
7336 struct sctp_tcb *stcb;
7337 struct sockaddr_in *sin_a;
7338 struct sctp_nets *net;
7341 stcb = LIST_FIRST(&inp->sctp_asoc_list);
7347 SCTP_TCB_LOCK(stcb);
7348 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
7349 sin_a = (struct sockaddr_in *)&net->ro._l_addr;
7351 /* this will make coverity happy */
7354 if (sin_a->sin_family == AF_INET) {
7359 if ((!fnd) || (sin_a == NULL)) {
7361 SCTP_TCB_UNLOCK(stcb);
7364 vrf_id = inp->def_vrf_id;
7365 sctp_ifa = sctp_source_address_selection(inp,
7367 (sctp_route_t *) & net->ro,
7370 sin->sin_addr = sctp_ifa->address.sin.sin_addr;
7371 sctp_free_ifa(sctp_ifa);
7373 SCTP_TCB_UNLOCK(stcb);
7375 /* For the bound all case you get back 0 */
7377 sin->sin_addr.s_addr = 0;
7381 /* Take the first IPv4 address in the list */
7382 struct sctp_laddr *laddr;
7385 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
7386 if (laddr->ifa->address.sa.sa_family == AF_INET) {
7387 struct sockaddr_in *sin_a;
7389 sin_a = &laddr->ifa->address.sin;
7390 sin->sin_addr = sin_a->sin_addr;
7396 SCTP_FREE_SONAME(sin);
7397 SCTP_INP_RUNLOCK(inp);
7398 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
7402 SCTP_INP_RUNLOCK(inp);
7403 (*addr) = (struct sockaddr *)sin;
7408 sctp_peeraddr(struct socket *so, struct sockaddr **addr)
7410 struct sockaddr_in *sin;
7412 struct sockaddr_in *sin_a;
7413 struct sctp_inpcb *inp;
7414 struct sctp_tcb *stcb;
7415 struct sctp_nets *net;
7417 /* Do the malloc first in case it blocks. */
7418 SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
7421 sin->sin_family = AF_INET;
7422 sin->sin_len = sizeof(*sin);
7424 inp = (struct sctp_inpcb *)so->so_pcb;
7425 if ((inp == NULL) ||
7426 ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
7427 /* UDP type and listeners will drop out here */
7428 SCTP_FREE_SONAME(sin);
7429 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
7432 SCTP_INP_RLOCK(inp);
7433 stcb = LIST_FIRST(&inp->sctp_asoc_list);
7435 SCTP_TCB_LOCK(stcb);
7437 SCTP_INP_RUNLOCK(inp);
7439 SCTP_FREE_SONAME(sin);
7440 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7441 return (ECONNRESET);
7444 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
7445 sin_a = (struct sockaddr_in *)&net->ro._l_addr;
7446 if (sin_a->sin_family == AF_INET) {
7448 sin->sin_port = stcb->rport;
7449 sin->sin_addr = sin_a->sin_addr;
7453 SCTP_TCB_UNLOCK(stcb);
7455 /* No IPv4 address */
7456 SCTP_FREE_SONAME(sin);
7457 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
7460 (*addr) = (struct sockaddr *)sin;
7464 struct pr_usrreqs sctp_usrreqs = {
7465 .pru_abort = sctp_abort,
7466 .pru_accept = sctp_accept,
7467 .pru_attach = sctp_attach,
7468 .pru_bind = sctp_bind,
7469 .pru_connect = sctp_connect,
7470 .pru_control = in_control,
7471 .pru_close = sctp_close,
7472 .pru_detach = sctp_close,
7473 .pru_sopoll = sopoll_generic,
7474 .pru_flush = sctp_flush,
7475 .pru_disconnect = sctp_disconnect,
7476 .pru_listen = sctp_listen,
7477 .pru_peeraddr = sctp_peeraddr,
7478 .pru_send = sctp_sendm,
7479 .pru_shutdown = sctp_shutdown,
7480 .pru_sockaddr = sctp_ingetaddr,
7481 .pru_sosend = sctp_sosend,
7482 .pru_soreceive = sctp_soreceive