2 * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
7 * a) Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
10 * b) Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the distribution.
14 * c) Neither the name of Cisco Systems, Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28 * THE POSSIBILITY OF SUCH DAMAGE.
31 /* $KAME: sctp_usrreq.c,v 1.48 2005/03/07 23:26:08 itojun Exp $ */
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35 #include <netinet/sctp_os.h>
37 #include <netinet/sctp_pcb.h>
38 #include <netinet/sctp_header.h>
39 #include <netinet/sctp_var.h>
42 #include <netinet/sctp_sysctl.h>
43 #include <netinet/sctp_output.h>
44 #include <netinet/sctp_uio.h>
45 #include <netinet/sctp_asconf.h>
46 #include <netinet/sctputil.h>
47 #include <netinet/sctp_indata.h>
48 #include <netinet/sctp_timer.h>
49 #include <netinet/sctp_auth.h>
50 #include <netinet/sctp_bsd_addr.h>
51 #include <netinet/sctp_cc_functions.h>
61 bzero(&SCTP_BASE_STATS
, sizeof(struct sctpstat
));
63 /* Initialize and modify the sysctled variables */
65 if ((nmbclusters
/ 8) > SCTP_ASOC_MAX_CHUNKS_ON_QUEUE
)
66 SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue
) = (nmbclusters
/ 8);
68 * Allow a user to take no more than 1/2 the number of clusters or
69 * the SB_MAX whichever is smaller for the send window.
71 sb_max_adj
= (u_long
)((u_quad_t
) (SB_MAX
) * MCLBYTES
/ (MSIZE
+ MCLBYTES
));
72 SCTP_BASE_SYSCTL(sctp_sendspace
) = min(sb_max_adj
,
73 (((uint32_t) nmbclusters
/ 2) * SCTP_DEFAULT_MAXSEGMENT
));
75 * Now for the recv window, should we take the same amount? or
76 * should I do 1/2 the SB_MAX instead in the SB_MAX min above. For
77 * now I will just copy.
79 SCTP_BASE_SYSCTL(sctp_recvspace
) = SCTP_BASE_SYSCTL(sctp_sendspace
);
81 SCTP_BASE_VAR(first_time
) = 0;
82 SCTP_BASE_VAR(sctp_pcb_initialized
) = 0;
84 #if defined(SCTP_PACKET_LOGGING)
85 SCTP_BASE_VAR(packet_log_writers
) = 0;
86 SCTP_BASE_VAR(packet_log_end
) = 0;
87 bzero(&SCTP_BASE_VAR(packet_log_buffer
), SCTP_PACKET_LOG_SIZE
);
102 sctp_pathmtu_adjustment(struct sctp_inpcb
*inp
,
103 struct sctp_tcb
*stcb
,
104 struct sctp_nets
*net
,
107 struct sctp_tmit_chunk
*chk
;
109 /* Adjust that too */
110 stcb
->asoc
.smallest_mtu
= nxtsz
;
111 /* now off to subtract IP_DF flag if needed */
112 #ifdef SCTP_PRINT_FOR_B_AND_M
113 SCTP_PRINTF("sctp_pathmtu_adjust called inp:%p stcb:%p net:%p nxtsz:%d\n",
114 inp
, stcb
, net
, nxtsz
);
116 TAILQ_FOREACH(chk
, &stcb
->asoc
.send_queue
, sctp_next
) {
117 if ((chk
->send_size
+ IP_HDR_SIZE
) > nxtsz
) {
118 chk
->flags
|= CHUNK_FLAGS_FRAGMENT_OK
;
121 TAILQ_FOREACH(chk
, &stcb
->asoc
.sent_queue
, sctp_next
) {
122 if ((chk
->send_size
+ IP_HDR_SIZE
) > nxtsz
) {
124 * For this guy we also mark for immediate resend
125 * since we sent to big of chunk
127 chk
->flags
|= CHUNK_FLAGS_FRAGMENT_OK
;
128 if (chk
->sent
!= SCTP_DATAGRAM_RESEND
) {
129 sctp_ucount_incr(stcb
->asoc
.sent_queue_retran_cnt
);
131 chk
->sent
= SCTP_DATAGRAM_RESEND
;
132 chk
->rec
.data
.doing_fast_retransmit
= 0;
133 if (SCTP_BASE_SYSCTL(sctp_logging_level
) & SCTP_FLIGHT_LOGGING_ENABLE
) {
134 sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_PMTU
,
135 chk
->whoTo
->flight_size
,
137 (uintptr_t) chk
->whoTo
,
138 chk
->rec
.data
.TSN_seq
);
140 /* Clear any time so NO RTT is being done */
142 sctp_flight_size_decrease(chk
);
143 sctp_total_flight_decrease(stcb
, chk
);
149 sctp_notify_mbuf(struct sctp_inpcb
*inp
,
150 struct sctp_tcb
*stcb
,
151 struct sctp_nets
*net
,
156 int totsz
, tmr_stopped
= 0;
160 if ((inp
== NULL
) || (stcb
== NULL
) || (net
== NULL
) ||
161 (ip
== NULL
) || (sh
== NULL
)) {
163 SCTP_TCB_UNLOCK(stcb
);
167 /* First job is to verify the vtag matches what I would send */
168 if (ntohl(sh
->v_tag
) != (stcb
->asoc
.peer_vtag
)) {
169 SCTP_TCB_UNLOCK(stcb
);
172 icmph
= (struct icmp
*)((caddr_t
)ip
- (sizeof(struct icmp
) -
174 if (icmph
->icmp_type
!= ICMP_UNREACH
) {
175 /* We only care about unreachable */
176 SCTP_TCB_UNLOCK(stcb
);
179 if (icmph
->icmp_code
!= ICMP_UNREACH_NEEDFRAG
) {
180 /* not a unreachable message due to frag. */
181 SCTP_TCB_UNLOCK(stcb
);
186 nxtsz
= ntohs(icmph
->icmp_nextmtu
);
189 * old type router that does not tell us what the next size
190 * mtu is. Rats we will have to guess (in a educated fashion
193 nxtsz
= find_next_best_mtu(totsz
);
195 /* Stop any PMTU timer */
196 if (SCTP_OS_TIMER_PENDING(&net
->pmtu_timer
.timer
)) {
198 sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE
, inp
, stcb
, net
,
199 SCTP_FROM_SCTP_USRREQ
+ SCTP_LOC_1
);
201 /* Adjust destination size limit */
202 if (net
->mtu
> nxtsz
) {
205 /* now what about the ep? */
206 if (stcb
->asoc
.smallest_mtu
> nxtsz
) {
207 #ifdef SCTP_PRINT_FOR_B_AND_M
208 SCTP_PRINTF("notify_mbuf (ICMP) calls sctp_pathmtu_adjust mtu:%d\n",
211 sctp_pathmtu_adjustment(inp
, stcb
, net
, nxtsz
);
214 sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE
, inp
, stcb
, net
);
216 SCTP_TCB_UNLOCK(stcb
);
221 sctp_notify(struct sctp_inpcb
*inp
,
225 struct sctp_tcb
*stcb
,
226 struct sctp_nets
*net
)
228 #if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
237 if ((inp
== NULL
) || (stcb
== NULL
) || (net
== NULL
) ||
238 (sh
== NULL
) || (to
== NULL
)) {
240 SCTP_TCB_UNLOCK(stcb
);
243 /* First job is to verify the vtag matches what I would send */
244 if (ntohl(sh
->v_tag
) != (stcb
->asoc
.peer_vtag
)) {
245 SCTP_TCB_UNLOCK(stcb
);
248 icmph
= (struct icmp
*)((caddr_t
)ip
- (sizeof(struct icmp
) -
250 if (icmph
->icmp_type
!= ICMP_UNREACH
) {
251 /* We only care about unreachable */
252 SCTP_TCB_UNLOCK(stcb
);
255 if ((icmph
->icmp_code
== ICMP_UNREACH_NET
) ||
256 (icmph
->icmp_code
== ICMP_UNREACH_HOST
) ||
257 (icmph
->icmp_code
== ICMP_UNREACH_NET_UNKNOWN
) ||
258 (icmph
->icmp_code
== ICMP_UNREACH_HOST_UNKNOWN
) ||
259 (icmph
->icmp_code
== ICMP_UNREACH_ISOLATED
) ||
260 (icmph
->icmp_code
== ICMP_UNREACH_NET_PROHIB
) ||
261 (icmph
->icmp_code
== ICMP_UNREACH_HOST_PROHIB
) ||
262 (icmph
->icmp_code
== ICMP_UNREACH_FILTER_PROHIB
)) {
265 * Hmm reachablity problems we must examine closely. If its
266 * not reachable, we may have lost a network. Or if there is
267 * NO protocol at the other end named SCTP. well we consider
270 if (net
->dest_state
& SCTP_ADDR_REACHABLE
) {
271 /* Ok that destination is NOT reachable */
272 SCTP_PRINTF("ICMP (thresh %d/%d) takes interface %p down\n",
274 net
->failure_threshold
,
277 net
->dest_state
&= ~SCTP_ADDR_REACHABLE
;
278 net
->dest_state
|= SCTP_ADDR_NOT_REACHABLE
;
280 * JRS 5/14/07 - If a destination is unreachable,
281 * the PF bit is turned off. This allows an
282 * unambiguous use of the PF bit for destinations
283 * that are reachable but potentially failed. If the
284 * destination is set to the unreachable state, also
285 * set the destination to the PF state.
288 * Add debug message here if destination is not in
291 /* Stop any running T3 timers here? */
292 if (SCTP_BASE_SYSCTL(sctp_cmt_on_off
) && SCTP_BASE_SYSCTL(sctp_cmt_pf
)) {
293 net
->dest_state
&= ~SCTP_ADDR_PF
;
294 SCTPDBG(SCTP_DEBUG_TIMER4
, "Destination %p moved from PF to unreachable.\n",
297 net
->error_count
= net
->failure_threshold
+ 1;
298 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN
,
299 stcb
, SCTP_FAILED_THRESHOLD
,
300 (void *)net
, SCTP_SO_NOT_LOCKED
);
302 SCTP_TCB_UNLOCK(stcb
);
303 } else if ((icmph
->icmp_code
== ICMP_UNREACH_PROTOCOL
) ||
304 (icmph
->icmp_code
== ICMP_UNREACH_PORT
)) {
306 * Here the peer is either playing tricks on us, including
307 * an address that belongs to someone who does not support
308 * SCTP OR was a userland implementation that shutdown and
309 * now is dead. In either case treat it like a OOTB abort
312 reason
= SCTP_PEER_FAULTY
;
313 sctp_abort_notification(stcb
, reason
, SCTP_SO_NOT_LOCKED
);
314 #if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
315 so
= SCTP_INP_SO(inp
);
316 atomic_add_int(&stcb
->asoc
.refcnt
, 1);
317 SCTP_TCB_UNLOCK(stcb
);
318 SCTP_SOCKET_LOCK(so
, 1);
320 atomic_subtract_int(&stcb
->asoc
.refcnt
, 1);
322 (void)sctp_free_assoc(inp
, stcb
, SCTP_NORMAL_PROC
, SCTP_FROM_SCTP_USRREQ
+ SCTP_LOC_2
);
323 #if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
324 SCTP_SOCKET_UNLOCK(so
, 1);
325 /* SCTP_TCB_UNLOCK(stcb); MT: I think this is not needed. */
327 /* no need to unlock here, since the TCB is gone */
329 SCTP_TCB_UNLOCK(stcb
);
334 sctp_ctlinput(cmd
, sa
, vip
)
343 /* FIX, for non-bsd is this right? */
344 vrf_id
= SCTP_DEFAULT_VRFID
;
345 if (sa
->sa_family
!= AF_INET
||
346 ((struct sockaddr_in
*)sa
)->sin_addr
.s_addr
== INADDR_ANY
) {
349 if (PRC_IS_REDIRECT(cmd
)) {
351 } else if ((unsigned)cmd
>= PRC_NCMDS
|| inetctlerrmap
[cmd
] == 0) {
355 struct sctp_inpcb
*inp
= NULL
;
356 struct sctp_tcb
*stcb
= NULL
;
357 struct sctp_nets
*net
= NULL
;
358 struct sockaddr_in to
, from
;
360 sh
= (struct sctphdr
*)((caddr_t
)ip
+ (ip
->ip_hl
<< 2));
361 bzero(&to
, sizeof(to
));
362 bzero(&from
, sizeof(from
));
363 from
.sin_family
= to
.sin_family
= AF_INET
;
364 from
.sin_len
= to
.sin_len
= sizeof(to
);
365 from
.sin_port
= sh
->src_port
;
366 from
.sin_addr
= ip
->ip_src
;
367 to
.sin_port
= sh
->dest_port
;
368 to
.sin_addr
= ip
->ip_dst
;
371 * 'to' holds the dest of the packet that failed to be sent.
372 * 'from' holds our local endpoint address. Thus we reverse
373 * the to and the from in the lookup.
375 stcb
= sctp_findassociation_addr_sa((struct sockaddr
*)&from
,
376 (struct sockaddr
*)&to
,
377 &inp
, &net
, 1, vrf_id
);
378 if (stcb
!= NULL
&& inp
&& (inp
->sctp_socket
!= NULL
)) {
379 if (cmd
!= PRC_MSGSIZE
) {
380 sctp_notify(inp
, ip
, sh
,
381 (struct sockaddr
*)&to
, stcb
,
384 /* handle possible ICMP size messages */
385 sctp_notify_mbuf(inp
, stcb
, net
, ip
, sh
);
388 if ((stcb
== NULL
) && (inp
!= NULL
)) {
389 /* reduce ref-count */
391 SCTP_INP_DECR_REF(inp
);
392 SCTP_INP_WUNLOCK(inp
);
400 sctp_getcred(SYSCTL_HANDLER_ARGS
)
403 struct sockaddr_in addrs
[2];
404 struct sctp_inpcb
*inp
;
405 struct sctp_nets
*net
;
406 struct sctp_tcb
*stcb
;
410 /* FIX, for non-bsd is this right? */
411 vrf_id
= SCTP_DEFAULT_VRFID
;
413 error
= priv_check(req
->td
, PRIV_NETINET_GETCRED
);
418 error
= SYSCTL_IN(req
, addrs
, sizeof(addrs
));
422 stcb
= sctp_findassociation_addr_sa(sintosa(&addrs
[0]),
424 &inp
, &net
, 1, vrf_id
);
425 if (stcb
== NULL
|| inp
== NULL
|| inp
->sctp_socket
== NULL
) {
426 if ((inp
!= NULL
) && (stcb
== NULL
)) {
427 /* reduce ref-count */
429 SCTP_INP_DECR_REF(inp
);
432 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, ENOENT
);
436 SCTP_TCB_UNLOCK(stcb
);
438 * We use the write lock here, only since in the error leg we need
439 * it. If we used RLOCK, then we would have to
440 * wlock/decr/unlock/rlock. Which in theory could create a hole.
441 * Better to use higher wlock.
445 error
= cr_canseesocket(req
->td
->td_ucred
, inp
->sctp_socket
);
447 SCTP_INP_WUNLOCK(inp
);
450 cru2x(inp
->sctp_socket
->so_cred
, &xuc
);
451 SCTP_INP_WUNLOCK(inp
);
452 error
= SYSCTL_OUT(req
, &xuc
, sizeof(struct xucred
));
457 SYSCTL_PROC(_net_inet_sctp
, OID_AUTO
, getcred
, CTLTYPE_OPAQUE
| CTLFLAG_RW
,
458 0, 0, sctp_getcred
, "S,ucred", "Get the ucred of a SCTP connection");
462 sctp_abort(struct socket
*so
)
464 struct sctp_inpcb
*inp
;
467 inp
= (struct sctp_inpcb
*)so
->so_pcb
;
472 flags
= inp
->sctp_flags
;
473 #ifdef SCTP_LOG_CLOSING
474 sctp_log_closing(inp
, NULL
, 17);
476 if (((flags
& SCTP_PCB_FLAGS_SOCKET_GONE
) == 0) &&
477 (atomic_cmpset_int(&inp
->sctp_flags
, flags
, (flags
| SCTP_PCB_FLAGS_SOCKET_GONE
| SCTP_PCB_FLAGS_CLOSE_IP
)))) {
478 #ifdef SCTP_LOG_CLOSING
479 sctp_log_closing(inp
, NULL
, 16);
481 sctp_inpcb_free(inp
, SCTP_FREE_SHOULD_USE_ABORT
,
482 SCTP_CALLED_AFTER_CMPSET_OFCLOSE
);
484 SCTP_SB_CLEAR(so
->so_snd
);
486 * same for the rcv ones, they are only here for the
489 SCTP_SB_CLEAR(so
->so_rcv
);
491 /* Now null out the reference, we are completely detached. */
495 flags
= inp
->sctp_flags
;
496 if ((flags
& SCTP_PCB_FLAGS_SOCKET_GONE
) == 0) {
497 goto sctp_must_try_again
;
504 sctp_attach(struct socket
*so
, int proto
, struct thread
*p
)
506 struct sctp_inpcb
*inp
;
507 struct inpcb
*ip_inp
;
509 uint32_t vrf_id
= SCTP_DEFAULT_VRFID
;
515 inp
= (struct sctp_inpcb
*)so
->so_pcb
;
517 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
520 error
= SCTP_SORESERVE(so
, SCTP_BASE_SYSCTL(sctp_sendspace
), SCTP_BASE_SYSCTL(sctp_recvspace
));
524 error
= sctp_inpcb_alloc(so
, vrf_id
);
528 inp
= (struct sctp_inpcb
*)so
->so_pcb
;
530 inp
->sctp_flags
&= ~SCTP_PCB_FLAGS_BOUND_V6
; /* I'm not v6! */
531 ip_inp
= &inp
->ip_inp
.inp
;
532 ip_inp
->inp_vflag
|= INP_IPV4
;
533 ip_inp
->inp_ip_ttl
= MODULE_GLOBAL(MOD_INET
, ip_defttl
);
535 error
= ipsec_init_policy(so
, &ip_inp
->inp_sp
);
536 #ifdef SCTP_LOG_CLOSING
537 sctp_log_closing(inp
, NULL
, 17);
540 flags
= inp
->sctp_flags
;
541 if (((flags
& SCTP_PCB_FLAGS_SOCKET_GONE
) == 0) &&
542 (atomic_cmpset_int(&inp
->sctp_flags
, flags
, (flags
| SCTP_PCB_FLAGS_SOCKET_GONE
| SCTP_PCB_FLAGS_CLOSE_IP
)))) {
543 #ifdef SCTP_LOG_CLOSING
544 sctp_log_closing(inp
, NULL
, 15);
546 SCTP_INP_WUNLOCK(inp
);
547 sctp_inpcb_free(inp
, SCTP_FREE_SHOULD_USE_ABORT
,
548 SCTP_CALLED_AFTER_CMPSET_OFCLOSE
);
550 SCTP_INP_WUNLOCK(inp
);
555 SCTP_INP_WUNLOCK(inp
);
560 sctp_bind(struct socket
*so
, struct sockaddr
*addr
, struct thread
*p
)
562 struct sctp_inpcb
*inp
= NULL
;
566 if (addr
&& addr
->sa_family
!= AF_INET
) {
567 /* must be a v4 address! */
568 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
572 if (addr
&& (addr
->sa_len
!= sizeof(struct sockaddr_in
))) {
573 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
576 inp
= (struct sctp_inpcb
*)so
->so_pcb
;
578 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
581 error
= sctp_inpcb_bind(so
, addr
, NULL
, p
);
586 sctp_close(struct socket
*so
)
588 struct sctp_inpcb
*inp
;
591 inp
= (struct sctp_inpcb
*)so
->so_pcb
;
596 * Inform all the lower layer assoc that we are done.
599 flags
= inp
->sctp_flags
;
600 #ifdef SCTP_LOG_CLOSING
601 sctp_log_closing(inp
, NULL
, 17);
603 if (((flags
& SCTP_PCB_FLAGS_SOCKET_GONE
) == 0) &&
604 (atomic_cmpset_int(&inp
->sctp_flags
, flags
, (flags
| SCTP_PCB_FLAGS_SOCKET_GONE
| SCTP_PCB_FLAGS_CLOSE_IP
)))) {
605 if (((so
->so_options
& SO_LINGER
) && (so
->so_linger
== 0)) ||
606 (so
->so_rcv
.sb_cc
> 0)) {
607 #ifdef SCTP_LOG_CLOSING
608 sctp_log_closing(inp
, NULL
, 13);
610 sctp_inpcb_free(inp
, SCTP_FREE_SHOULD_USE_ABORT
,
611 SCTP_CALLED_AFTER_CMPSET_OFCLOSE
);
613 #ifdef SCTP_LOG_CLOSING
614 sctp_log_closing(inp
, NULL
, 14);
616 sctp_inpcb_free(inp
, SCTP_FREE_SHOULD_USE_GRACEFUL_CLOSE
,
617 SCTP_CALLED_AFTER_CMPSET_OFCLOSE
);
620 * The socket is now detached, no matter what the state of
621 * the SCTP association.
624 SCTP_SB_CLEAR(so
->so_snd
);
626 * same for the rcv ones, they are only here for the
629 SCTP_SB_CLEAR(so
->so_rcv
);
631 /* Now null out the reference, we are completely detached. */
635 flags
= inp
->sctp_flags
;
636 if ((flags
& SCTP_PCB_FLAGS_SOCKET_GONE
) == 0) {
637 goto sctp_must_try_again
;
645 sctp_sendm(struct socket
*so
, int flags
, struct mbuf
*m
, struct sockaddr
*addr
,
646 struct mbuf
*control
, struct thread
*p
);
650 sctp_sendm(struct socket
*so
, int flags
, struct mbuf
*m
, struct sockaddr
*addr
,
651 struct mbuf
*control
, struct thread
*p
)
653 struct sctp_inpcb
*inp
;
656 inp
= (struct sctp_inpcb
*)so
->so_pcb
;
659 sctp_m_freem(control
);
662 SCTP_LTRACE_ERR_RET_PKT(m
, inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
666 /* Got to have an to address if we are NOT a connected socket */
667 if ((addr
== NULL
) &&
668 ((inp
->sctp_flags
& SCTP_PCB_FLAGS_CONNECTED
) ||
669 (inp
->sctp_flags
& SCTP_PCB_FLAGS_TCPTYPE
))
672 } else if (addr
== NULL
) {
673 SCTP_LTRACE_ERR_RET_PKT(m
, inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EDESTADDRREQ
);
674 error
= EDESTADDRREQ
;
677 sctp_m_freem(control
);
683 if (addr
->sa_family
!= AF_INET
) {
684 /* must be a v4 address! */
685 SCTP_LTRACE_ERR_RET_PKT(m
, inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EDESTADDRREQ
);
688 sctp_m_freem(control
);
691 error
= EDESTADDRREQ
;
696 /* now what about control */
699 SCTP_PRINTF("huh? control set?\n");
700 sctp_m_freem(inp
->control
);
703 inp
->control
= control
;
707 SCTP_BUF_NEXT(inp
->pkt_last
) = m
;
710 inp
->pkt_last
= inp
->pkt
= m
;
713 /* FreeBSD uses a flag passed */
714 ((flags
& PRUS_MORETOCOME
) == 0)
717 * note with the current version this code will only be used
718 * by OpenBSD-- NetBSD, FreeBSD, and MacOS have methods for
719 * re-defining sosend to use the sctp_sosend. One can
720 * optionally switch back to this code (by changing back the
721 * definitions) but this is not advisable. This code is used
722 * by FreeBSD when sending a file with sendfile() though.
726 ret
= sctp_output(inp
, inp
->pkt
, addr
, inp
->control
, p
, flags
);
736 sctp_disconnect(struct socket
*so
)
738 struct sctp_inpcb
*inp
;
740 inp
= (struct sctp_inpcb
*)so
->so_pcb
;
742 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, ENOTCONN
);
746 if ((inp
->sctp_flags
& SCTP_PCB_FLAGS_TCPTYPE
) ||
747 (inp
->sctp_flags
& SCTP_PCB_FLAGS_IN_TCPPOOL
)) {
748 if (SCTP_LIST_EMPTY(&inp
->sctp_asoc_list
)) {
750 SCTP_INP_RUNLOCK(inp
);
753 struct sctp_association
*asoc
;
754 struct sctp_tcb
*stcb
;
756 stcb
= LIST_FIRST(&inp
->sctp_asoc_list
);
758 SCTP_INP_RUNLOCK(inp
);
759 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
764 if (stcb
->asoc
.state
& SCTP_STATE_ABOUT_TO_BE_FREED
) {
765 /* We are about to be freed, out of here */
766 SCTP_TCB_UNLOCK(stcb
);
767 SCTP_INP_RUNLOCK(inp
);
770 if (((so
->so_options
& SO_LINGER
) &&
771 (so
->so_linger
== 0)) ||
772 (so
->so_rcv
.sb_cc
> 0)) {
773 if (SCTP_GET_STATE(asoc
) !=
774 SCTP_STATE_COOKIE_WAIT
) {
775 /* Left with Data unread */
778 err
= sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr
), 0, M_DONTWAIT
, 1, MT_DATA
);
784 struct sctp_paramhdr
*ph
;
786 ph
= mtod(err
, struct sctp_paramhdr
*);
787 SCTP_BUF_LEN(err
) = sizeof(struct sctp_paramhdr
);
788 ph
->param_type
= htons(SCTP_CAUSE_USER_INITIATED_ABT
);
789 ph
->param_length
= htons(SCTP_BUF_LEN(err
));
791 #if defined(SCTP_PANIC_ON_ABORT)
792 panic("disconnect does an abort");
794 sctp_send_abort_tcb(stcb
, err
, SCTP_SO_LOCKED
);
795 SCTP_STAT_INCR_COUNTER32(sctps_aborted
);
797 SCTP_INP_RUNLOCK(inp
);
798 if ((SCTP_GET_STATE(&stcb
->asoc
) == SCTP_STATE_OPEN
) ||
799 (SCTP_GET_STATE(&stcb
->asoc
) == SCTP_STATE_SHUTDOWN_RECEIVED
)) {
800 SCTP_STAT_DECR_GAUGE32(sctps_currestab
);
802 (void)sctp_free_assoc(inp
, stcb
, SCTP_NORMAL_PROC
, SCTP_FROM_SCTP_USRREQ
+ SCTP_LOC_3
);
803 /* No unlock tcb assoc is gone */
806 if (TAILQ_EMPTY(&asoc
->send_queue
) &&
807 TAILQ_EMPTY(&asoc
->sent_queue
) &&
808 (asoc
->stream_queue_cnt
== 0)) {
809 /* there is nothing queued to send, so done */
810 if (asoc
->locked_on_sending
) {
813 if ((SCTP_GET_STATE(asoc
) != SCTP_STATE_SHUTDOWN_SENT
) &&
814 (SCTP_GET_STATE(asoc
) != SCTP_STATE_SHUTDOWN_ACK_SENT
)) {
815 /* only send SHUTDOWN 1st time thru */
816 sctp_stop_timers_for_shutdown(stcb
);
817 sctp_send_shutdown(stcb
,
818 stcb
->asoc
.primary_destination
);
819 sctp_chunk_output(stcb
->sctp_ep
, stcb
, SCTP_OUTPUT_FROM_T3
, SCTP_SO_LOCKED
);
820 if ((SCTP_GET_STATE(asoc
) == SCTP_STATE_OPEN
) ||
821 (SCTP_GET_STATE(asoc
) == SCTP_STATE_SHUTDOWN_RECEIVED
)) {
822 SCTP_STAT_DECR_GAUGE32(sctps_currestab
);
824 SCTP_SET_STATE(asoc
, SCTP_STATE_SHUTDOWN_SENT
);
825 SCTP_CLEAR_SUBSTATE(asoc
, SCTP_STATE_SHUTDOWN_PENDING
);
826 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN
,
828 asoc
->primary_destination
);
829 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD
,
831 asoc
->primary_destination
);
835 * we still got (or just got) data to send,
836 * so set SHUTDOWN_PENDING
839 * XXX sockets draft says that SCTP_EOF
840 * should be sent with no data. currently,
841 * we will allow user data to be sent first
842 * and move to SHUTDOWN-PENDING
844 asoc
->state
|= SCTP_STATE_SHUTDOWN_PENDING
;
845 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD
, stcb
->sctp_ep
, stcb
,
846 asoc
->primary_destination
);
847 if (asoc
->locked_on_sending
) {
848 /* Locked to send out the data */
849 struct sctp_stream_queue_pending
*sp
;
851 sp
= TAILQ_LAST(&asoc
->locked_on_sending
->outqueue
, sctp_streamhead
);
853 SCTP_PRINTF("Error, sp is NULL, locked on sending is non-null strm:%d\n",
854 asoc
->locked_on_sending
->stream_no
);
856 if ((sp
->length
== 0) && (sp
->msg_is_complete
== 0))
857 asoc
->state
|= SCTP_STATE_PARTIAL_MSG_LEFT
;
860 if (TAILQ_EMPTY(&asoc
->send_queue
) &&
861 TAILQ_EMPTY(&asoc
->sent_queue
) &&
862 (asoc
->state
& SCTP_STATE_PARTIAL_MSG_LEFT
)) {
866 op_err
= sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr
) + sizeof(uint32_t)),
867 0, M_DONTWAIT
, 1, MT_DATA
);
873 struct sctp_paramhdr
*ph
;
876 SCTP_BUF_LEN(op_err
) =
877 (sizeof(struct sctp_paramhdr
) + sizeof(uint32_t));
879 struct sctp_paramhdr
*);
880 ph
->param_type
= htons(
881 SCTP_CAUSE_USER_INITIATED_ABT
);
882 ph
->param_length
= htons(SCTP_BUF_LEN(op_err
));
883 ippp
= (uint32_t *) (ph
+ 1);
884 *ippp
= htonl(SCTP_FROM_SCTP_USRREQ
+ SCTP_LOC_4
);
886 #if defined(SCTP_PANIC_ON_ABORT)
887 panic("disconnect does an abort");
890 stcb
->sctp_ep
->last_abort_code
= SCTP_FROM_SCTP_USRREQ
+ SCTP_LOC_4
;
891 sctp_send_abort_tcb(stcb
, op_err
, SCTP_SO_LOCKED
);
892 SCTP_STAT_INCR_COUNTER32(sctps_aborted
);
893 if ((SCTP_GET_STATE(&stcb
->asoc
) == SCTP_STATE_OPEN
) ||
894 (SCTP_GET_STATE(&stcb
->asoc
) == SCTP_STATE_SHUTDOWN_RECEIVED
)) {
895 SCTP_STAT_DECR_GAUGE32(sctps_currestab
);
897 SCTP_INP_RUNLOCK(inp
);
898 (void)sctp_free_assoc(inp
, stcb
, SCTP_NORMAL_PROC
, SCTP_FROM_SCTP_USRREQ
+ SCTP_LOC_5
);
901 sctp_chunk_output(inp
, stcb
, SCTP_OUTPUT_FROM_CLOSING
, SCTP_SO_LOCKED
);
904 SCTP_TCB_UNLOCK(stcb
);
905 SCTP_INP_RUNLOCK(inp
);
910 /* UDP model does not support this */
911 SCTP_INP_RUNLOCK(inp
);
912 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EOPNOTSUPP
);
918 sctp_flush(struct socket
*so
, int how
)
921 * We will just clear out the values and let subsequent close clear
922 * out the data, if any. Note if the user did a shutdown(SHUT_RD)
923 * they will not be able to read the data, the socket will block
924 * that from happening.
926 if ((how
== PRU_FLUSH_RD
) || (how
== PRU_FLUSH_RDWR
)) {
928 * First make sure the sb will be happy, we don't use these
929 * except maybe the count
931 so
->so_rcv
.sb_cc
= 0;
932 so
->so_rcv
.sb_mbcnt
= 0;
933 so
->so_rcv
.sb_mb
= NULL
;
935 if ((how
== PRU_FLUSH_WR
) || (how
== PRU_FLUSH_RDWR
)) {
937 * First make sure the sb will be happy, we don't use these
938 * except maybe the count
940 so
->so_snd
.sb_cc
= 0;
941 so
->so_snd
.sb_mbcnt
= 0;
942 so
->so_snd
.sb_mb
= NULL
;
949 sctp_shutdown(struct socket
*so
)
951 struct sctp_inpcb
*inp
;
953 inp
= (struct sctp_inpcb
*)so
->so_pcb
;
955 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
959 /* For UDP model this is a invalid call */
960 if (inp
->sctp_flags
& SCTP_PCB_FLAGS_UDPTYPE
) {
961 /* Restore the flags that the soshutdown took away. */
962 so
->so_rcv
.sb_state
&= ~SBS_CANTRCVMORE
;
963 /* This proc will wakeup for read and do nothing (I hope) */
964 SCTP_INP_RUNLOCK(inp
);
965 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EOPNOTSUPP
);
969 * Ok if we reach here its the TCP model and it is either a SHUT_WR
970 * or SHUT_RDWR. This means we put the shutdown flag against it.
973 struct sctp_tcb
*stcb
;
974 struct sctp_association
*asoc
;
978 stcb
= LIST_FIRST(&inp
->sctp_asoc_list
);
981 * Ok we hit the case that the shutdown call was
982 * made after an abort or something. Nothing to do
985 SCTP_INP_RUNLOCK(inp
);
990 if (TAILQ_EMPTY(&asoc
->send_queue
) &&
991 TAILQ_EMPTY(&asoc
->sent_queue
) &&
992 (asoc
->stream_queue_cnt
== 0)) {
993 if (asoc
->locked_on_sending
) {
996 /* there is nothing queued to send, so I'm done... */
997 if (SCTP_GET_STATE(asoc
) != SCTP_STATE_SHUTDOWN_SENT
) {
998 /* only send SHUTDOWN the first time through */
999 sctp_stop_timers_for_shutdown(stcb
);
1000 sctp_send_shutdown(stcb
,
1001 stcb
->asoc
.primary_destination
);
1002 sctp_chunk_output(stcb
->sctp_ep
, stcb
, SCTP_OUTPUT_FROM_T3
, SCTP_SO_LOCKED
);
1003 if ((SCTP_GET_STATE(asoc
) == SCTP_STATE_OPEN
) ||
1004 (SCTP_GET_STATE(asoc
) == SCTP_STATE_SHUTDOWN_RECEIVED
)) {
1005 SCTP_STAT_DECR_GAUGE32(sctps_currestab
);
1007 SCTP_SET_STATE(asoc
, SCTP_STATE_SHUTDOWN_SENT
);
1008 SCTP_CLEAR_SUBSTATE(asoc
, SCTP_STATE_SHUTDOWN_PENDING
);
1009 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN
,
1010 stcb
->sctp_ep
, stcb
,
1011 asoc
->primary_destination
);
1012 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD
,
1013 stcb
->sctp_ep
, stcb
,
1014 asoc
->primary_destination
);
1018 * we still got (or just got) data to send, so set
1021 asoc
->state
|= SCTP_STATE_SHUTDOWN_PENDING
;
1022 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD
, stcb
->sctp_ep
, stcb
,
1023 asoc
->primary_destination
);
1025 if (asoc
->locked_on_sending
) {
1026 /* Locked to send out the data */
1027 struct sctp_stream_queue_pending
*sp
;
1029 sp
= TAILQ_LAST(&asoc
->locked_on_sending
->outqueue
, sctp_streamhead
);
1031 SCTP_PRINTF("Error, sp is NULL, locked on sending is non-null strm:%d\n",
1032 asoc
->locked_on_sending
->stream_no
);
1034 if ((sp
->length
== 0) && (sp
->msg_is_complete
== 0)) {
1035 asoc
->state
|= SCTP_STATE_PARTIAL_MSG_LEFT
;
1039 if (TAILQ_EMPTY(&asoc
->send_queue
) &&
1040 TAILQ_EMPTY(&asoc
->sent_queue
) &&
1041 (asoc
->state
& SCTP_STATE_PARTIAL_MSG_LEFT
)) {
1042 struct mbuf
*op_err
;
1045 op_err
= sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr
) + sizeof(uint32_t)),
1046 0, M_DONTWAIT
, 1, MT_DATA
);
1048 /* Fill in the user initiated abort */
1049 struct sctp_paramhdr
*ph
;
1052 SCTP_BUF_LEN(op_err
) =
1053 sizeof(struct sctp_paramhdr
) + sizeof(uint32_t);
1055 struct sctp_paramhdr
*);
1056 ph
->param_type
= htons(
1057 SCTP_CAUSE_USER_INITIATED_ABT
);
1058 ph
->param_length
= htons(SCTP_BUF_LEN(op_err
));
1059 ippp
= (uint32_t *) (ph
+ 1);
1060 *ippp
= htonl(SCTP_FROM_SCTP_USRREQ
+ SCTP_LOC_6
);
1062 #if defined(SCTP_PANIC_ON_ABORT)
1063 panic("shutdown does an abort");
1065 stcb
->sctp_ep
->last_abort_code
= SCTP_FROM_SCTP_USRREQ
+ SCTP_LOC_6
;
1066 sctp_abort_an_association(stcb
->sctp_ep
, stcb
,
1067 SCTP_RESPONSE_TO_USER_REQ
,
1068 op_err
, SCTP_SO_LOCKED
);
1071 sctp_chunk_output(inp
, stcb
, SCTP_OUTPUT_FROM_CLOSING
, SCTP_SO_LOCKED
);
1074 SCTP_TCB_UNLOCK(stcb
);
1077 SCTP_INP_RUNLOCK(inp
);
1082 * copies a "user" presentable address and removes embedded scope, etc.
1083 * returns 0 on success, 1 on error
1086 sctp_fill_user_address(struct sockaddr_storage
*ss
, struct sockaddr
*sa
)
1089 struct sockaddr_in6 lsa6
;
1091 sa
= (struct sockaddr
*)sctp_recover_scope((struct sockaddr_in6
*)sa
,
1094 memcpy(ss
, sa
, sa
->sa_len
);
1101 * NOTE: assumes addr lock is held
1104 sctp_fill_up_addresses_vrf(struct sctp_inpcb
*inp
,
1105 struct sctp_tcb
*stcb
,
1107 struct sockaddr_storage
*sas
,
1110 struct sctp_ifn
*sctp_ifn
;
1111 struct sctp_ifa
*sctp_ifa
;
1112 int loopback_scope
, ipv4_local_scope
, local_scope
, site_scope
;
1114 int ipv4_addr_legal
, ipv6_addr_legal
;
1115 struct sctp_vrf
*vrf
;
1122 /* Turn on all the appropriate scope */
1123 loopback_scope
= stcb
->asoc
.loopback_scope
;
1124 ipv4_local_scope
= stcb
->asoc
.ipv4_local_scope
;
1125 local_scope
= stcb
->asoc
.local_scope
;
1126 site_scope
= stcb
->asoc
.site_scope
;
1128 /* Turn on ALL scope, since we look at the EP */
1129 loopback_scope
= ipv4_local_scope
= local_scope
=
1132 ipv4_addr_legal
= ipv6_addr_legal
= 0;
1133 if (inp
->sctp_flags
& SCTP_PCB_FLAGS_BOUND_V6
) {
1134 ipv6_addr_legal
= 1;
1135 if (SCTP_IPV6_V6ONLY(inp
) == 0) {
1136 ipv4_addr_legal
= 1;
1139 ipv4_addr_legal
= 1;
1141 vrf
= sctp_find_vrf(vrf_id
);
1145 if (inp
->sctp_flags
& SCTP_PCB_FLAGS_BOUNDALL
) {
1146 LIST_FOREACH(sctp_ifn
, &vrf
->ifnlist
, next_ifn
) {
1147 if ((loopback_scope
== 0) &&
1148 SCTP_IFN_IS_IFT_LOOP(sctp_ifn
)) {
1149 /* Skip loopback if loopback_scope not set */
1152 LIST_FOREACH(sctp_ifa
, &sctp_ifn
->ifalist
, next_ifa
) {
1155 * For the BOUND-ALL case, the list
1156 * associated with a TCB is Always
1157 * considered a reverse list.. i.e.
1158 * it lists addresses that are NOT
1159 * part of the association. If this
1160 * is one of those we must skip it.
1162 if (sctp_is_addr_restricted(stcb
,
1167 switch (sctp_ifa
->address
.sa
.sa_family
) {
1169 if (ipv4_addr_legal
) {
1170 struct sockaddr_in
*sin
;
1172 sin
= (struct sockaddr_in
*)&sctp_ifa
->address
.sa
;
1173 if (sin
->sin_addr
.s_addr
== 0) {
1181 if ((ipv4_local_scope
== 0) &&
1182 (IN4_ISPRIVATE_ADDRESS(&sin
->sin_addr
))) {
1186 if (sctp_is_feature_on(inp
, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4
)) {
1187 in6_sin_2_v4mapsin6(sin
, (struct sockaddr_in6
*)sas
);
1188 ((struct sockaddr_in6
*)sas
)->sin6_port
= inp
->sctp_lport
;
1189 sas
= (struct sockaddr_storage
*)((caddr_t
)sas
+ sizeof(struct sockaddr_in6
));
1190 actual
+= sizeof(struct sockaddr_in6
);
1193 memcpy(sas
, sin
, sizeof(*sin
));
1194 ((struct sockaddr_in
*)sas
)->sin_port
= inp
->sctp_lport
;
1195 sas
= (struct sockaddr_storage
*)((caddr_t
)sas
+ sizeof(*sin
));
1196 actual
+= sizeof(*sin
);
1200 if (actual
>= limit
) {
1209 if (ipv6_addr_legal
) {
1210 struct sockaddr_in6
*sin6
;
1212 sin6
= (struct sockaddr_in6
*)&sctp_ifa
->address
.sa
;
1213 if (IN6_IS_ADDR_UNSPECIFIED(&sin6
->sin6_addr
)) {
1221 if (IN6_IS_ADDR_LINKLOCAL(&sin6
->sin6_addr
)) {
1222 if (local_scope
== 0)
1224 if (sin6
->sin6_scope_id
== 0) {
1225 if (sa6_recoverscope(sin6
) != 0)
1243 if ((site_scope
== 0) &&
1244 (IN6_IS_ADDR_SITELOCAL(&sin6
->sin6_addr
))) {
1247 memcpy(sas
, sin6
, sizeof(*sin6
));
1248 ((struct sockaddr_in6
*)sas
)->sin6_port
= inp
->sctp_lport
;
1249 sas
= (struct sockaddr_storage
*)((caddr_t
)sas
+ sizeof(*sin6
));
1250 actual
+= sizeof(*sin6
);
1251 if (actual
>= limit
) {
1266 struct sctp_laddr
*laddr
;
1268 LIST_FOREACH(laddr
, &inp
->sctp_addr_list
, sctp_nxt_addr
) {
1270 if (sctp_is_addr_restricted(stcb
, laddr
->ifa
)) {
1274 if (sctp_fill_user_address(sas
, &laddr
->ifa
->address
.sa
))
1277 ((struct sockaddr_in6
*)sas
)->sin6_port
= inp
->sctp_lport
;
1278 sas
= (struct sockaddr_storage
*)((caddr_t
)sas
+
1279 laddr
->ifa
->address
.sa
.sa_len
);
1280 actual
+= laddr
->ifa
->address
.sa
.sa_len
;
1281 if (actual
>= limit
) {
1290 sctp_fill_up_addresses(struct sctp_inpcb
*inp
,
1291 struct sctp_tcb
*stcb
,
1293 struct sockaddr_storage
*sas
)
1297 SCTP_IPI_ADDR_RLOCK();
1298 /* fill up addresses for the endpoint's default vrf */
1299 size
= sctp_fill_up_addresses_vrf(inp
, stcb
, limit
, sas
,
1301 SCTP_IPI_ADDR_RUNLOCK();
1306 * NOTE: assumes addr lock is held
1309 sctp_count_max_addresses_vrf(struct sctp_inpcb
*inp
, uint32_t vrf_id
)
1312 struct sctp_vrf
*vrf
= NULL
;
1315 * In both sub-set bound an bound_all cases we return the MAXIMUM
1316 * number of addresses that you COULD get. In reality the sub-set
1317 * bound may have an exclusion list for a given TCB OR in the
1318 * bound-all case a TCB may NOT include the loopback or other
1319 * addresses as well.
1321 vrf
= sctp_find_vrf(vrf_id
);
1325 if (inp
->sctp_flags
& SCTP_PCB_FLAGS_BOUNDALL
) {
1326 struct sctp_ifn
*sctp_ifn
;
1327 struct sctp_ifa
*sctp_ifa
;
1329 LIST_FOREACH(sctp_ifn
, &vrf
->ifnlist
, next_ifn
) {
1330 LIST_FOREACH(sctp_ifa
, &sctp_ifn
->ifalist
, next_ifa
) {
1331 /* Count them if they are the right type */
1332 if (sctp_ifa
->address
.sa
.sa_family
== AF_INET
) {
1333 if (sctp_is_feature_on(inp
, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4
))
1334 cnt
+= sizeof(struct sockaddr_in6
);
1336 cnt
+= sizeof(struct sockaddr_in
);
1338 } else if (sctp_ifa
->address
.sa
.sa_family
== AF_INET6
)
1339 cnt
+= sizeof(struct sockaddr_in6
);
1343 struct sctp_laddr
*laddr
;
1345 LIST_FOREACH(laddr
, &inp
->sctp_addr_list
, sctp_nxt_addr
) {
1346 if (laddr
->ifa
->address
.sa
.sa_family
== AF_INET
) {
1347 if (sctp_is_feature_on(inp
, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4
))
1348 cnt
+= sizeof(struct sockaddr_in6
);
1350 cnt
+= sizeof(struct sockaddr_in
);
1352 } else if (laddr
->ifa
->address
.sa
.sa_family
== AF_INET6
)
1353 cnt
+= sizeof(struct sockaddr_in6
);
1360 sctp_count_max_addresses(struct sctp_inpcb
*inp
)
1364 SCTP_IPI_ADDR_RLOCK();
1365 /* count addresses for the endpoint's default VRF */
1366 cnt
= sctp_count_max_addresses_vrf(inp
, inp
->def_vrf_id
);
1367 SCTP_IPI_ADDR_RUNLOCK();
1372 sctp_do_connect_x(struct socket
*so
, struct sctp_inpcb
*inp
, void *optval
,
1373 size_t optsize
, void *p
, int delay
)
1376 int creat_lock_on
= 0;
1377 struct sctp_tcb
*stcb
= NULL
;
1378 struct sockaddr
*sa
;
1379 int num_v6
= 0, num_v4
= 0, *totaddrp
, totaddr
;
1382 int bad_addresses
= 0;
1385 SCTPDBG(SCTP_DEBUG_PCB1
, "Connectx called\n");
1387 if ((inp
->sctp_flags
& SCTP_PCB_FLAGS_TCPTYPE
) &&
1388 (inp
->sctp_flags
& SCTP_PCB_FLAGS_CONNECTED
)) {
1389 /* We are already connected AND the TCP model */
1390 SCTP_LTRACE_ERR_RET(inp
, stcb
, NULL
, SCTP_FROM_SCTP_USRREQ
, EADDRINUSE
);
1391 return (EADDRINUSE
);
1393 if ((inp
->sctp_flags
& SCTP_PCB_FLAGS_IN_TCPPOOL
) &&
1394 (sctp_is_feature_off(inp
, SCTP_PCB_FLAGS_PORTREUSE
))) {
1395 SCTP_LTRACE_ERR_RET(inp
, stcb
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
1398 if (inp
->sctp_flags
& SCTP_PCB_FLAGS_CONNECTED
) {
1399 SCTP_INP_RLOCK(inp
);
1400 stcb
= LIST_FIRST(&inp
->sctp_asoc_list
);
1401 SCTP_INP_RUNLOCK(inp
);
1404 SCTP_LTRACE_ERR_RET(inp
, stcb
, NULL
, SCTP_FROM_SCTP_USRREQ
, EALREADY
);
1407 SCTP_INP_INCR_REF(inp
);
1408 SCTP_ASOC_CREATE_LOCK(inp
);
1410 if ((inp
->sctp_flags
& SCTP_PCB_FLAGS_SOCKET_ALLGONE
) ||
1411 (inp
->sctp_flags
& SCTP_PCB_FLAGS_SOCKET_GONE
)) {
1412 SCTP_LTRACE_ERR_RET(inp
, stcb
, NULL
, SCTP_FROM_SCTP_USRREQ
, EFAULT
);
1416 totaddrp
= (int *)optval
;
1417 totaddr
= *totaddrp
;
1418 sa
= (struct sockaddr
*)(totaddrp
+ 1);
1419 stcb
= sctp_connectx_helper_find(inp
, sa
, &totaddr
, &num_v4
, &num_v6
, &error
, (optsize
- sizeof(int)), &bad_addresses
);
1420 if ((stcb
!= NULL
) || bad_addresses
) {
1421 /* Already have or am bring up an association */
1422 SCTP_ASOC_CREATE_UNLOCK(inp
);
1425 SCTP_TCB_UNLOCK(stcb
);
1426 if (bad_addresses
== 0) {
1427 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EALREADY
);
1433 if (((inp
->sctp_flags
& SCTP_PCB_FLAGS_BOUND_V6
) == 0) &&
1438 if ((inp
->sctp_flags
& SCTP_PCB_FLAGS_BOUND_V6
) &&
1440 struct in6pcb
*inp6
;
1442 inp6
= (struct in6pcb
*)inp
;
1443 if (SCTP_IPV6_V6ONLY(inp6
)) {
1445 * if IPV6_V6ONLY flag, ignore connections destined
1446 * to a v4 addr or v4-mapped addr
1448 SCTP_LTRACE_ERR_RET(inp
, stcb
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
1454 if ((inp
->sctp_flags
& SCTP_PCB_FLAGS_UNBOUND
) ==
1455 SCTP_PCB_FLAGS_UNBOUND
) {
1456 /* Bind a ephemeral port */
1457 error
= sctp_inpcb_bind(so
, NULL
, NULL
, p
);
1462 /* FIX ME: do we want to pass in a vrf on the connect call? */
1463 vrf_id
= inp
->def_vrf_id
;
1466 /* We are GOOD to go */
1467 stcb
= sctp_aloc_assoc(inp
, sa
, 1, &error
, 0, vrf_id
,
1471 /* Gak! no memory */
1474 SCTP_SET_STATE(&stcb
->asoc
, SCTP_STATE_COOKIE_WAIT
);
1475 /* move to second address */
1476 if (sa
->sa_family
== AF_INET
)
1477 sa
= (struct sockaddr
*)((caddr_t
)sa
+ sizeof(struct sockaddr_in
));
1479 sa
= (struct sockaddr
*)((caddr_t
)sa
+ sizeof(struct sockaddr_in6
));
1482 added
= sctp_connectx_helper_add(stcb
, sa
, (totaddr
- 1), &error
);
1483 /* Fill in the return id */
1485 (void)sctp_free_assoc(inp
, stcb
, SCTP_PCBFREE_FORCE
, SCTP_FROM_SCTP_USRREQ
+ SCTP_LOC_12
);
1488 a_id
= (sctp_assoc_t
*) optval
;
1489 *a_id
= sctp_get_associd(stcb
);
1491 /* initialize authentication parameters for the assoc */
1492 sctp_initialize_auth_params(inp
, stcb
);
1495 /* doing delayed connection */
1496 stcb
->asoc
.delayed_connection
= 1;
1497 sctp_timer_start(SCTP_TIMER_TYPE_INIT
, inp
, stcb
, stcb
->asoc
.primary_destination
);
1499 (void)SCTP_GETTIME_TIMEVAL(&stcb
->asoc
.time_entered
);
1500 sctp_send_initiate(inp
, stcb
, SCTP_SO_LOCKED
);
1502 SCTP_TCB_UNLOCK(stcb
);
1503 if (stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_TCPTYPE
) {
1504 stcb
->sctp_ep
->sctp_flags
|= SCTP_PCB_FLAGS_CONNECTED
;
1505 /* Set the connected flag so we can queue data */
1509 if (creat_lock_on
) {
1510 SCTP_ASOC_CREATE_UNLOCK(inp
);
1512 SCTP_INP_DECR_REF(inp
);
1516 #define SCTP_FIND_STCB(inp, stcb, assoc_id) { \
1517 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||\
1518 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { \
1519 SCTP_INP_RLOCK(inp); \
1520 stcb = LIST_FIRST(&inp->sctp_asoc_list); \
1522 SCTP_TCB_LOCK(stcb); \
1524 SCTP_INP_RUNLOCK(inp); \
1525 } else if (assoc_id != 0) { \
1526 stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1); \
1527 if (stcb == NULL) { \
1528 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT); \
1538 #define SCTP_CHECK_AND_CAST(destp, srcp, type, size) {\
1539 if (size < sizeof(type)) { \
1540 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); \
1544 destp = (type *)srcp; \
1549 sctp_getopt(struct socket
*so
, int optname
, void *optval
, size_t *optsize
,
1552 struct sctp_inpcb
*inp
= NULL
;
1554 struct sctp_tcb
*stcb
= NULL
;
1556 if (optval
== NULL
) {
1557 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
1560 inp
= (struct sctp_inpcb
*)so
->so_pcb
;
1562 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
1569 case SCTP_AUTOCLOSE
:
1570 case SCTP_EXPLICIT_EOR
:
1571 case SCTP_AUTO_ASCONF
:
1572 case SCTP_DISABLE_FRAGMENTS
:
1573 case SCTP_I_WANT_MAPPED_V4_ADDR
:
1574 case SCTP_USE_EXT_RCVINFO
:
1575 SCTP_INP_RLOCK(inp
);
1577 case SCTP_DISABLE_FRAGMENTS
:
1578 val
= sctp_is_feature_on(inp
, SCTP_PCB_FLAGS_NO_FRAGMENT
);
1580 case SCTP_I_WANT_MAPPED_V4_ADDR
:
1581 val
= sctp_is_feature_on(inp
, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4
);
1583 case SCTP_AUTO_ASCONF
:
1584 if (inp
->sctp_flags
& SCTP_PCB_FLAGS_BOUNDALL
) {
1585 /* only valid for bound all sockets */
1586 val
= sctp_is_feature_on(inp
, SCTP_PCB_FLAGS_AUTO_ASCONF
);
1588 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
1593 case SCTP_EXPLICIT_EOR
:
1594 val
= sctp_is_feature_on(inp
, SCTP_PCB_FLAGS_EXPLICIT_EOR
);
1597 val
= sctp_is_feature_on(inp
, SCTP_PCB_FLAGS_NODELAY
);
1599 case SCTP_USE_EXT_RCVINFO
:
1600 val
= sctp_is_feature_on(inp
, SCTP_PCB_FLAGS_EXT_RCVINFO
);
1602 case SCTP_AUTOCLOSE
:
1603 if (sctp_is_feature_on(inp
, SCTP_PCB_FLAGS_AUTOCLOSE
))
1604 val
= TICKS_TO_SEC(inp
->sctp_ep
.auto_close_time
);
1610 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, ENOPROTOOPT
);
1611 error
= ENOPROTOOPT
;
1612 } /* end switch (sopt->sopt_name) */
1613 if (optname
!= SCTP_AUTOCLOSE
) {
1614 /* make it an "on/off" value */
1617 if (*optsize
< sizeof(val
)) {
1618 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
1622 SCTP_INP_RUNLOCK(inp
);
1624 /* return the option value */
1625 *(int *)optval
= val
;
1626 *optsize
= sizeof(val
);
1629 case SCTP_GET_PACKET_LOG
:
1631 #ifdef SCTP_PACKET_LOGGING
1635 SCTP_CHECK_AND_CAST(target
, optval
, uint8_t, *optsize
);
1636 ret
= sctp_copy_out_packet_log(target
, (int)*optsize
);
1639 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EOPNOTSUPP
);
1644 case SCTP_REUSE_PORT
:
1648 if ((inp
->sctp_flags
& SCTP_PCB_FLAGS_UDPTYPE
)) {
1649 /* Can't do this for a 1-m socket */
1653 SCTP_CHECK_AND_CAST(value
, optval
, uint32_t, *optsize
);
1654 *value
= sctp_is_feature_on(inp
, SCTP_PCB_FLAGS_PORTREUSE
);
1655 *optsize
= sizeof(uint32_t);
1658 case SCTP_PARTIAL_DELIVERY_POINT
:
1662 SCTP_CHECK_AND_CAST(value
, optval
, uint32_t, *optsize
);
1663 *value
= inp
->partial_delivery_point
;
1664 *optsize
= sizeof(uint32_t);
1667 case SCTP_FRAGMENT_INTERLEAVE
:
1671 SCTP_CHECK_AND_CAST(value
, optval
, uint32_t, *optsize
);
1672 if (sctp_is_feature_on(inp
, SCTP_PCB_FLAGS_FRAG_INTERLEAVE
)) {
1673 if (sctp_is_feature_on(inp
, SCTP_PCB_FLAGS_INTERLEAVE_STRMS
)) {
1674 *value
= SCTP_FRAG_LEVEL_2
;
1676 *value
= SCTP_FRAG_LEVEL_1
;
1679 *value
= SCTP_FRAG_LEVEL_0
;
1681 *optsize
= sizeof(uint32_t);
1684 case SCTP_CMT_ON_OFF
:
1686 struct sctp_assoc_value
*av
;
1688 SCTP_CHECK_AND_CAST(av
, optval
, struct sctp_assoc_value
, *optsize
);
1689 if (SCTP_BASE_SYSCTL(sctp_cmt_on_off
)) {
1690 SCTP_FIND_STCB(inp
, stcb
, av
->assoc_id
);
1692 av
->assoc_value
= stcb
->asoc
.sctp_cmt_on_off
;
1693 SCTP_TCB_UNLOCK(stcb
);
1696 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, ENOTCONN
);
1700 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, ENOPROTOOPT
);
1701 error
= ENOPROTOOPT
;
1703 *optsize
= sizeof(*av
);
1706 /* JRS - Get socket option for pluggable congestion control */
1707 case SCTP_PLUGGABLE_CC
:
1709 struct sctp_assoc_value
*av
;
1711 SCTP_CHECK_AND_CAST(av
, optval
, struct sctp_assoc_value
, *optsize
);
1712 SCTP_FIND_STCB(inp
, stcb
, av
->assoc_id
);
1714 av
->assoc_value
= stcb
->asoc
.congestion_control_module
;
1715 SCTP_TCB_UNLOCK(stcb
);
1717 av
->assoc_value
= inp
->sctp_ep
.sctp_default_cc_module
;
1719 *optsize
= sizeof(*av
);
1722 case SCTP_GET_ADDR_LEN
:
1724 struct sctp_assoc_value
*av
;
1726 SCTP_CHECK_AND_CAST(av
, optval
, struct sctp_assoc_value
, *optsize
);
1729 if (av
->assoc_value
== AF_INET
) {
1730 av
->assoc_value
= sizeof(struct sockaddr_in
);
1735 if (av
->assoc_value
== AF_INET6
) {
1736 av
->assoc_value
= sizeof(struct sockaddr_in6
);
1741 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, error
);
1743 *optsize
= sizeof(*av
);
1746 case SCTP_GET_ASSOC_NUMBER
:
1748 uint32_t *value
, cnt
;
1750 SCTP_CHECK_AND_CAST(value
, optval
, uint32_t, *optsize
);
1752 SCTP_INP_RLOCK(inp
);
1753 LIST_FOREACH(stcb
, &inp
->sctp_asoc_list
, sctp_tcblist
) {
1756 SCTP_INP_RUNLOCK(inp
);
1758 *optsize
= sizeof(uint32_t);
1762 case SCTP_GET_ASSOC_ID_LIST
:
1764 struct sctp_assoc_ids
*ids
;
1765 unsigned int at
, limit
;
1767 SCTP_CHECK_AND_CAST(ids
, optval
, struct sctp_assoc_ids
, *optsize
);
1769 limit
= *optsize
/ sizeof(sctp_assoc_t
);
1770 SCTP_INP_RLOCK(inp
);
1771 LIST_FOREACH(stcb
, &inp
->sctp_asoc_list
, sctp_tcblist
) {
1773 ids
->gaids_assoc_id
[at
++] = sctp_get_associd(stcb
);
1776 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, error
);
1780 SCTP_INP_RUNLOCK(inp
);
1781 *optsize
= at
* sizeof(sctp_assoc_t
);
1786 struct sctp_assoc_value
*av
;
1788 SCTP_CHECK_AND_CAST(av
, optval
, struct sctp_assoc_value
, *optsize
);
1789 SCTP_FIND_STCB(inp
, stcb
, av
->assoc_id
);
1792 av
->assoc_value
= stcb
->asoc
.context
;
1793 SCTP_TCB_UNLOCK(stcb
);
1795 SCTP_INP_RLOCK(inp
);
1796 av
->assoc_value
= inp
->sctp_context
;
1797 SCTP_INP_RUNLOCK(inp
);
1799 *optsize
= sizeof(*av
);
1804 uint32_t *default_vrfid
;
1806 SCTP_CHECK_AND_CAST(default_vrfid
, optval
, uint32_t, *optsize
);
1807 *default_vrfid
= inp
->def_vrf_id
;
1810 case SCTP_GET_ASOC_VRF
:
1812 struct sctp_assoc_value
*id
;
1814 SCTP_CHECK_AND_CAST(id
, optval
, struct sctp_assoc_value
, *optsize
);
1815 SCTP_FIND_STCB(inp
, stcb
, id
->assoc_id
);
1818 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, error
);
1821 id
->assoc_value
= stcb
->asoc
.vrf_id
;
1824 case SCTP_GET_VRF_IDS
:
1826 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EOPNOTSUPP
);
1830 case SCTP_GET_NONCE_VALUES
:
1832 struct sctp_get_nonce_values
*gnv
;
1834 SCTP_CHECK_AND_CAST(gnv
, optval
, struct sctp_get_nonce_values
, *optsize
);
1835 SCTP_FIND_STCB(inp
, stcb
, gnv
->gn_assoc_id
);
1838 gnv
->gn_peers_tag
= stcb
->asoc
.peer_vtag
;
1839 gnv
->gn_local_tag
= stcb
->asoc
.my_vtag
;
1840 SCTP_TCB_UNLOCK(stcb
);
1842 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, ENOTCONN
);
1845 *optsize
= sizeof(*gnv
);
1848 case SCTP_DELAYED_SACK
:
1850 struct sctp_sack_info
*sack
;
1852 SCTP_CHECK_AND_CAST(sack
, optval
, struct sctp_sack_info
, *optsize
);
1853 SCTP_FIND_STCB(inp
, stcb
, sack
->sack_assoc_id
);
1855 sack
->sack_delay
= stcb
->asoc
.delayed_ack
;
1856 sack
->sack_freq
= stcb
->asoc
.sack_freq
;
1857 SCTP_TCB_UNLOCK(stcb
);
1859 SCTP_INP_RLOCK(inp
);
1860 sack
->sack_delay
= TICKS_TO_MSEC(inp
->sctp_ep
.sctp_timeoutticks
[SCTP_TIMER_RECV
]);
1861 sack
->sack_freq
= inp
->sctp_ep
.sctp_sack_freq
;
1862 SCTP_INP_RUNLOCK(inp
);
1864 *optsize
= sizeof(*sack
);
1868 case SCTP_GET_SNDBUF_USE
:
1870 struct sctp_sockstat
*ss
;
1872 SCTP_CHECK_AND_CAST(ss
, optval
, struct sctp_sockstat
, *optsize
);
1873 SCTP_FIND_STCB(inp
, stcb
, ss
->ss_assoc_id
);
1876 ss
->ss_total_sndbuf
= stcb
->asoc
.total_output_queue_size
;
1877 ss
->ss_total_recv_buf
= (stcb
->asoc
.size_on_reasm_queue
+
1878 stcb
->asoc
.size_on_all_streams
);
1879 SCTP_TCB_UNLOCK(stcb
);
1881 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, ENOTCONN
);
1884 *optsize
= sizeof(struct sctp_sockstat
);
1887 case SCTP_MAX_BURST
:
1891 SCTP_CHECK_AND_CAST(value
, optval
, uint8_t, *optsize
);
1893 SCTP_INP_RLOCK(inp
);
1894 *value
= inp
->sctp_ep
.max_burst
;
1895 SCTP_INP_RUNLOCK(inp
);
1896 *optsize
= sizeof(uint8_t);
1901 struct sctp_assoc_value
*av
;
1904 SCTP_CHECK_AND_CAST(av
, optval
, struct sctp_assoc_value
, *optsize
);
1905 SCTP_FIND_STCB(inp
, stcb
, av
->assoc_id
);
1908 av
->assoc_value
= sctp_get_frag_point(stcb
, &stcb
->asoc
);
1909 SCTP_TCB_UNLOCK(stcb
);
1911 SCTP_INP_RLOCK(inp
);
1912 if (inp
->sctp_flags
& SCTP_PCB_FLAGS_BOUND_V6
) {
1913 ovh
= SCTP_MED_OVERHEAD
;
1915 ovh
= SCTP_MED_V4_OVERHEAD
;
1917 if (inp
->sctp_frag_point
>= SCTP_DEFAULT_MAXSEGMENT
)
1918 av
->assoc_value
= 0;
1920 av
->assoc_value
= inp
->sctp_frag_point
- ovh
;
1921 SCTP_INP_RUNLOCK(inp
);
1923 *optsize
= sizeof(struct sctp_assoc_value
);
1926 case SCTP_GET_STAT_LOG
:
1927 error
= sctp_fill_stat_log(optval
, optsize
);
1931 struct sctp_event_subscribe
*events
;
1933 SCTP_CHECK_AND_CAST(events
, optval
, struct sctp_event_subscribe
, *optsize
);
1934 memset(events
, 0, sizeof(*events
));
1935 SCTP_INP_RLOCK(inp
);
1936 if (sctp_is_feature_on(inp
, SCTP_PCB_FLAGS_RECVDATAIOEVNT
))
1937 events
->sctp_data_io_event
= 1;
1939 if (sctp_is_feature_on(inp
, SCTP_PCB_FLAGS_RECVASSOCEVNT
))
1940 events
->sctp_association_event
= 1;
1942 if (sctp_is_feature_on(inp
, SCTP_PCB_FLAGS_RECVPADDREVNT
))
1943 events
->sctp_address_event
= 1;
1945 if (sctp_is_feature_on(inp
, SCTP_PCB_FLAGS_RECVSENDFAILEVNT
))
1946 events
->sctp_send_failure_event
= 1;
1948 if (sctp_is_feature_on(inp
, SCTP_PCB_FLAGS_RECVPEERERR
))
1949 events
->sctp_peer_error_event
= 1;
1951 if (sctp_is_feature_on(inp
, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT
))
1952 events
->sctp_shutdown_event
= 1;
1954 if (sctp_is_feature_on(inp
, SCTP_PCB_FLAGS_PDAPIEVNT
))
1955 events
->sctp_partial_delivery_event
= 1;
1957 if (sctp_is_feature_on(inp
, SCTP_PCB_FLAGS_ADAPTATIONEVNT
))
1958 events
->sctp_adaptation_layer_event
= 1;
1960 if (sctp_is_feature_on(inp
, SCTP_PCB_FLAGS_AUTHEVNT
))
1961 events
->sctp_authentication_event
= 1;
1963 if (sctp_is_feature_on(inp
, SCTP_PCB_FLAGS_STREAM_RESETEVNT
))
1964 events
->sctp_stream_reset_events
= 1;
1965 SCTP_INP_RUNLOCK(inp
);
1966 *optsize
= sizeof(struct sctp_event_subscribe
);
1970 case SCTP_ADAPTATION_LAYER
:
1974 SCTP_CHECK_AND_CAST(value
, optval
, uint32_t, *optsize
);
1976 SCTP_INP_RLOCK(inp
);
1977 *value
= inp
->sctp_ep
.adaptation_layer_indicator
;
1978 SCTP_INP_RUNLOCK(inp
);
1979 *optsize
= sizeof(uint32_t);
1982 case SCTP_SET_INITIAL_DBG_SEQ
:
1986 SCTP_CHECK_AND_CAST(value
, optval
, uint32_t, *optsize
);
1987 SCTP_INP_RLOCK(inp
);
1988 *value
= inp
->sctp_ep
.initial_sequence_debug
;
1989 SCTP_INP_RUNLOCK(inp
);
1990 *optsize
= sizeof(uint32_t);
1993 case SCTP_GET_LOCAL_ADDR_SIZE
:
1997 SCTP_CHECK_AND_CAST(value
, optval
, uint32_t, *optsize
);
1998 SCTP_INP_RLOCK(inp
);
1999 *value
= sctp_count_max_addresses(inp
);
2000 SCTP_INP_RUNLOCK(inp
);
2001 *optsize
= sizeof(uint32_t);
2004 case SCTP_GET_REMOTE_ADDR_SIZE
:
2008 struct sctp_nets
*net
;
2010 SCTP_CHECK_AND_CAST(value
, optval
, uint32_t, *optsize
);
2011 /* FIXME MT: change to sctp_assoc_value? */
2012 SCTP_FIND_STCB(inp
, stcb
, (sctp_assoc_t
) * value
);
2016 /* Count the sizes */
2017 TAILQ_FOREACH(net
, &stcb
->asoc
.nets
, sctp_next
) {
2018 if ((sctp_is_feature_on(inp
, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4
)) ||
2019 (((struct sockaddr
*)&net
->ro
._l_addr
)->sa_family
== AF_INET6
)) {
2020 size
+= sizeof(struct sockaddr_in6
);
2021 } else if (((struct sockaddr
*)&net
->ro
._l_addr
)->sa_family
== AF_INET
) {
2022 size
+= sizeof(struct sockaddr_in
);
2028 SCTP_TCB_UNLOCK(stcb
);
2029 *value
= (uint32_t) size
;
2031 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, ENOTCONN
);
2034 *optsize
= sizeof(uint32_t);
2037 case SCTP_GET_PEER_ADDRESSES
:
2039 * Get the address information, an array is passed in to
2040 * fill up we pack it.
2044 struct sockaddr_storage
*sas
;
2045 struct sctp_nets
*net
;
2046 struct sctp_getaddresses
*saddr
;
2048 SCTP_CHECK_AND_CAST(saddr
, optval
, struct sctp_getaddresses
, *optsize
);
2049 SCTP_FIND_STCB(inp
, stcb
, saddr
->sget_assoc_id
);
2052 left
= (*optsize
) - sizeof(struct sctp_getaddresses
);
2053 *optsize
= sizeof(struct sctp_getaddresses
);
2054 sas
= (struct sockaddr_storage
*)&saddr
->addr
[0];
2056 TAILQ_FOREACH(net
, &stcb
->asoc
.nets
, sctp_next
) {
2057 if ((sctp_is_feature_on(inp
, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4
)) ||
2058 (((struct sockaddr
*)&net
->ro
._l_addr
)->sa_family
== AF_INET6
)) {
2059 cpsz
= sizeof(struct sockaddr_in6
);
2060 } else if (((struct sockaddr
*)&net
->ro
._l_addr
)->sa_family
== AF_INET
) {
2061 cpsz
= sizeof(struct sockaddr_in
);
2067 /* not enough room. */
2071 if ((sctp_is_feature_on(inp
, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4
)) &&
2072 (((struct sockaddr
*)&net
->ro
._l_addr
)->sa_family
== AF_INET
)) {
2073 /* Must map the address */
2074 in6_sin_2_v4mapsin6((struct sockaddr_in
*)&net
->ro
._l_addr
,
2075 (struct sockaddr_in6
*)sas
);
2078 memcpy(sas
, &net
->ro
._l_addr
, cpsz
);
2082 ((struct sockaddr_in
*)sas
)->sin_port
= stcb
->rport
;
2084 sas
= (struct sockaddr_storage
*)((caddr_t
)sas
+ cpsz
);
2088 SCTP_TCB_UNLOCK(stcb
);
2090 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, ENOENT
);
2095 case SCTP_GET_LOCAL_ADDRESSES
:
2097 size_t limit
, actual
;
2098 struct sockaddr_storage
*sas
;
2099 struct sctp_getaddresses
*saddr
;
2101 SCTP_CHECK_AND_CAST(saddr
, optval
, struct sctp_getaddresses
, *optsize
);
2102 SCTP_FIND_STCB(inp
, stcb
, saddr
->sget_assoc_id
);
2104 sas
= (struct sockaddr_storage
*)&saddr
->addr
[0];
2105 limit
= *optsize
- sizeof(sctp_assoc_t
);
2106 actual
= sctp_fill_up_addresses(inp
, stcb
, limit
, sas
);
2108 SCTP_TCB_UNLOCK(stcb
);
2110 *optsize
= sizeof(struct sockaddr_storage
) + actual
;
2113 case SCTP_PEER_ADDR_PARAMS
:
2115 struct sctp_paddrparams
*paddrp
;
2116 struct sctp_nets
*net
;
2118 SCTP_CHECK_AND_CAST(paddrp
, optval
, struct sctp_paddrparams
, *optsize
);
2119 SCTP_FIND_STCB(inp
, stcb
, paddrp
->spp_assoc_id
);
2123 net
= sctp_findnet(stcb
, (struct sockaddr
*)&paddrp
->spp_address
);
2126 * We increment here since
2127 * sctp_findassociation_ep_addr() wil do a
2128 * decrement if it finds the stcb as long as
2129 * the locked tcb (last argument) is NOT a
2132 SCTP_INP_INCR_REF(inp
);
2133 stcb
= sctp_findassociation_ep_addr(&inp
, (struct sockaddr
*)&paddrp
->spp_address
, &net
, NULL
, NULL
);
2135 SCTP_INP_DECR_REF(inp
);
2138 if (stcb
&& (net
== NULL
)) {
2139 struct sockaddr
*sa
;
2141 sa
= (struct sockaddr
*)&paddrp
->spp_address
;
2142 if (sa
->sa_family
== AF_INET
) {
2143 struct sockaddr_in
*sin
;
2145 sin
= (struct sockaddr_in
*)sa
;
2146 if (sin
->sin_addr
.s_addr
) {
2148 SCTP_TCB_UNLOCK(stcb
);
2149 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, error
);
2152 } else if (sa
->sa_family
== AF_INET6
) {
2153 struct sockaddr_in6
*sin6
;
2155 sin6
= (struct sockaddr_in6
*)sa
;
2156 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6
->sin6_addr
)) {
2158 SCTP_TCB_UNLOCK(stcb
);
2159 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, error
);
2163 error
= EAFNOSUPPORT
;
2164 SCTP_TCB_UNLOCK(stcb
);
2165 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, error
);
2170 /* Applys to the specific association */
2171 paddrp
->spp_flags
= 0;
2175 if (inp
->sctp_flags
& SCTP_PCB_FLAGS_BOUND_V6
) {
2176 ovh
= SCTP_MED_OVERHEAD
;
2178 ovh
= SCTP_MED_V4_OVERHEAD
;
2182 paddrp
->spp_pathmaxrxt
= net
->failure_threshold
;
2183 paddrp
->spp_pathmtu
= net
->mtu
- ovh
;
2184 /* get flags for HB */
2185 if (net
->dest_state
& SCTP_ADDR_NOHB
)
2186 paddrp
->spp_flags
|= SPP_HB_DISABLE
;
2188 paddrp
->spp_flags
|= SPP_HB_ENABLE
;
2189 /* get flags for PMTU */
2190 if (SCTP_OS_TIMER_PENDING(&net
->pmtu_timer
.timer
)) {
2191 paddrp
->spp_flags
|= SPP_PMTUD_ENABLE
;
2193 paddrp
->spp_flags
|= SPP_PMTUD_DISABLE
;
2196 if (net
->ro
._l_addr
.sin
.sin_family
== AF_INET
) {
2197 paddrp
->spp_ipv4_tos
= net
->tos_flowlabel
& 0x000000fc;
2198 paddrp
->spp_flags
|= SPP_IPV4_TOS
;
2202 if (net
->ro
._l_addr
.sin6
.sin6_family
== AF_INET6
) {
2203 paddrp
->spp_ipv6_flowlabel
= net
->tos_flowlabel
;
2204 paddrp
->spp_flags
|= SPP_IPV6_FLOWLABEL
;
2209 * No destination so return default
2214 paddrp
->spp_pathmaxrxt
= stcb
->asoc
.def_net_failure
;
2215 paddrp
->spp_pathmtu
= sctp_get_frag_point(stcb
, &stcb
->asoc
);
2217 paddrp
->spp_ipv4_tos
= stcb
->asoc
.default_tos
& 0x000000fc;
2218 paddrp
->spp_flags
|= SPP_IPV4_TOS
;
2221 paddrp
->spp_ipv6_flowlabel
= stcb
->asoc
.default_flowlabel
;
2222 paddrp
->spp_flags
|= SPP_IPV6_FLOWLABEL
;
2224 /* default settings should be these */
2225 if (stcb
->asoc
.hb_is_disabled
== 0) {
2226 paddrp
->spp_flags
|= SPP_HB_ENABLE
;
2228 paddrp
->spp_flags
|= SPP_HB_DISABLE
;
2230 TAILQ_FOREACH(net
, &stcb
->asoc
.nets
, sctp_next
) {
2231 if (SCTP_OS_TIMER_PENDING(&net
->pmtu_timer
.timer
)) {
2236 paddrp
->spp_flags
|= SPP_PMTUD_ENABLE
;
2239 paddrp
->spp_hbinterval
= stcb
->asoc
.heart_beat_delay
;
2240 paddrp
->spp_assoc_id
= sctp_get_associd(stcb
);
2241 SCTP_TCB_UNLOCK(stcb
);
2243 /* Use endpoint defaults */
2244 SCTP_INP_RLOCK(inp
);
2245 paddrp
->spp_pathmaxrxt
= inp
->sctp_ep
.def_net_failure
;
2246 paddrp
->spp_hbinterval
= TICKS_TO_MSEC(inp
->sctp_ep
.sctp_timeoutticks
[SCTP_TIMER_HEARTBEAT
]);
2247 paddrp
->spp_assoc_id
= (sctp_assoc_t
) 0;
2248 /* get inp's default */
2250 paddrp
->spp_ipv4_tos
= inp
->ip_inp
.inp
.inp_ip_tos
;
2251 paddrp
->spp_flags
|= SPP_IPV4_TOS
;
2254 if (inp
->sctp_flags
& SCTP_PCB_FLAGS_BOUND_V6
) {
2255 paddrp
->spp_ipv6_flowlabel
= ((struct in6pcb
*)inp
)->in6p_flowinfo
;
2256 paddrp
->spp_flags
|= SPP_IPV6_FLOWLABEL
;
2259 /* can't return this */
2260 paddrp
->spp_pathmtu
= 0;
2262 /* default behavior, no stcb */
2263 paddrp
->spp_flags
= SPP_PMTUD_ENABLE
;
2265 if (sctp_is_feature_off(inp
, SCTP_PCB_FLAGS_DONOT_HEARTBEAT
)) {
2266 paddrp
->spp_flags
|= SPP_HB_ENABLE
;
2268 paddrp
->spp_flags
|= SPP_HB_DISABLE
;
2270 SCTP_INP_RUNLOCK(inp
);
2272 *optsize
= sizeof(struct sctp_paddrparams
);
2275 case SCTP_GET_PEER_ADDR_INFO
:
2277 struct sctp_paddrinfo
*paddri
;
2278 struct sctp_nets
*net
;
2280 SCTP_CHECK_AND_CAST(paddri
, optval
, struct sctp_paddrinfo
, *optsize
);
2281 SCTP_FIND_STCB(inp
, stcb
, paddri
->spinfo_assoc_id
);
2285 net
= sctp_findnet(stcb
, (struct sockaddr
*)&paddri
->spinfo_address
);
2288 * We increment here since
2289 * sctp_findassociation_ep_addr() wil do a
2290 * decrement if it finds the stcb as long as
2291 * the locked tcb (last argument) is NOT a
2294 SCTP_INP_INCR_REF(inp
);
2295 stcb
= sctp_findassociation_ep_addr(&inp
, (struct sockaddr
*)&paddri
->spinfo_address
, &net
, NULL
, NULL
);
2297 SCTP_INP_DECR_REF(inp
);
2301 if ((stcb
) && (net
)) {
2302 paddri
->spinfo_state
= net
->dest_state
& (SCTP_REACHABLE_MASK
| SCTP_ADDR_NOHB
);
2303 paddri
->spinfo_cwnd
= net
->cwnd
;
2304 paddri
->spinfo_srtt
= ((net
->lastsa
>> 2) + net
->lastsv
) >> 1;
2305 paddri
->spinfo_rto
= net
->RTO
;
2306 paddri
->spinfo_assoc_id
= sctp_get_associd(stcb
);
2307 SCTP_TCB_UNLOCK(stcb
);
2310 SCTP_TCB_UNLOCK(stcb
);
2312 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, ENOENT
);
2315 *optsize
= sizeof(struct sctp_paddrinfo
);
2318 case SCTP_PCB_STATUS
:
2320 struct sctp_pcbinfo
*spcb
;
2322 SCTP_CHECK_AND_CAST(spcb
, optval
, struct sctp_pcbinfo
, *optsize
);
2323 sctp_fill_pcbinfo(spcb
);
2324 *optsize
= sizeof(struct sctp_pcbinfo
);
2330 struct sctp_nets
*net
;
2331 struct sctp_status
*sstat
;
2333 SCTP_CHECK_AND_CAST(sstat
, optval
, struct sctp_status
, *optsize
);
2334 SCTP_FIND_STCB(inp
, stcb
, sstat
->sstat_assoc_id
);
2337 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, error
);
2342 * I think passing the state is fine since
2343 * sctp_constants.h will be available to the user
2346 sstat
->sstat_state
= stcb
->asoc
.state
;
2347 sstat
->sstat_assoc_id
= sctp_get_associd(stcb
);
2348 sstat
->sstat_rwnd
= stcb
->asoc
.peers_rwnd
;
2349 sstat
->sstat_unackdata
= stcb
->asoc
.sent_queue_cnt
;
2351 * We can't include chunks that have been passed to
2352 * the socket layer. Only things in queue.
2354 sstat
->sstat_penddata
= (stcb
->asoc
.cnt_on_reasm_queue
+
2355 stcb
->asoc
.cnt_on_all_streams
);
2358 sstat
->sstat_instrms
= stcb
->asoc
.streamincnt
;
2359 sstat
->sstat_outstrms
= stcb
->asoc
.streamoutcnt
;
2360 sstat
->sstat_fragmentation_point
= sctp_get_frag_point(stcb
, &stcb
->asoc
);
2361 memcpy(&sstat
->sstat_primary
.spinfo_address
,
2362 &stcb
->asoc
.primary_destination
->ro
._l_addr
,
2363 ((struct sockaddr
*)(&stcb
->asoc
.primary_destination
->ro
._l_addr
))->sa_len
);
2364 net
= stcb
->asoc
.primary_destination
;
2365 ((struct sockaddr_in
*)&sstat
->sstat_primary
.spinfo_address
)->sin_port
= stcb
->rport
;
2367 * Again the user can get info from sctp_constants.h
2368 * for what the state of the network is.
2370 sstat
->sstat_primary
.spinfo_state
= net
->dest_state
& SCTP_REACHABLE_MASK
;
2371 sstat
->sstat_primary
.spinfo_cwnd
= net
->cwnd
;
2372 sstat
->sstat_primary
.spinfo_srtt
= net
->lastsa
;
2373 sstat
->sstat_primary
.spinfo_rto
= net
->RTO
;
2374 sstat
->sstat_primary
.spinfo_mtu
= net
->mtu
;
2375 sstat
->sstat_primary
.spinfo_assoc_id
= sctp_get_associd(stcb
);
2376 SCTP_TCB_UNLOCK(stcb
);
2377 *optsize
= sizeof(*sstat
);
2382 struct sctp_rtoinfo
*srto
;
2384 SCTP_CHECK_AND_CAST(srto
, optval
, struct sctp_rtoinfo
, *optsize
);
2385 SCTP_FIND_STCB(inp
, stcb
, srto
->srto_assoc_id
);
2388 srto
->srto_initial
= stcb
->asoc
.initial_rto
;
2389 srto
->srto_max
= stcb
->asoc
.maxrto
;
2390 srto
->srto_min
= stcb
->asoc
.minrto
;
2391 SCTP_TCB_UNLOCK(stcb
);
2393 SCTP_INP_RLOCK(inp
);
2394 srto
->srto_initial
= inp
->sctp_ep
.initial_rto
;
2395 srto
->srto_max
= inp
->sctp_ep
.sctp_maxrto
;
2396 srto
->srto_min
= inp
->sctp_ep
.sctp_minrto
;
2397 SCTP_INP_RUNLOCK(inp
);
2399 *optsize
= sizeof(*srto
);
2402 case SCTP_ASSOCINFO
:
2404 struct sctp_assocparams
*sasoc
;
2407 SCTP_CHECK_AND_CAST(sasoc
, optval
, struct sctp_assocparams
, *optsize
);
2408 SCTP_FIND_STCB(inp
, stcb
, sasoc
->sasoc_assoc_id
);
2411 oldval
= sasoc
->sasoc_cookie_life
;
2412 sasoc
->sasoc_cookie_life
= TICKS_TO_MSEC(stcb
->asoc
.cookie_life
);
2413 sasoc
->sasoc_asocmaxrxt
= stcb
->asoc
.max_send_times
;
2414 sasoc
->sasoc_number_peer_destinations
= stcb
->asoc
.numnets
;
2415 sasoc
->sasoc_peer_rwnd
= stcb
->asoc
.peers_rwnd
;
2416 sasoc
->sasoc_local_rwnd
= stcb
->asoc
.my_rwnd
;
2417 SCTP_TCB_UNLOCK(stcb
);
2419 SCTP_INP_RLOCK(inp
);
2420 sasoc
->sasoc_cookie_life
= TICKS_TO_MSEC(inp
->sctp_ep
.def_cookie_life
);
2421 sasoc
->sasoc_asocmaxrxt
= inp
->sctp_ep
.max_send_times
;
2422 sasoc
->sasoc_number_peer_destinations
= 0;
2423 sasoc
->sasoc_peer_rwnd
= 0;
2424 sasoc
->sasoc_local_rwnd
= sbspace(&inp
->sctp_socket
->so_rcv
);
2425 SCTP_INP_RUNLOCK(inp
);
2427 *optsize
= sizeof(*sasoc
);
2430 case SCTP_DEFAULT_SEND_PARAM
:
2432 struct sctp_sndrcvinfo
*s_info
;
2434 SCTP_CHECK_AND_CAST(s_info
, optval
, struct sctp_sndrcvinfo
, *optsize
);
2435 SCTP_FIND_STCB(inp
, stcb
, s_info
->sinfo_assoc_id
);
2438 memcpy(s_info
, &stcb
->asoc
.def_send
, sizeof(stcb
->asoc
.def_send
));
2439 SCTP_TCB_UNLOCK(stcb
);
2441 SCTP_INP_RLOCK(inp
);
2442 memcpy(s_info
, &inp
->def_send
, sizeof(inp
->def_send
));
2443 SCTP_INP_RUNLOCK(inp
);
2445 *optsize
= sizeof(*s_info
);
2450 struct sctp_initmsg
*sinit
;
2452 SCTP_CHECK_AND_CAST(sinit
, optval
, struct sctp_initmsg
, *optsize
);
2453 SCTP_INP_RLOCK(inp
);
2454 sinit
->sinit_num_ostreams
= inp
->sctp_ep
.pre_open_stream_count
;
2455 sinit
->sinit_max_instreams
= inp
->sctp_ep
.max_open_streams_intome
;
2456 sinit
->sinit_max_attempts
= inp
->sctp_ep
.max_init_times
;
2457 sinit
->sinit_max_init_timeo
= inp
->sctp_ep
.initial_init_rto_max
;
2458 SCTP_INP_RUNLOCK(inp
);
2459 *optsize
= sizeof(*sinit
);
2462 case SCTP_PRIMARY_ADDR
:
2463 /* we allow a "get" operation on this */
2465 struct sctp_setprim
*ssp
;
2467 SCTP_CHECK_AND_CAST(ssp
, optval
, struct sctp_setprim
, *optsize
);
2468 SCTP_FIND_STCB(inp
, stcb
, ssp
->ssp_assoc_id
);
2471 /* simply copy out the sockaddr_storage... */
2475 if (len
> stcb
->asoc
.primary_destination
->ro
._l_addr
.sa
.sa_len
)
2476 len
= stcb
->asoc
.primary_destination
->ro
._l_addr
.sa
.sa_len
;
2478 memcpy(&ssp
->ssp_addr
,
2479 &stcb
->asoc
.primary_destination
->ro
._l_addr
,
2481 SCTP_TCB_UNLOCK(stcb
);
2483 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, error
);
2486 *optsize
= sizeof(*ssp
);
2490 case SCTP_HMAC_IDENT
:
2492 struct sctp_hmacalgo
*shmac
;
2493 sctp_hmaclist_t
*hmaclist
;
2497 SCTP_CHECK_AND_CAST(shmac
, optval
, struct sctp_hmacalgo
, *optsize
);
2499 SCTP_INP_RLOCK(inp
);
2500 hmaclist
= inp
->sctp_ep
.local_hmacs
;
2501 if (hmaclist
== NULL
) {
2502 /* no HMACs to return */
2503 *optsize
= sizeof(*shmac
);
2504 SCTP_INP_RUNLOCK(inp
);
2507 /* is there room for all of the hmac ids? */
2508 size
= sizeof(*shmac
) + (hmaclist
->num_algo
*
2509 sizeof(shmac
->shmac_idents
[0]));
2510 if ((size_t)(*optsize
) < size
) {
2511 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, error
);
2513 SCTP_INP_RUNLOCK(inp
);
2516 /* copy in the list */
2517 shmac
->shmac_number_of_idents
= hmaclist
->num_algo
;
2518 for (i
= 0; i
< hmaclist
->num_algo
; i
++) {
2519 shmac
->shmac_idents
[i
] = hmaclist
->hmac
[i
];
2521 SCTP_INP_RUNLOCK(inp
);
2525 case SCTP_AUTH_ACTIVE_KEY
:
2527 struct sctp_authkeyid
*scact
;
2529 SCTP_CHECK_AND_CAST(scact
, optval
, struct sctp_authkeyid
, *optsize
);
2530 SCTP_FIND_STCB(inp
, stcb
, scact
->scact_assoc_id
);
2533 /* get the active key on the assoc */
2534 scact
->scact_keynumber
= stcb
->asoc
.authinfo
.assoc_keyid
;
2535 SCTP_TCB_UNLOCK(stcb
);
2537 /* get the endpoint active key */
2538 SCTP_INP_RLOCK(inp
);
2539 scact
->scact_keynumber
= inp
->sctp_ep
.default_keyid
;
2540 SCTP_INP_RUNLOCK(inp
);
2542 *optsize
= sizeof(*scact
);
2545 case SCTP_LOCAL_AUTH_CHUNKS
:
2547 struct sctp_authchunks
*sac
;
2548 sctp_auth_chklist_t
*chklist
= NULL
;
2551 SCTP_CHECK_AND_CAST(sac
, optval
, struct sctp_authchunks
, *optsize
);
2552 SCTP_FIND_STCB(inp
, stcb
, sac
->gauth_assoc_id
);
2555 /* get off the assoc */
2556 chklist
= stcb
->asoc
.local_auth_chunks
;
2557 /* is there enough space? */
2558 size
= sctp_auth_get_chklist_size(chklist
);
2559 if (*optsize
< (sizeof(struct sctp_authchunks
) + size
)) {
2561 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, error
);
2563 /* copy in the chunks */
2564 (void)sctp_serialize_auth_chunks(chklist
, sac
->gauth_chunks
);
2566 SCTP_TCB_UNLOCK(stcb
);
2568 /* get off the endpoint */
2569 SCTP_INP_RLOCK(inp
);
2570 chklist
= inp
->sctp_ep
.local_auth_chunks
;
2571 /* is there enough space? */
2572 size
= sctp_auth_get_chklist_size(chklist
);
2573 if (*optsize
< (sizeof(struct sctp_authchunks
) + size
)) {
2575 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, error
);
2577 /* copy in the chunks */
2578 (void)sctp_serialize_auth_chunks(chklist
, sac
->gauth_chunks
);
2580 SCTP_INP_RUNLOCK(inp
);
2582 *optsize
= sizeof(struct sctp_authchunks
) + size
;
2585 case SCTP_PEER_AUTH_CHUNKS
:
2587 struct sctp_authchunks
*sac
;
2588 sctp_auth_chklist_t
*chklist
= NULL
;
2591 SCTP_CHECK_AND_CAST(sac
, optval
, struct sctp_authchunks
, *optsize
);
2592 SCTP_FIND_STCB(inp
, stcb
, sac
->gauth_assoc_id
);
2595 /* get off the assoc */
2596 chklist
= stcb
->asoc
.peer_auth_chunks
;
2597 /* is there enough space? */
2598 size
= sctp_auth_get_chklist_size(chklist
);
2599 if (*optsize
< (sizeof(struct sctp_authchunks
) + size
)) {
2601 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, error
);
2603 /* copy in the chunks */
2604 (void)sctp_serialize_auth_chunks(chklist
, sac
->gauth_chunks
);
2606 SCTP_TCB_UNLOCK(stcb
);
2608 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, ENOENT
);
2611 *optsize
= sizeof(struct sctp_authchunks
) + size
;
2617 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, ENOPROTOOPT
);
2618 error
= ENOPROTOOPT
;
2621 } /* end switch (sopt->sopt_name) */
2626 sctp_setopt(struct socket
*so
, int optname
, void *optval
, size_t optsize
,
2631 struct sctp_tcb
*stcb
= NULL
;
2632 struct sctp_inpcb
*inp
= NULL
;
2635 if (optval
== NULL
) {
2636 SCTP_PRINTF("optval is NULL\n");
2637 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
2640 inp
= (struct sctp_inpcb
*)so
->so_pcb
;
2642 SCTP_PRINTF("inp is NULL?\n");
2643 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
2646 vrf_id
= inp
->def_vrf_id
;
2651 case SCTP_AUTOCLOSE
:
2652 case SCTP_AUTO_ASCONF
:
2653 case SCTP_EXPLICIT_EOR
:
2654 case SCTP_DISABLE_FRAGMENTS
:
2655 case SCTP_USE_EXT_RCVINFO
:
2656 case SCTP_I_WANT_MAPPED_V4_ADDR
:
2657 /* copy in the option value */
2658 SCTP_CHECK_AND_CAST(mopt
, optval
, uint32_t, optsize
);
2663 case SCTP_DISABLE_FRAGMENTS
:
2664 set_opt
= SCTP_PCB_FLAGS_NO_FRAGMENT
;
2666 case SCTP_AUTO_ASCONF
:
2668 * NOTE: we don't really support this flag
2670 if (inp
->sctp_flags
& SCTP_PCB_FLAGS_BOUNDALL
) {
2671 /* only valid for bound all sockets */
2672 set_opt
= SCTP_PCB_FLAGS_AUTO_ASCONF
;
2674 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
2678 case SCTP_EXPLICIT_EOR
:
2679 set_opt
= SCTP_PCB_FLAGS_EXPLICIT_EOR
;
2681 case SCTP_USE_EXT_RCVINFO
:
2682 set_opt
= SCTP_PCB_FLAGS_EXT_RCVINFO
;
2684 case SCTP_I_WANT_MAPPED_V4_ADDR
:
2685 if (inp
->sctp_flags
& SCTP_PCB_FLAGS_BOUND_V6
) {
2686 set_opt
= SCTP_PCB_FLAGS_NEEDS_MAPPED_V4
;
2688 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
2693 set_opt
= SCTP_PCB_FLAGS_NODELAY
;
2695 case SCTP_AUTOCLOSE
:
2696 if ((inp
->sctp_flags
& SCTP_PCB_FLAGS_TCPTYPE
) ||
2697 (inp
->sctp_flags
& SCTP_PCB_FLAGS_IN_TCPPOOL
)) {
2698 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
2701 set_opt
= SCTP_PCB_FLAGS_AUTOCLOSE
;
2703 * The value is in ticks. Note this does not effect
2704 * old associations, only new ones.
2706 inp
->sctp_ep
.auto_close_time
= SEC_TO_TICKS(*mopt
);
2709 SCTP_INP_WLOCK(inp
);
2711 sctp_feature_on(inp
, set_opt
);
2713 sctp_feature_off(inp
, set_opt
);
2715 SCTP_INP_WUNLOCK(inp
);
2717 case SCTP_REUSE_PORT
:
2719 SCTP_CHECK_AND_CAST(mopt
, optval
, uint32_t, optsize
);
2720 if ((inp
->sctp_flags
& SCTP_PCB_FLAGS_UNBOUND
) == 0) {
2721 /* Can't set it after we are bound */
2725 if ((inp
->sctp_flags
& SCTP_PCB_FLAGS_UDPTYPE
)) {
2726 /* Can't do this for a 1-m socket */
2731 sctp_feature_on(inp
, SCTP_PCB_FLAGS_PORTREUSE
);
2733 sctp_feature_off(inp
, SCTP_PCB_FLAGS_PORTREUSE
);
2736 case SCTP_PARTIAL_DELIVERY_POINT
:
2740 SCTP_CHECK_AND_CAST(value
, optval
, uint32_t, optsize
);
2741 if (*value
> SCTP_SB_LIMIT_RCV(so
)) {
2742 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
2746 inp
->partial_delivery_point
= *value
;
2749 case SCTP_FRAGMENT_INTERLEAVE
:
2750 /* not yet until we re-write sctp_recvmsg() */
2754 SCTP_CHECK_AND_CAST(level
, optval
, uint32_t, optsize
);
2755 if (*level
== SCTP_FRAG_LEVEL_2
) {
2756 sctp_feature_on(inp
, SCTP_PCB_FLAGS_FRAG_INTERLEAVE
);
2757 sctp_feature_on(inp
, SCTP_PCB_FLAGS_INTERLEAVE_STRMS
);
2758 } else if (*level
== SCTP_FRAG_LEVEL_1
) {
2759 sctp_feature_on(inp
, SCTP_PCB_FLAGS_FRAG_INTERLEAVE
);
2760 sctp_feature_off(inp
, SCTP_PCB_FLAGS_INTERLEAVE_STRMS
);
2761 } else if (*level
== SCTP_FRAG_LEVEL_0
) {
2762 sctp_feature_off(inp
, SCTP_PCB_FLAGS_FRAG_INTERLEAVE
);
2763 sctp_feature_off(inp
, SCTP_PCB_FLAGS_INTERLEAVE_STRMS
);
2766 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
2771 case SCTP_CMT_ON_OFF
:
2773 struct sctp_assoc_value
*av
;
2775 SCTP_CHECK_AND_CAST(av
, optval
, struct sctp_assoc_value
, optsize
);
2776 if (SCTP_BASE_SYSCTL(sctp_cmt_on_off
)) {
2777 SCTP_FIND_STCB(inp
, stcb
, av
->assoc_id
);
2779 stcb
->asoc
.sctp_cmt_on_off
= (uint8_t) av
->assoc_value
;
2780 SCTP_TCB_UNLOCK(stcb
);
2782 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, ENOTCONN
);
2786 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, ENOPROTOOPT
);
2787 error
= ENOPROTOOPT
;
2791 /* JRS - Set socket option for pluggable congestion control */
2792 case SCTP_PLUGGABLE_CC
:
2794 struct sctp_assoc_value
*av
;
2796 SCTP_CHECK_AND_CAST(av
, optval
, struct sctp_assoc_value
, optsize
);
2797 SCTP_FIND_STCB(inp
, stcb
, av
->assoc_id
);
2799 switch (av
->assoc_value
) {
2801 * JRS - Standard TCP congestion
2804 case SCTP_CC_RFC2581
:
2806 stcb
->asoc
.congestion_control_module
= SCTP_CC_RFC2581
;
2807 stcb
->asoc
.cc_functions
.sctp_set_initial_cc_param
= &sctp_set_initial_cc_param
;
2808 stcb
->asoc
.cc_functions
.sctp_cwnd_update_after_sack
= &sctp_cwnd_update_after_sack
;
2809 stcb
->asoc
.cc_functions
.sctp_cwnd_update_after_fr
= &sctp_cwnd_update_after_fr
;
2810 stcb
->asoc
.cc_functions
.sctp_cwnd_update_after_timeout
= &sctp_cwnd_update_after_timeout
;
2811 stcb
->asoc
.cc_functions
.sctp_cwnd_update_after_ecn_echo
= &sctp_cwnd_update_after_ecn_echo
;
2812 stcb
->asoc
.cc_functions
.sctp_cwnd_update_after_packet_dropped
= &sctp_cwnd_update_after_packet_dropped
;
2813 stcb
->asoc
.cc_functions
.sctp_cwnd_update_after_output
= &sctp_cwnd_update_after_output
;
2814 stcb
->asoc
.cc_functions
.sctp_cwnd_update_after_fr_timer
= &sctp_cwnd_update_after_fr_timer
;
2815 SCTP_TCB_UNLOCK(stcb
);
2819 * JRS - High Speed TCP congestion
2824 stcb
->asoc
.congestion_control_module
= SCTP_CC_HSTCP
;
2825 stcb
->asoc
.cc_functions
.sctp_set_initial_cc_param
= &sctp_set_initial_cc_param
;
2826 stcb
->asoc
.cc_functions
.sctp_cwnd_update_after_sack
= &sctp_hs_cwnd_update_after_sack
;
2827 stcb
->asoc
.cc_functions
.sctp_cwnd_update_after_fr
= &sctp_hs_cwnd_update_after_fr
;
2828 stcb
->asoc
.cc_functions
.sctp_cwnd_update_after_timeout
= &sctp_cwnd_update_after_timeout
;
2829 stcb
->asoc
.cc_functions
.sctp_cwnd_update_after_ecn_echo
= &sctp_cwnd_update_after_ecn_echo
;
2830 stcb
->asoc
.cc_functions
.sctp_cwnd_update_after_packet_dropped
= &sctp_cwnd_update_after_packet_dropped
;
2831 stcb
->asoc
.cc_functions
.sctp_cwnd_update_after_output
= &sctp_cwnd_update_after_output
;
2832 stcb
->asoc
.cc_functions
.sctp_cwnd_update_after_fr_timer
= &sctp_cwnd_update_after_fr_timer
;
2833 SCTP_TCB_UNLOCK(stcb
);
2836 /* JRS - HTCP congestion control */
2839 stcb
->asoc
.congestion_control_module
= SCTP_CC_HTCP
;
2840 stcb
->asoc
.cc_functions
.sctp_set_initial_cc_param
= &sctp_htcp_set_initial_cc_param
;
2841 stcb
->asoc
.cc_functions
.sctp_cwnd_update_after_sack
= &sctp_htcp_cwnd_update_after_sack
;
2842 stcb
->asoc
.cc_functions
.sctp_cwnd_update_after_fr
= &sctp_htcp_cwnd_update_after_fr
;
2843 stcb
->asoc
.cc_functions
.sctp_cwnd_update_after_timeout
= &sctp_htcp_cwnd_update_after_timeout
;
2844 stcb
->asoc
.cc_functions
.sctp_cwnd_update_after_ecn_echo
= &sctp_htcp_cwnd_update_after_ecn_echo
;
2845 stcb
->asoc
.cc_functions
.sctp_cwnd_update_after_packet_dropped
= &sctp_cwnd_update_after_packet_dropped
;
2846 stcb
->asoc
.cc_functions
.sctp_cwnd_update_after_output
= &sctp_cwnd_update_after_output
;
2847 stcb
->asoc
.cc_functions
.sctp_cwnd_update_after_fr_timer
= &sctp_htcp_cwnd_update_after_fr_timer
;
2848 SCTP_TCB_UNLOCK(stcb
);
2852 * JRS - All other values are
2857 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
2859 SCTP_TCB_UNLOCK(stcb
);
2864 switch (av
->assoc_value
) {
2865 case SCTP_CC_RFC2581
:
2868 inp
->sctp_ep
.sctp_default_cc_module
= av
->assoc_value
;
2871 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
2878 case SCTP_CLR_STAT_LOG
:
2879 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EOPNOTSUPP
);
2884 struct sctp_assoc_value
*av
;
2886 SCTP_CHECK_AND_CAST(av
, optval
, struct sctp_assoc_value
, optsize
);
2887 SCTP_FIND_STCB(inp
, stcb
, av
->assoc_id
);
2890 stcb
->asoc
.context
= av
->assoc_value
;
2891 SCTP_TCB_UNLOCK(stcb
);
2893 SCTP_INP_WLOCK(inp
);
2894 inp
->sctp_context
= av
->assoc_value
;
2895 SCTP_INP_WUNLOCK(inp
);
2901 uint32_t *default_vrfid
;
2903 SCTP_CHECK_AND_CAST(default_vrfid
, optval
, uint32_t, optsize
);
2904 if (*default_vrfid
> SCTP_MAX_VRF_ID
) {
2905 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
2909 inp
->def_vrf_id
= *default_vrfid
;
2912 case SCTP_DEL_VRF_ID
:
2914 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EOPNOTSUPP
);
2918 case SCTP_ADD_VRF_ID
:
2920 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EOPNOTSUPP
);
2924 case SCTP_DELAYED_SACK
:
2926 struct sctp_sack_info
*sack
;
2928 SCTP_CHECK_AND_CAST(sack
, optval
, struct sctp_sack_info
, optsize
);
2929 SCTP_FIND_STCB(inp
, stcb
, sack
->sack_assoc_id
);
2930 if (sack
->sack_delay
) {
2931 if (sack
->sack_delay
> SCTP_MAX_SACK_DELAY
)
2932 sack
->sack_delay
= SCTP_MAX_SACK_DELAY
;
2935 if (sack
->sack_delay
) {
2936 if (MSEC_TO_TICKS(sack
->sack_delay
) < 1) {
2937 sack
->sack_delay
= TICKS_TO_MSEC(1);
2939 stcb
->asoc
.delayed_ack
= sack
->sack_delay
;
2941 if (sack
->sack_freq
) {
2942 stcb
->asoc
.sack_freq
= sack
->sack_freq
;
2944 SCTP_TCB_UNLOCK(stcb
);
2946 SCTP_INP_WLOCK(inp
);
2947 if (sack
->sack_delay
) {
2948 if (MSEC_TO_TICKS(sack
->sack_delay
) < 1) {
2949 sack
->sack_delay
= TICKS_TO_MSEC(1);
2951 inp
->sctp_ep
.sctp_timeoutticks
[SCTP_TIMER_RECV
] = MSEC_TO_TICKS(sack
->sack_delay
);
2953 if (sack
->sack_freq
) {
2954 inp
->sctp_ep
.sctp_sack_freq
= sack
->sack_freq
;
2956 SCTP_INP_WUNLOCK(inp
);
2960 case SCTP_AUTH_CHUNK
:
2962 struct sctp_authchunk
*sauth
;
2964 SCTP_CHECK_AND_CAST(sauth
, optval
, struct sctp_authchunk
, optsize
);
2966 SCTP_INP_WLOCK(inp
);
2967 if (sctp_auth_add_chunk(sauth
->sauth_chunk
, inp
->sctp_ep
.local_auth_chunks
)) {
2968 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
2971 SCTP_INP_WUNLOCK(inp
);
2976 struct sctp_authkey
*sca
;
2977 struct sctp_keyhead
*shared_keys
;
2978 sctp_sharedkey_t
*shared_key
;
2979 sctp_key_t
*key
= NULL
;
2982 SCTP_CHECK_AND_CAST(sca
, optval
, struct sctp_authkey
, optsize
);
2983 SCTP_FIND_STCB(inp
, stcb
, sca
->sca_assoc_id
);
2984 size
= optsize
- sizeof(*sca
);
2987 /* set it on the assoc */
2988 shared_keys
= &stcb
->asoc
.shared_keys
;
2989 /* clear the cached keys for this key id */
2990 sctp_clear_cachedkeys(stcb
, sca
->sca_keynumber
);
2992 * create the new shared key and
2996 key
= sctp_set_key(sca
->sca_key
, (uint32_t) size
);
2998 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, ENOMEM
);
3000 SCTP_TCB_UNLOCK(stcb
);
3004 shared_key
= sctp_alloc_sharedkey();
3005 if (shared_key
== NULL
) {
3007 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, ENOMEM
);
3009 SCTP_TCB_UNLOCK(stcb
);
3012 shared_key
->key
= key
;
3013 shared_key
->keyid
= sca
->sca_keynumber
;
3014 sctp_insert_sharedkey(shared_keys
, shared_key
);
3015 SCTP_TCB_UNLOCK(stcb
);
3017 /* set it on the endpoint */
3018 SCTP_INP_WLOCK(inp
);
3019 shared_keys
= &inp
->sctp_ep
.shared_keys
;
3021 * clear the cached keys on all assocs for
3024 sctp_clear_cachedkeys_ep(inp
, sca
->sca_keynumber
);
3026 * create the new shared key and
3030 key
= sctp_set_key(sca
->sca_key
, (uint32_t) size
);
3032 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, ENOMEM
);
3034 SCTP_INP_WUNLOCK(inp
);
3038 shared_key
= sctp_alloc_sharedkey();
3039 if (shared_key
== NULL
) {
3041 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, ENOMEM
);
3043 SCTP_INP_WUNLOCK(inp
);
3046 shared_key
->key
= key
;
3047 shared_key
->keyid
= sca
->sca_keynumber
;
3048 sctp_insert_sharedkey(shared_keys
, shared_key
);
3049 SCTP_INP_WUNLOCK(inp
);
3053 case SCTP_HMAC_IDENT
:
3055 struct sctp_hmacalgo
*shmac
;
3056 sctp_hmaclist_t
*hmaclist
;
3062 SCTP_CHECK_AND_CAST(shmac
, optval
, struct sctp_hmacalgo
, optsize
);
3063 if (optsize
< sizeof(struct sctp_hmacalgo
) + shmac
->shmac_number_of_idents
* sizeof(uint16_t)) {
3064 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
3068 hmaclist
= sctp_alloc_hmaclist(shmac
->shmac_number_of_idents
);
3069 if (hmaclist
== NULL
) {
3070 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, ENOMEM
);
3074 for (i
= 0; i
< shmac
->shmac_number_of_idents
; i
++) {
3075 hmacid
= shmac
->shmac_idents
[i
];
3076 if (sctp_auth_add_hmacid(hmaclist
, hmacid
)) {
3077 /* invalid HMACs were found */ ;
3078 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
3080 sctp_free_hmaclist(hmaclist
);
3081 goto sctp_set_hmac_done
;
3085 for (i
= 0; i
< hmaclist
->num_algo
; i
++) {
3086 if (hmaclist
->hmac
[i
] == SCTP_AUTH_HMAC_ID_SHA1
) {
3087 /* already in list */
3092 sctp_free_hmaclist(hmaclist
);
3093 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
3097 /* set it on the endpoint */
3098 SCTP_INP_WLOCK(inp
);
3099 if (inp
->sctp_ep
.local_hmacs
)
3100 sctp_free_hmaclist(inp
->sctp_ep
.local_hmacs
);
3101 inp
->sctp_ep
.local_hmacs
= hmaclist
;
3102 SCTP_INP_WUNLOCK(inp
);
3106 case SCTP_AUTH_ACTIVE_KEY
:
3108 struct sctp_authkeyid
*scact
;
3110 SCTP_CHECK_AND_CAST(scact
, optval
, struct sctp_authkeyid
, optsize
);
3111 SCTP_FIND_STCB(inp
, stcb
, scact
->scact_assoc_id
);
3113 /* set the active key on the right place */
3115 /* set the active key on the assoc */
3116 if (sctp_auth_setactivekey(stcb
, scact
->scact_keynumber
)) {
3117 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
3120 SCTP_TCB_UNLOCK(stcb
);
3122 /* set the active key on the endpoint */
3123 SCTP_INP_WLOCK(inp
);
3124 if (sctp_auth_setactivekey_ep(inp
, scact
->scact_keynumber
)) {
3125 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
3128 SCTP_INP_WUNLOCK(inp
);
3132 case SCTP_AUTH_DELETE_KEY
:
3134 struct sctp_authkeyid
*scdel
;
3136 SCTP_CHECK_AND_CAST(scdel
, optval
, struct sctp_authkeyid
, optsize
);
3137 SCTP_FIND_STCB(inp
, stcb
, scdel
->scact_assoc_id
);
3139 /* delete the key from the right place */
3141 if (sctp_delete_sharedkey(stcb
, scdel
->scact_keynumber
)) {
3142 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
3145 SCTP_TCB_UNLOCK(stcb
);
3147 SCTP_INP_WLOCK(inp
);
3148 if (sctp_delete_sharedkey_ep(inp
, scdel
->scact_keynumber
)) {
3149 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
3152 SCTP_INP_WUNLOCK(inp
);
3157 case SCTP_RESET_STREAMS
:
3159 struct sctp_stream_reset
*strrst
;
3160 uint8_t send_in
= 0, send_tsn
= 0, send_out
= 0;
3163 SCTP_CHECK_AND_CAST(strrst
, optval
, struct sctp_stream_reset
, optsize
);
3164 SCTP_FIND_STCB(inp
, stcb
, strrst
->strrst_assoc_id
);
3167 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, ENOENT
);
3171 if (stcb
->asoc
.peer_supports_strreset
== 0) {
3173 * Peer does not support it, we return
3174 * protocol not supported since this is true
3175 * for this feature and this peer, not the
3176 * socket request in general.
3178 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EPROTONOSUPPORT
);
3179 error
= EPROTONOSUPPORT
;
3180 SCTP_TCB_UNLOCK(stcb
);
3183 if (stcb
->asoc
.stream_reset_outstanding
) {
3184 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EALREADY
);
3186 SCTP_TCB_UNLOCK(stcb
);
3189 if (strrst
->strrst_flags
== SCTP_RESET_LOCAL_RECV
) {
3191 } else if (strrst
->strrst_flags
== SCTP_RESET_LOCAL_SEND
) {
3193 } else if (strrst
->strrst_flags
== SCTP_RESET_BOTH
) {
3196 } else if (strrst
->strrst_flags
== SCTP_RESET_TSN
) {
3199 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
3201 SCTP_TCB_UNLOCK(stcb
);
3204 for (i
= 0; i
< strrst
->strrst_num_streams
; i
++) {
3207 (strrst
->strrst_list
[i
] > stcb
->asoc
.streamincnt
)) {
3208 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
3213 (strrst
->strrst_list
[i
] > stcb
->asoc
.streamoutcnt
)) {
3214 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
3221 SCTP_TCB_UNLOCK(stcb
);
3224 error
= sctp_send_str_reset_req(stcb
, strrst
->strrst_num_streams
,
3225 strrst
->strrst_list
,
3226 send_out
, (stcb
->asoc
.str_reset_seq_in
- 3),
3229 sctp_chunk_output(inp
, stcb
, SCTP_OUTPUT_FROM_STRRST_REQ
, SCTP_SO_LOCKED
);
3230 SCTP_TCB_UNLOCK(stcb
);
3234 case SCTP_CONNECT_X
:
3235 if (optsize
< (sizeof(int) + sizeof(struct sockaddr_in
))) {
3236 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
3240 error
= sctp_do_connect_x(so
, inp
, optval
, optsize
, p
, 0);
3243 case SCTP_CONNECT_X_DELAYED
:
3244 if (optsize
< (sizeof(int) + sizeof(struct sockaddr_in
))) {
3245 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
3249 error
= sctp_do_connect_x(so
, inp
, optval
, optsize
, p
, 1);
3252 case SCTP_CONNECT_X_COMPLETE
:
3254 struct sockaddr
*sa
;
3255 struct sctp_nets
*net
;
3257 /* FIXME MT: check correct? */
3258 SCTP_CHECK_AND_CAST(sa
, optval
, struct sockaddr
, optsize
);
3261 if (inp
->sctp_flags
& SCTP_PCB_FLAGS_CONNECTED
) {
3262 SCTP_INP_RLOCK(inp
);
3263 stcb
= LIST_FIRST(&inp
->sctp_asoc_list
);
3265 SCTP_TCB_LOCK(stcb
);
3266 net
= sctp_findnet(stcb
, sa
);
3268 SCTP_INP_RUNLOCK(inp
);
3271 * We increment here since
3272 * sctp_findassociation_ep_addr() wil do a
3273 * decrement if it finds the stcb as long as
3274 * the locked tcb (last argument) is NOT a
3277 SCTP_INP_INCR_REF(inp
);
3278 stcb
= sctp_findassociation_ep_addr(&inp
, sa
, &net
, NULL
, NULL
);
3280 SCTP_INP_DECR_REF(inp
);
3285 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, ENOENT
);
3289 if (stcb
->asoc
.delayed_connection
== 1) {
3290 stcb
->asoc
.delayed_connection
= 0;
3291 (void)SCTP_GETTIME_TIMEVAL(&stcb
->asoc
.time_entered
);
3292 sctp_timer_stop(SCTP_TIMER_TYPE_INIT
, inp
, stcb
,
3293 stcb
->asoc
.primary_destination
,
3294 SCTP_FROM_SCTP_USRREQ
+ SCTP_LOC_9
);
3295 sctp_send_initiate(inp
, stcb
, SCTP_SO_LOCKED
);
3298 * already expired or did not use delayed
3301 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EALREADY
);
3304 SCTP_TCB_UNLOCK(stcb
);
3307 case SCTP_MAX_BURST
:
3311 SCTP_CHECK_AND_CAST(burst
, optval
, uint8_t, optsize
);
3313 SCTP_INP_WLOCK(inp
);
3315 inp
->sctp_ep
.max_burst
= *burst
;
3317 SCTP_INP_WUNLOCK(inp
);
3322 struct sctp_assoc_value
*av
;
3325 SCTP_CHECK_AND_CAST(av
, optval
, struct sctp_assoc_value
, optsize
);
3326 SCTP_FIND_STCB(inp
, stcb
, av
->assoc_id
);
3328 if (inp
->sctp_flags
& SCTP_PCB_FLAGS_BOUND_V6
) {
3329 ovh
= SCTP_MED_OVERHEAD
;
3331 ovh
= SCTP_MED_V4_OVERHEAD
;
3334 if (av
->assoc_value
) {
3335 stcb
->asoc
.sctp_frag_point
= (av
->assoc_value
+ ovh
);
3337 stcb
->asoc
.sctp_frag_point
= SCTP_DEFAULT_MAXSEGMENT
;
3339 SCTP_TCB_UNLOCK(stcb
);
3341 SCTP_INP_WLOCK(inp
);
3343 * FIXME MT: I think this is not in tune
3346 if (av
->assoc_value
) {
3347 inp
->sctp_frag_point
= (av
->assoc_value
+ ovh
);
3349 inp
->sctp_frag_point
= SCTP_DEFAULT_MAXSEGMENT
;
3351 SCTP_INP_WUNLOCK(inp
);
3357 struct sctp_event_subscribe
*events
;
3359 SCTP_CHECK_AND_CAST(events
, optval
, struct sctp_event_subscribe
, optsize
);
3361 SCTP_INP_WLOCK(inp
);
3362 if (events
->sctp_data_io_event
) {
3363 sctp_feature_on(inp
, SCTP_PCB_FLAGS_RECVDATAIOEVNT
);
3365 sctp_feature_off(inp
, SCTP_PCB_FLAGS_RECVDATAIOEVNT
);
3368 if (events
->sctp_association_event
) {
3369 sctp_feature_on(inp
, SCTP_PCB_FLAGS_RECVASSOCEVNT
);
3371 sctp_feature_off(inp
, SCTP_PCB_FLAGS_RECVASSOCEVNT
);
3374 if (events
->sctp_address_event
) {
3375 sctp_feature_on(inp
, SCTP_PCB_FLAGS_RECVPADDREVNT
);
3377 sctp_feature_off(inp
, SCTP_PCB_FLAGS_RECVPADDREVNT
);
3380 if (events
->sctp_send_failure_event
) {
3381 sctp_feature_on(inp
, SCTP_PCB_FLAGS_RECVSENDFAILEVNT
);
3383 sctp_feature_off(inp
, SCTP_PCB_FLAGS_RECVSENDFAILEVNT
);
3386 if (events
->sctp_peer_error_event
) {
3387 sctp_feature_on(inp
, SCTP_PCB_FLAGS_RECVPEERERR
);
3389 sctp_feature_off(inp
, SCTP_PCB_FLAGS_RECVPEERERR
);
3392 if (events
->sctp_shutdown_event
) {
3393 sctp_feature_on(inp
, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT
);
3395 sctp_feature_off(inp
, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT
);
3398 if (events
->sctp_partial_delivery_event
) {
3399 sctp_feature_on(inp
, SCTP_PCB_FLAGS_PDAPIEVNT
);
3401 sctp_feature_off(inp
, SCTP_PCB_FLAGS_PDAPIEVNT
);
3404 if (events
->sctp_adaptation_layer_event
) {
3405 sctp_feature_on(inp
, SCTP_PCB_FLAGS_ADAPTATIONEVNT
);
3407 sctp_feature_off(inp
, SCTP_PCB_FLAGS_ADAPTATIONEVNT
);
3410 if (events
->sctp_authentication_event
) {
3411 sctp_feature_on(inp
, SCTP_PCB_FLAGS_AUTHEVNT
);
3413 sctp_feature_off(inp
, SCTP_PCB_FLAGS_AUTHEVNT
);
3416 if (events
->sctp_stream_reset_events
) {
3417 sctp_feature_on(inp
, SCTP_PCB_FLAGS_STREAM_RESETEVNT
);
3419 sctp_feature_off(inp
, SCTP_PCB_FLAGS_STREAM_RESETEVNT
);
3421 SCTP_INP_WUNLOCK(inp
);
3425 case SCTP_ADAPTATION_LAYER
:
3427 struct sctp_setadaptation
*adap_bits
;
3429 SCTP_CHECK_AND_CAST(adap_bits
, optval
, struct sctp_setadaptation
, optsize
);
3430 SCTP_INP_WLOCK(inp
);
3431 inp
->sctp_ep
.adaptation_layer_indicator
= adap_bits
->ssb_adaptation_ind
;
3432 SCTP_INP_WUNLOCK(inp
);
3436 case SCTP_SET_INITIAL_DBG_SEQ
:
3440 SCTP_CHECK_AND_CAST(vvv
, optval
, uint32_t, optsize
);
3441 SCTP_INP_WLOCK(inp
);
3442 inp
->sctp_ep
.initial_sequence_debug
= *vvv
;
3443 SCTP_INP_WUNLOCK(inp
);
3447 case SCTP_DEFAULT_SEND_PARAM
:
3449 struct sctp_sndrcvinfo
*s_info
;
3451 SCTP_CHECK_AND_CAST(s_info
, optval
, struct sctp_sndrcvinfo
, optsize
);
3452 SCTP_FIND_STCB(inp
, stcb
, s_info
->sinfo_assoc_id
);
3455 if (s_info
->sinfo_stream
<= stcb
->asoc
.streamoutcnt
) {
3456 memcpy(&stcb
->asoc
.def_send
, s_info
, min(optsize
, sizeof(stcb
->asoc
.def_send
)));
3458 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
3461 SCTP_TCB_UNLOCK(stcb
);
3463 SCTP_INP_WLOCK(inp
);
3464 memcpy(&inp
->def_send
, s_info
, min(optsize
, sizeof(inp
->def_send
)));
3465 SCTP_INP_WUNLOCK(inp
);
3469 case SCTP_PEER_ADDR_PARAMS
:
3470 /* Applys to the specific association */
3472 struct sctp_paddrparams
*paddrp
;
3473 struct sctp_nets
*net
;
3475 SCTP_CHECK_AND_CAST(paddrp
, optval
, struct sctp_paddrparams
, optsize
);
3476 SCTP_FIND_STCB(inp
, stcb
, paddrp
->spp_assoc_id
);
3479 net
= sctp_findnet(stcb
, (struct sockaddr
*)&paddrp
->spp_address
);
3482 * We increment here since
3483 * sctp_findassociation_ep_addr() wil do a
3484 * decrement if it finds the stcb as long as
3485 * the locked tcb (last argument) is NOT a
3488 SCTP_INP_INCR_REF(inp
);
3489 stcb
= sctp_findassociation_ep_addr(&inp
,
3490 (struct sockaddr
*)&paddrp
->spp_address
,
3493 SCTP_INP_DECR_REF(inp
);
3496 if (stcb
&& (net
== NULL
)) {
3497 struct sockaddr
*sa
;
3499 sa
= (struct sockaddr
*)&paddrp
->spp_address
;
3500 if (sa
->sa_family
== AF_INET
) {
3501 struct sockaddr_in
*sin
;
3503 sin
= (struct sockaddr_in
*)sa
;
3504 if (sin
->sin_addr
.s_addr
) {
3505 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
3506 SCTP_TCB_UNLOCK(stcb
);
3510 } else if (sa
->sa_family
== AF_INET6
) {
3511 struct sockaddr_in6
*sin6
;
3513 sin6
= (struct sockaddr_in6
*)sa
;
3514 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6
->sin6_addr
)) {
3515 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
3516 SCTP_TCB_UNLOCK(stcb
);
3521 error
= EAFNOSUPPORT
;
3522 SCTP_TCB_UNLOCK(stcb
);
3523 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, error
);
3528 if ((paddrp
->spp_flags
& SPP_HB_ENABLE
) && (paddrp
->spp_flags
& SPP_HB_DISABLE
)) {
3530 SCTP_TCB_UNLOCK(stcb
);
3531 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
3534 if ((paddrp
->spp_flags
& SPP_PMTUD_ENABLE
) && (paddrp
->spp_flags
& SPP_PMTUD_DISABLE
)) {
3536 SCTP_TCB_UNLOCK(stcb
);
3537 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
3541 /************************TCB SPECIFIC SET ******************/
3543 * do we change the timer for HB, we run
3548 if (stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_BOUND_V6
) {
3549 ovh
= SCTP_MED_OVERHEAD
;
3551 ovh
= SCTP_MED_V4_OVERHEAD
;
3554 if (paddrp
->spp_hbinterval
)
3555 stcb
->asoc
.heart_beat_delay
= paddrp
->spp_hbinterval
;
3556 else if (paddrp
->spp_flags
& SPP_HB_TIME_IS_ZERO
)
3557 stcb
->asoc
.heart_beat_delay
= 0;
3559 /* network sets ? */
3561 /************************NET SPECIFIC SET ******************/
3562 if (paddrp
->spp_flags
& SPP_HB_DEMAND
) {
3564 if (sctp_send_hb(stcb
, 1, net
) < 0) {
3565 /* asoc destroyed */
3566 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
3571 if (paddrp
->spp_flags
& SPP_HB_DISABLE
) {
3572 net
->dest_state
|= SCTP_ADDR_NOHB
;
3574 if (paddrp
->spp_flags
& SPP_HB_ENABLE
) {
3575 net
->dest_state
&= ~SCTP_ADDR_NOHB
;
3577 if ((paddrp
->spp_flags
& SPP_PMTUD_DISABLE
) && (paddrp
->spp_pathmtu
>= SCTP_SMALLEST_PMTU
)) {
3578 if (SCTP_OS_TIMER_PENDING(&net
->pmtu_timer
.timer
)) {
3579 sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE
, inp
, stcb
, net
,
3580 SCTP_FROM_SCTP_USRREQ
+ SCTP_LOC_10
);
3582 if (paddrp
->spp_pathmtu
> SCTP_DEFAULT_MINSEGMENT
) {
3583 net
->mtu
= paddrp
->spp_pathmtu
+ ovh
;
3584 if (net
->mtu
< stcb
->asoc
.smallest_mtu
) {
3585 #ifdef SCTP_PRINT_FOR_B_AND_M
3586 SCTP_PRINTF("SCTP_PMTU_DISABLE calls sctp_pathmtu_adjustment:%d\n",
3589 sctp_pathmtu_adjustment(inp
, stcb
, net
, net
->mtu
);
3593 if (paddrp
->spp_flags
& SPP_PMTUD_ENABLE
) {
3594 if (SCTP_OS_TIMER_PENDING(&net
->pmtu_timer
.timer
)) {
3595 sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE
, inp
, stcb
, net
);
3598 if (paddrp
->spp_pathmaxrxt
)
3599 net
->failure_threshold
= paddrp
->spp_pathmaxrxt
;
3601 if (paddrp
->spp_flags
& SPP_IPV4_TOS
) {
3602 if (net
->ro
._l_addr
.sin
.sin_family
== AF_INET
) {
3603 net
->tos_flowlabel
= paddrp
->spp_ipv4_tos
& 0x000000fc;
3608 if (paddrp
->spp_flags
& SPP_IPV6_FLOWLABEL
) {
3609 if (net
->ro
._l_addr
.sin6
.sin6_family
== AF_INET6
) {
3610 net
->tos_flowlabel
= paddrp
->spp_ipv6_flowlabel
;
3615 /************************ASSOC ONLY -- NO NET SPECIFIC SET ******************/
3616 if (paddrp
->spp_pathmaxrxt
)
3617 stcb
->asoc
.def_net_failure
= paddrp
->spp_pathmaxrxt
;
3619 if (paddrp
->spp_flags
& SPP_HB_ENABLE
) {
3620 /* Turn back on the timer */
3621 stcb
->asoc
.hb_is_disabled
= 0;
3622 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT
, inp
, stcb
, net
);
3624 if ((paddrp
->spp_flags
& SPP_PMTUD_DISABLE
) && (paddrp
->spp_pathmtu
>= SCTP_SMALLEST_PMTU
)) {
3625 TAILQ_FOREACH(net
, &stcb
->asoc
.nets
, sctp_next
) {
3626 if (SCTP_OS_TIMER_PENDING(&net
->pmtu_timer
.timer
)) {
3627 sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE
, inp
, stcb
, net
,
3628 SCTP_FROM_SCTP_USRREQ
+ SCTP_LOC_10
);
3630 if (paddrp
->spp_pathmtu
> SCTP_DEFAULT_MINSEGMENT
) {
3631 net
->mtu
= paddrp
->spp_pathmtu
+ ovh
;
3632 if (net
->mtu
< stcb
->asoc
.smallest_mtu
) {
3633 #ifdef SCTP_PRINT_FOR_B_AND_M
3634 SCTP_PRINTF("SCTP_PMTU_DISABLE calls sctp_pathmtu_adjustment:%d\n",
3637 sctp_pathmtu_adjustment(inp
, stcb
, net
, net
->mtu
);
3642 if (paddrp
->spp_flags
& SPP_PMTUD_ENABLE
) {
3643 TAILQ_FOREACH(net
, &stcb
->asoc
.nets
, sctp_next
) {
3644 if (SCTP_OS_TIMER_PENDING(&net
->pmtu_timer
.timer
)) {
3645 sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE
, inp
, stcb
, net
);
3649 if (paddrp
->spp_flags
& SPP_HB_DISABLE
) {
3650 int cnt_of_unconf
= 0;
3651 struct sctp_nets
*lnet
;
3653 stcb
->asoc
.hb_is_disabled
= 1;
3654 TAILQ_FOREACH(lnet
, &stcb
->asoc
.nets
, sctp_next
) {
3655 if (lnet
->dest_state
& SCTP_ADDR_UNCONFIRMED
) {
3660 * stop the timer ONLY if we
3661 * have no unconfirmed
3664 if (cnt_of_unconf
== 0) {
3665 TAILQ_FOREACH(net
, &stcb
->asoc
.nets
, sctp_next
) {
3666 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT
, inp
, stcb
, net
,
3667 SCTP_FROM_SCTP_USRREQ
+ SCTP_LOC_11
);
3671 if (paddrp
->spp_flags
& SPP_HB_ENABLE
) {
3672 /* start up the timer. */
3673 TAILQ_FOREACH(net
, &stcb
->asoc
.nets
, sctp_next
) {
3674 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT
, inp
, stcb
, net
);
3678 if (paddrp
->spp_flags
& SPP_IPV4_TOS
)
3679 stcb
->asoc
.default_tos
= paddrp
->spp_ipv4_tos
& 0x000000fc;
3682 if (paddrp
->spp_flags
& SPP_IPV6_FLOWLABEL
)
3683 stcb
->asoc
.default_flowlabel
= paddrp
->spp_ipv6_flowlabel
;
3687 SCTP_TCB_UNLOCK(stcb
);
3689 /************************NO TCB, SET TO default stuff ******************/
3690 SCTP_INP_WLOCK(inp
);
3692 * For the TOS/FLOWLABEL stuff you set it
3693 * with the options on the socket
3695 if (paddrp
->spp_pathmaxrxt
) {
3696 inp
->sctp_ep
.def_net_failure
= paddrp
->spp_pathmaxrxt
;
3698 if (paddrp
->spp_flags
& SPP_HB_TIME_IS_ZERO
)
3699 inp
->sctp_ep
.sctp_timeoutticks
[SCTP_TIMER_HEARTBEAT
] = 0;
3700 else if (paddrp
->spp_hbinterval
) {
3701 if (paddrp
->spp_hbinterval
> SCTP_MAX_HB_INTERVAL
)
3702 paddrp
->spp_hbinterval
= SCTP_MAX_HB_INTERVAL
;
3703 inp
->sctp_ep
.sctp_timeoutticks
[SCTP_TIMER_HEARTBEAT
] = MSEC_TO_TICKS(paddrp
->spp_hbinterval
);
3705 if (paddrp
->spp_flags
& SPP_HB_ENABLE
) {
3706 sctp_feature_off(inp
, SCTP_PCB_FLAGS_DONOT_HEARTBEAT
);
3708 } else if (paddrp
->spp_flags
& SPP_HB_DISABLE
) {
3709 sctp_feature_on(inp
, SCTP_PCB_FLAGS_DONOT_HEARTBEAT
);
3711 SCTP_INP_WUNLOCK(inp
);
3717 struct sctp_rtoinfo
*srto
;
3718 uint32_t new_init
, new_min
, new_max
;
3720 SCTP_CHECK_AND_CAST(srto
, optval
, struct sctp_rtoinfo
, optsize
);
3721 SCTP_FIND_STCB(inp
, stcb
, srto
->srto_assoc_id
);
3724 if (srto
->srto_initial
)
3725 new_init
= srto
->srto_initial
;
3727 new_init
= stcb
->asoc
.initial_rto
;
3729 new_max
= srto
->srto_max
;
3731 new_max
= stcb
->asoc
.maxrto
;
3733 new_min
= srto
->srto_min
;
3735 new_min
= stcb
->asoc
.minrto
;
3736 if ((new_min
<= new_init
) && (new_init
<= new_max
)) {
3737 stcb
->asoc
.initial_rto
= new_init
;
3738 stcb
->asoc
.maxrto
= new_max
;
3739 stcb
->asoc
.minrto
= new_min
;
3741 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
3744 SCTP_TCB_UNLOCK(stcb
);
3746 SCTP_INP_WLOCK(inp
);
3747 if (srto
->srto_initial
)
3748 new_init
= srto
->srto_initial
;
3750 new_init
= inp
->sctp_ep
.initial_rto
;
3752 new_max
= srto
->srto_max
;
3754 new_max
= inp
->sctp_ep
.sctp_maxrto
;
3756 new_min
= srto
->srto_min
;
3758 new_min
= inp
->sctp_ep
.sctp_minrto
;
3759 if ((new_min
<= new_init
) && (new_init
<= new_max
)) {
3760 inp
->sctp_ep
.initial_rto
= new_init
;
3761 inp
->sctp_ep
.sctp_maxrto
= new_max
;
3762 inp
->sctp_ep
.sctp_minrto
= new_min
;
3764 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
3767 SCTP_INP_WUNLOCK(inp
);
3771 case SCTP_ASSOCINFO
:
3773 struct sctp_assocparams
*sasoc
;
3775 SCTP_CHECK_AND_CAST(sasoc
, optval
, struct sctp_assocparams
, optsize
);
3776 SCTP_FIND_STCB(inp
, stcb
, sasoc
->sasoc_assoc_id
);
3777 if (sasoc
->sasoc_cookie_life
) {
3778 /* boundary check the cookie life */
3779 if (sasoc
->sasoc_cookie_life
< 1000)
3780 sasoc
->sasoc_cookie_life
= 1000;
3781 if (sasoc
->sasoc_cookie_life
> SCTP_MAX_COOKIE_LIFE
) {
3782 sasoc
->sasoc_cookie_life
= SCTP_MAX_COOKIE_LIFE
;
3786 if (sasoc
->sasoc_asocmaxrxt
)
3787 stcb
->asoc
.max_send_times
= sasoc
->sasoc_asocmaxrxt
;
3788 sasoc
->sasoc_number_peer_destinations
= stcb
->asoc
.numnets
;
3789 sasoc
->sasoc_peer_rwnd
= 0;
3790 sasoc
->sasoc_local_rwnd
= 0;
3791 if (sasoc
->sasoc_cookie_life
) {
3792 stcb
->asoc
.cookie_life
= MSEC_TO_TICKS(sasoc
->sasoc_cookie_life
);
3794 SCTP_TCB_UNLOCK(stcb
);
3796 SCTP_INP_WLOCK(inp
);
3797 if (sasoc
->sasoc_asocmaxrxt
)
3798 inp
->sctp_ep
.max_send_times
= sasoc
->sasoc_asocmaxrxt
;
3799 sasoc
->sasoc_number_peer_destinations
= 0;
3800 sasoc
->sasoc_peer_rwnd
= 0;
3801 sasoc
->sasoc_local_rwnd
= 0;
3802 if (sasoc
->sasoc_cookie_life
) {
3803 inp
->sctp_ep
.def_cookie_life
= MSEC_TO_TICKS(sasoc
->sasoc_cookie_life
);
3805 SCTP_INP_WUNLOCK(inp
);
3811 struct sctp_initmsg
*sinit
;
3813 SCTP_CHECK_AND_CAST(sinit
, optval
, struct sctp_initmsg
, optsize
);
3814 SCTP_INP_WLOCK(inp
);
3815 if (sinit
->sinit_num_ostreams
)
3816 inp
->sctp_ep
.pre_open_stream_count
= sinit
->sinit_num_ostreams
;
3818 if (sinit
->sinit_max_instreams
)
3819 inp
->sctp_ep
.max_open_streams_intome
= sinit
->sinit_max_instreams
;
3821 if (sinit
->sinit_max_attempts
)
3822 inp
->sctp_ep
.max_init_times
= sinit
->sinit_max_attempts
;
3824 if (sinit
->sinit_max_init_timeo
)
3825 inp
->sctp_ep
.initial_init_rto_max
= sinit
->sinit_max_init_timeo
;
3826 SCTP_INP_WUNLOCK(inp
);
3829 case SCTP_PRIMARY_ADDR
:
3831 struct sctp_setprim
*spa
;
3832 struct sctp_nets
*net
, *lnet
;
3834 SCTP_CHECK_AND_CAST(spa
, optval
, struct sctp_setprim
, optsize
);
3835 SCTP_FIND_STCB(inp
, stcb
, spa
->ssp_assoc_id
);
3839 net
= sctp_findnet(stcb
, (struct sockaddr
*)&spa
->ssp_addr
);
3842 * We increment here since
3843 * sctp_findassociation_ep_addr() wil do a
3844 * decrement if it finds the stcb as long as
3845 * the locked tcb (last argument) is NOT a
3848 SCTP_INP_INCR_REF(inp
);
3849 stcb
= sctp_findassociation_ep_addr(&inp
,
3850 (struct sockaddr
*)&spa
->ssp_addr
,
3853 SCTP_INP_DECR_REF(inp
);
3857 if ((stcb
) && (net
)) {
3858 if ((net
!= stcb
->asoc
.primary_destination
) &&
3859 (!(net
->dest_state
& SCTP_ADDR_UNCONFIRMED
))) {
3860 /* Ok we need to set it */
3861 lnet
= stcb
->asoc
.primary_destination
;
3862 if (sctp_set_primary_addr(stcb
, (struct sockaddr
*)NULL
, net
) == 0) {
3863 if (net
->dest_state
& SCTP_ADDR_SWITCH_PRIMARY
) {
3864 net
->dest_state
|= SCTP_ADDR_DOUBLE_SWITCH
;
3866 net
->dest_state
|= SCTP_ADDR_SWITCH_PRIMARY
;
3870 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
3874 SCTP_TCB_UNLOCK(stcb
);
3878 case SCTP_SET_DYNAMIC_PRIMARY
:
3880 union sctp_sockstore
*ss
;
3882 error
= priv_check(curthread
,
3883 PRIV_NETINET_RESERVEDPORT
);
3887 SCTP_CHECK_AND_CAST(ss
, optval
, union sctp_sockstore
, optsize
);
3888 /* SUPER USER CHECK? */
3889 error
= sctp_dynamic_set_primary(&ss
->sa
, vrf_id
);
3892 case SCTP_SET_PEER_PRIMARY_ADDR
:
3894 struct sctp_setpeerprim
*sspp
;
3896 SCTP_CHECK_AND_CAST(sspp
, optval
, struct sctp_setpeerprim
, optsize
);
3897 SCTP_FIND_STCB(inp
, stcb
, sspp
->sspp_assoc_id
);
3899 struct sctp_ifa
*ifa
;
3901 ifa
= sctp_find_ifa_by_addr((struct sockaddr
*)&sspp
->sspp_addr
,
3902 stcb
->asoc
.vrf_id
, SCTP_ADDR_NOT_LOCKED
);
3904 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
3908 if ((inp
->sctp_flags
& SCTP_PCB_FLAGS_BOUNDALL
) == 0) {
3910 * Must validate the ifa found is in
3913 struct sctp_laddr
*laddr
;
3916 LIST_FOREACH(laddr
, &inp
->sctp_addr_list
, sctp_nxt_addr
) {
3917 if (laddr
->ifa
== NULL
) {
3918 SCTPDBG(SCTP_DEBUG_OUTPUT1
, "%s: NULL ifa\n",
3922 if (laddr
->ifa
== ifa
) {
3928 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
3933 if (sctp_set_primary_ip_address_sa(stcb
,
3934 (struct sockaddr
*)&sspp
->sspp_addr
) != 0) {
3935 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
3939 SCTP_TCB_UNLOCK(stcb
);
3941 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
3947 case SCTP_BINDX_ADD_ADDR
:
3949 struct sctp_getaddresses
*addrs
;
3954 td
= (struct thread
*)p
;
3955 if (jailed(td
->td_ucred
)) {
3958 SCTP_CHECK_AND_CAST(addrs
, optval
, struct sctp_getaddresses
,
3960 if (addrs
->addr
->sa_family
== AF_INET
) {
3961 sz
= sizeof(struct sctp_getaddresses
) - sizeof(struct sockaddr
) + sizeof(struct sockaddr_in
);
3963 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
3967 if (prison
&& prison_ip(td
->td_ucred
, 0, &(((struct sockaddr_in
*)(addrs
->addr
))->sin_addr
.s_addr
))) {
3968 SCTP_LTRACE_ERR_RET(inp
, stcb
, NULL
, SCTP_FROM_SCTP_USRREQ
, EADDRNOTAVAIL
);
3969 error
= EADDRNOTAVAIL
;
3971 } else if (addrs
->addr
->sa_family
== AF_INET6
) {
3972 sz
= sizeof(struct sctp_getaddresses
) - sizeof(struct sockaddr
) + sizeof(struct sockaddr_in6
);
3974 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
3978 /* JAIL XXXX Add else here for V6 */
3980 sctp_bindx_add_address(so
, inp
, addrs
->addr
,
3981 addrs
->sget_assoc_id
, vrf_id
,
3985 case SCTP_BINDX_REM_ADDR
:
3987 struct sctp_getaddresses
*addrs
;
3992 td
= (struct thread
*)p
;
3993 if (jailed(td
->td_ucred
)) {
3996 SCTP_CHECK_AND_CAST(addrs
, optval
, struct sctp_getaddresses
, optsize
);
3997 if (addrs
->addr
->sa_family
== AF_INET
) {
3998 sz
= sizeof(struct sctp_getaddresses
) - sizeof(struct sockaddr
) + sizeof(struct sockaddr_in
);
4000 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
4004 if (prison
&& prison_ip(td
->td_ucred
, 0, &(((struct sockaddr_in
*)(addrs
->addr
))->sin_addr
.s_addr
))) {
4005 SCTP_LTRACE_ERR_RET(inp
, stcb
, NULL
, SCTP_FROM_SCTP_USRREQ
, EADDRNOTAVAIL
);
4006 error
= EADDRNOTAVAIL
;
4008 } else if (addrs
->addr
->sa_family
== AF_INET6
) {
4009 sz
= sizeof(struct sctp_getaddresses
) - sizeof(struct sockaddr
) + sizeof(struct sockaddr_in6
);
4011 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
4015 /* JAIL XXXX Add else here for V6 */
4017 sctp_bindx_delete_address(so
, inp
, addrs
->addr
,
4018 addrs
->sget_assoc_id
, vrf_id
,
4023 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, ENOPROTOOPT
);
4024 error
= ENOPROTOOPT
;
4026 } /* end switch (opt) */
4031 sctp_ctloutput(struct socket
*so
, struct sockopt
*sopt
)
4033 void *optval
= NULL
;
4035 struct sctp_inpcb
*inp
;
4039 inp
= (struct sctp_inpcb
*)so
->so_pcb
;
4041 /* I made the same as TCP since we are not setup? */
4042 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
4043 return (ECONNRESET
);
4045 if (sopt
->sopt_level
!= IPPROTO_SCTP
) {
4046 /* wrong proto level... send back up to IP */
4048 if (INP_CHECK_SOCKAF(so
, AF_INET6
))
4049 error
= ip6_ctloutput(so
, sopt
);
4052 error
= ip_ctloutput(so
, sopt
);
4055 optsize
= sopt
->sopt_valsize
;
4057 SCTP_MALLOC(optval
, void *, optsize
, SCTP_M_SOCKOPT
);
4058 if (optval
== NULL
) {
4059 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, ENOBUFS
);
4062 error
= sooptcopyin(sopt
, optval
, optsize
, optsize
);
4064 SCTP_FREE(optval
, SCTP_M_SOCKOPT
);
4068 p
= (void *)sopt
->sopt_td
;
4069 if (sopt
->sopt_dir
== SOPT_SET
) {
4070 error
= sctp_setopt(so
, sopt
->sopt_name
, optval
, optsize
, p
);
4071 } else if (sopt
->sopt_dir
== SOPT_GET
) {
4072 error
= sctp_getopt(so
, sopt
->sopt_name
, optval
, &optsize
, p
);
4074 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
4077 if ((error
== 0) && (optval
!= NULL
)) {
4078 error
= sooptcopyout(sopt
, optval
, optsize
);
4079 SCTP_FREE(optval
, SCTP_M_SOCKOPT
);
4080 } else if (optval
!= NULL
) {
4081 SCTP_FREE(optval
, SCTP_M_SOCKOPT
);
4089 sctp_connect(struct socket
*so
, struct sockaddr
*addr
, struct thread
*p
)
4092 int create_lock_on
= 0;
4094 struct sctp_inpcb
*inp
;
4095 struct sctp_tcb
*stcb
= NULL
;
4097 inp
= (struct sctp_inpcb
*)so
->so_pcb
;
4099 /* I made the same as TCP since we are not setup? */
4100 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
4101 return (ECONNRESET
);
4104 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
4107 if ((addr
->sa_family
== AF_INET6
) && (addr
->sa_len
!= sizeof(struct sockaddr_in6
))) {
4108 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
4111 if ((addr
->sa_family
== AF_INET
) && (addr
->sa_len
!= sizeof(struct sockaddr_in
))) {
4112 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
4115 SCTP_INP_INCR_REF(inp
);
4116 SCTP_ASOC_CREATE_LOCK(inp
);
4120 if ((inp
->sctp_flags
& SCTP_PCB_FLAGS_SOCKET_ALLGONE
) ||
4121 (inp
->sctp_flags
& SCTP_PCB_FLAGS_SOCKET_GONE
)) {
4122 /* Should I really unlock ? */
4123 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EFAULT
);
4128 if (((inp
->sctp_flags
& SCTP_PCB_FLAGS_BOUND_V6
) == 0) &&
4129 (addr
->sa_family
== AF_INET6
)) {
4130 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
4135 if ((inp
->sctp_flags
& SCTP_PCB_FLAGS_UNBOUND
) ==
4136 SCTP_PCB_FLAGS_UNBOUND
) {
4137 /* Bind a ephemeral port */
4138 error
= sctp_inpcb_bind(so
, NULL
, NULL
, p
);
4143 /* Now do we connect? */
4144 if ((inp
->sctp_flags
& SCTP_PCB_FLAGS_IN_TCPPOOL
) &&
4145 (sctp_is_feature_off(inp
, SCTP_PCB_FLAGS_PORTREUSE
))) {
4146 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
4150 if ((inp
->sctp_flags
& SCTP_PCB_FLAGS_TCPTYPE
) &&
4151 (inp
->sctp_flags
& SCTP_PCB_FLAGS_CONNECTED
)) {
4152 /* We are already connected AND the TCP model */
4153 SCTP_LTRACE_ERR_RET(inp
, stcb
, NULL
, SCTP_FROM_SCTP_USRREQ
, EADDRINUSE
);
4157 if (inp
->sctp_flags
& SCTP_PCB_FLAGS_CONNECTED
) {
4158 SCTP_INP_RLOCK(inp
);
4159 stcb
= LIST_FIRST(&inp
->sctp_asoc_list
);
4160 SCTP_INP_RUNLOCK(inp
);
4163 * We increment here since sctp_findassociation_ep_addr()
4164 * will do a decrement if it finds the stcb as long as the
4165 * locked tcb (last argument) is NOT a TCB.. aka NULL.
4167 SCTP_INP_INCR_REF(inp
);
4168 stcb
= sctp_findassociation_ep_addr(&inp
, addr
, NULL
, NULL
, NULL
);
4170 SCTP_INP_DECR_REF(inp
);
4172 SCTP_TCB_UNLOCK(stcb
);
4176 /* Already have or am bring up an association */
4177 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EALREADY
);
4181 vrf_id
= inp
->def_vrf_id
;
4182 /* We are GOOD to go */
4183 stcb
= sctp_aloc_assoc(inp
, addr
, 1, &error
, 0, vrf_id
, p
);
4185 /* Gak! no memory */
4188 if (stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_TCPTYPE
) {
4189 stcb
->sctp_ep
->sctp_flags
|= SCTP_PCB_FLAGS_CONNECTED
;
4190 /* Set the connected flag so we can queue data */
4193 SCTP_SET_STATE(&stcb
->asoc
, SCTP_STATE_COOKIE_WAIT
);
4194 (void)SCTP_GETTIME_TIMEVAL(&stcb
->asoc
.time_entered
);
4196 /* initialize authentication parameters for the assoc */
4197 sctp_initialize_auth_params(inp
, stcb
);
4199 sctp_send_initiate(inp
, stcb
, SCTP_SO_LOCKED
);
4200 SCTP_TCB_UNLOCK(stcb
);
4202 if (create_lock_on
) {
4203 SCTP_ASOC_CREATE_UNLOCK(inp
);
4205 SCTP_INP_DECR_REF(inp
);
4210 sctp_listen(struct socket
*so
, int backlog
, struct thread
*p
)
4213 * Note this module depends on the protocol processing being called
4214 * AFTER any socket level flags and backlog are applied to the
4215 * socket. The traditional way that the socket flags are applied is
4216 * AFTER protocol processing. We have made a change to the
4217 * sys/kern/uipc_socket.c module to reverse this but this MUST be in
4218 * place if the socket API for SCTP is to work properly.
4222 struct sctp_inpcb
*inp
;
4224 inp
= (struct sctp_inpcb
*)so
->so_pcb
;
4226 /* I made the same as TCP since we are not setup? */
4227 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
4228 return (ECONNRESET
);
4230 if (sctp_is_feature_on(inp
, SCTP_PCB_FLAGS_PORTREUSE
)) {
4231 /* See if we have a listener */
4232 struct sctp_inpcb
*tinp
;
4233 union sctp_sockstore store
, *sp
;
4236 if ((inp
->sctp_flags
& SCTP_PCB_FLAGS_BOUNDALL
) == 0) {
4238 struct sctp_laddr
*laddr
;
4240 LIST_FOREACH(laddr
, &inp
->sctp_addr_list
, sctp_nxt_addr
) {
4241 memcpy(&store
, &laddr
->ifa
->address
, sizeof(store
));
4242 sp
->sin
.sin_port
= inp
->sctp_lport
;
4243 tinp
= sctp_pcb_findep(&sp
->sa
, 0, 0, inp
->def_vrf_id
);
4244 if (tinp
&& (tinp
!= inp
) &&
4245 ((tinp
->sctp_flags
& SCTP_PCB_FLAGS_SOCKET_ALLGONE
) == 0) &&
4246 ((tinp
->sctp_flags
& SCTP_PCB_FLAGS_SOCKET_GONE
) == 0) &&
4247 (tinp
->sctp_socket
->so_qlimit
)) {
4249 * we have a listener already and
4252 SCTP_INP_DECR_REF(tinp
);
4253 return (EADDRINUSE
);
4255 SCTP_INP_DECR_REF(tinp
);
4259 /* Setup a local addr bound all */
4260 memset(&store
, 0, sizeof(store
));
4261 store
.sin
.sin_port
= inp
->sctp_lport
;
4263 if (inp
->sctp_flags
& SCTP_PCB_FLAGS_BOUND_V6
) {
4264 store
.sa
.sa_family
= AF_INET6
;
4265 store
.sa
.sa_len
= sizeof(struct sockaddr_in6
);
4268 if ((inp
->sctp_flags
& SCTP_PCB_FLAGS_BOUND_V6
) == 0) {
4269 store
.sa
.sa_family
= AF_INET
;
4270 store
.sa
.sa_len
= sizeof(struct sockaddr_in
);
4272 tinp
= sctp_pcb_findep(&sp
->sa
, 0, 0, inp
->def_vrf_id
);
4273 if (tinp
&& (tinp
!= inp
) &&
4274 ((tinp
->sctp_flags
& SCTP_PCB_FLAGS_SOCKET_ALLGONE
) == 0) &&
4275 ((tinp
->sctp_flags
& SCTP_PCB_FLAGS_SOCKET_GONE
) == 0) &&
4276 (tinp
->sctp_socket
->so_qlimit
)) {
4278 * we have a listener already and its not
4281 SCTP_INP_DECR_REF(tinp
);
4282 return (EADDRINUSE
);
4284 SCTP_INP_DECR_REF(inp
);
4288 SCTP_INP_RLOCK(inp
);
4289 #ifdef SCTP_LOCK_LOGGING
4290 if (SCTP_BASE_SYSCTL(sctp_logging_level
) & SCTP_LOCK_LOGGING_ENABLE
) {
4291 sctp_log_lock(inp
, (struct sctp_tcb
*)NULL
, SCTP_LOG_LOCK_SOCK
);
4295 error
= solisten_proto_check(so
);
4298 SCTP_INP_RUNLOCK(inp
);
4301 if ((sctp_is_feature_on(inp
, SCTP_PCB_FLAGS_PORTREUSE
)) &&
4302 (inp
->sctp_flags
& SCTP_PCB_FLAGS_IN_TCPPOOL
)) {
4304 * The unlucky case - We are in the tcp pool with this guy.
4305 * - Someone else is in the main inp slot. - We must move
4306 * this guy (the listener) to the main slot - We must then
4307 * move the guy that was listener to the TCP Pool.
4309 if (sctp_swap_inpcb_for_listen(inp
)) {
4313 if ((inp
->sctp_flags
& SCTP_PCB_FLAGS_TCPTYPE
) &&
4314 (inp
->sctp_flags
& SCTP_PCB_FLAGS_CONNECTED
)) {
4315 /* We are already connected AND the TCP model */
4317 SCTP_INP_RUNLOCK(inp
);
4319 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EADDRINUSE
);
4320 return (EADDRINUSE
);
4322 SCTP_INP_RUNLOCK(inp
);
4323 if (inp
->sctp_flags
& SCTP_PCB_FLAGS_UNBOUND
) {
4324 /* We must do a bind. */
4326 if ((error
= sctp_inpcb_bind(so
, NULL
, NULL
, p
))) {
4327 /* bind error, probably perm */
4332 /* It appears for 7.0 and on, we must always call this. */
4333 solisten_proto(so
, backlog
);
4334 if (inp
->sctp_flags
& SCTP_PCB_FLAGS_UDPTYPE
) {
4335 /* remove the ACCEPTCONN flag for one-to-many sockets */
4336 so
->so_options
&= ~SO_ACCEPTCONN
;
4339 /* turning off listen */
4340 so
->so_options
&= ~SO_ACCEPTCONN
;
4346 static int sctp_defered_wakeup_cnt
= 0;
4349 sctp_accept(struct socket
*so
, struct sockaddr
**addr
)
4351 struct sctp_tcb
*stcb
;
4352 struct sctp_inpcb
*inp
;
4353 union sctp_sockstore store
;
4359 inp
= (struct sctp_inpcb
*)so
->so_pcb
;
4362 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
4363 return (ECONNRESET
);
4365 SCTP_INP_RLOCK(inp
);
4366 if (inp
->sctp_flags
& SCTP_PCB_FLAGS_UDPTYPE
) {
4367 SCTP_INP_RUNLOCK(inp
);
4368 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EOPNOTSUPP
);
4369 return (EOPNOTSUPP
);
4371 if (so
->so_state
& SS_ISDISCONNECTED
) {
4372 SCTP_INP_RUNLOCK(inp
);
4373 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, ECONNABORTED
);
4374 return (ECONNABORTED
);
4376 stcb
= LIST_FIRST(&inp
->sctp_asoc_list
);
4378 SCTP_INP_RUNLOCK(inp
);
4379 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
4380 return (ECONNRESET
);
4382 SCTP_TCB_LOCK(stcb
);
4383 SCTP_INP_RUNLOCK(inp
);
4384 store
= stcb
->asoc
.primary_destination
->ro
._l_addr
;
4385 SCTP_TCB_UNLOCK(stcb
);
4386 switch (store
.sa
.sa_family
) {
4389 struct sockaddr_in
*sin
;
4391 SCTP_MALLOC_SONAME(sin
, struct sockaddr_in
*, sizeof *sin
);
4392 sin
->sin_family
= AF_INET
;
4393 sin
->sin_len
= sizeof(*sin
);
4394 sin
->sin_port
= ((struct sockaddr_in
*)&store
)->sin_port
;
4395 sin
->sin_addr
= ((struct sockaddr_in
*)&store
)->sin_addr
;
4396 *addr
= (struct sockaddr
*)sin
;
4402 struct sockaddr_in6
*sin6
;
4404 SCTP_MALLOC_SONAME(sin6
, struct sockaddr_in6
*, sizeof *sin6
);
4405 sin6
->sin6_family
= AF_INET6
;
4406 sin6
->sin6_len
= sizeof(*sin6
);
4407 sin6
->sin6_port
= ((struct sockaddr_in6
*)&store
)->sin6_port
;
4409 sin6
->sin6_addr
= ((struct sockaddr_in6
*)&store
)->sin6_addr
;
4410 if ((error
= sa6_recoverscope(sin6
)) != 0) {
4411 SCTP_FREE_SONAME(sin6
);
4414 *addr
= (struct sockaddr
*)sin6
;
4422 /* Wake any delayed sleep action */
4423 if (inp
->sctp_flags
& SCTP_PCB_FLAGS_DONT_WAKE
) {
4424 SCTP_INP_WLOCK(inp
);
4425 inp
->sctp_flags
&= ~SCTP_PCB_FLAGS_DONT_WAKE
;
4426 if (inp
->sctp_flags
& SCTP_PCB_FLAGS_WAKEOUTPUT
) {
4427 inp
->sctp_flags
&= ~SCTP_PCB_FLAGS_WAKEOUTPUT
;
4428 SCTP_INP_WUNLOCK(inp
);
4429 SOCKBUF_LOCK(&inp
->sctp_socket
->so_snd
);
4430 if (sowriteable(inp
->sctp_socket
)) {
4431 sowwakeup_locked(inp
->sctp_socket
);
4433 SOCKBUF_UNLOCK(&inp
->sctp_socket
->so_snd
);
4435 SCTP_INP_WLOCK(inp
);
4437 if (inp
->sctp_flags
& SCTP_PCB_FLAGS_WAKEINPUT
) {
4438 inp
->sctp_flags
&= ~SCTP_PCB_FLAGS_WAKEINPUT
;
4439 SCTP_INP_WUNLOCK(inp
);
4440 SOCKBUF_LOCK(&inp
->sctp_socket
->so_rcv
);
4441 if (soreadable(inp
->sctp_socket
)) {
4442 sctp_defered_wakeup_cnt
++;
4443 sorwakeup_locked(inp
->sctp_socket
);
4445 SOCKBUF_UNLOCK(&inp
->sctp_socket
->so_rcv
);
4447 SCTP_INP_WLOCK(inp
);
4449 SCTP_INP_WUNLOCK(inp
);
4455 sctp_ingetaddr(struct socket
*so
, struct sockaddr
**addr
)
4457 struct sockaddr_in
*sin
;
4459 struct sctp_inpcb
*inp
;
4460 struct sctp_ifa
*sctp_ifa
;
4463 * Do the malloc first in case it blocks.
4465 SCTP_MALLOC_SONAME(sin
, struct sockaddr_in
*, sizeof *sin
);
4466 sin
->sin_family
= AF_INET
;
4467 sin
->sin_len
= sizeof(*sin
);
4468 inp
= (struct sctp_inpcb
*)so
->so_pcb
;
4470 SCTP_FREE_SONAME(sin
);
4471 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
4474 SCTP_INP_RLOCK(inp
);
4475 sin
->sin_port
= inp
->sctp_lport
;
4476 if (inp
->sctp_flags
& SCTP_PCB_FLAGS_BOUNDALL
) {
4477 if (inp
->sctp_flags
& SCTP_PCB_FLAGS_CONNECTED
) {
4478 struct sctp_tcb
*stcb
;
4479 struct sockaddr_in
*sin_a
;
4480 struct sctp_nets
*net
;
4483 stcb
= LIST_FIRST(&inp
->sctp_asoc_list
);
4489 SCTP_TCB_LOCK(stcb
);
4490 TAILQ_FOREACH(net
, &stcb
->asoc
.nets
, sctp_next
) {
4491 sin_a
= (struct sockaddr_in
*)&net
->ro
._l_addr
;
4493 /* this will make coverity happy */
4496 if (sin_a
->sin_family
== AF_INET
) {
4501 if ((!fnd
) || (sin_a
== NULL
)) {
4503 SCTP_TCB_UNLOCK(stcb
);
4506 vrf_id
= inp
->def_vrf_id
;
4507 sctp_ifa
= sctp_source_address_selection(inp
,
4509 (sctp_route_t
*) & net
->ro
,
4512 sin
->sin_addr
= sctp_ifa
->address
.sin
.sin_addr
;
4513 sctp_free_ifa(sctp_ifa
);
4515 SCTP_TCB_UNLOCK(stcb
);
4517 /* For the bound all case you get back 0 */
4519 sin
->sin_addr
.s_addr
= 0;
4523 /* Take the first IPv4 address in the list */
4524 struct sctp_laddr
*laddr
;
4527 LIST_FOREACH(laddr
, &inp
->sctp_addr_list
, sctp_nxt_addr
) {
4528 if (laddr
->ifa
->address
.sa
.sa_family
== AF_INET
) {
4529 struct sockaddr_in
*sin_a
;
4531 sin_a
= (struct sockaddr_in
*)&laddr
->ifa
->address
.sa
;
4532 sin
->sin_addr
= sin_a
->sin_addr
;
4538 SCTP_FREE_SONAME(sin
);
4539 SCTP_INP_RUNLOCK(inp
);
4540 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, ENOENT
);
4544 SCTP_INP_RUNLOCK(inp
);
4545 (*addr
) = (struct sockaddr
*)sin
;
4550 sctp_peeraddr(struct socket
*so
, struct sockaddr
**addr
)
4552 struct sockaddr_in
*sin
= (struct sockaddr_in
*)*addr
;
4554 struct sockaddr_in
*sin_a
;
4555 struct sctp_inpcb
*inp
;
4556 struct sctp_tcb
*stcb
;
4557 struct sctp_nets
*net
;
4559 /* Do the malloc first in case it blocks. */
4560 inp
= (struct sctp_inpcb
*)so
->so_pcb
;
4561 if ((inp
== NULL
) ||
4562 ((inp
->sctp_flags
& SCTP_PCB_FLAGS_CONNECTED
) == 0)) {
4563 /* UDP type and listeners will drop out here */
4564 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, ENOTCONN
);
4567 SCTP_MALLOC_SONAME(sin
, struct sockaddr_in
*, sizeof *sin
);
4568 sin
->sin_family
= AF_INET
;
4569 sin
->sin_len
= sizeof(*sin
);
4571 /* We must recapture incase we blocked */
4572 inp
= (struct sctp_inpcb
*)so
->so_pcb
;
4574 SCTP_FREE_SONAME(sin
);
4575 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
4578 SCTP_INP_RLOCK(inp
);
4579 stcb
= LIST_FIRST(&inp
->sctp_asoc_list
);
4581 SCTP_TCB_LOCK(stcb
);
4583 SCTP_INP_RUNLOCK(inp
);
4585 SCTP_FREE_SONAME(sin
);
4586 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, EINVAL
);
4590 TAILQ_FOREACH(net
, &stcb
->asoc
.nets
, sctp_next
) {
4591 sin_a
= (struct sockaddr_in
*)&net
->ro
._l_addr
;
4592 if (sin_a
->sin_family
== AF_INET
) {
4594 sin
->sin_port
= stcb
->rport
;
4595 sin
->sin_addr
= sin_a
->sin_addr
;
4599 SCTP_TCB_UNLOCK(stcb
);
4601 /* No IPv4 address */
4602 SCTP_FREE_SONAME(sin
);
4603 SCTP_LTRACE_ERR_RET(inp
, NULL
, NULL
, SCTP_FROM_SCTP_USRREQ
, ENOENT
);
4606 (*addr
) = (struct sockaddr
*)sin
;
4610 struct pr_usrreqs sctp_usrreqs
= {
4611 .pru_abort
= sctp_abort
,
4612 .pru_accept
= sctp_accept
,
4613 .pru_attach
= sctp_attach
,
4614 .pru_bind
= sctp_bind
,
4615 .pru_connect
= sctp_connect
,
4616 .pru_control
= in_control
,
4617 .pru_close
= sctp_close
,
4618 .pru_detach
= sctp_close
,
4619 .pru_sopoll
= sopoll_generic
,
4620 .pru_flush
= sctp_flush
,
4621 .pru_disconnect
= sctp_disconnect
,
4622 .pru_listen
= sctp_listen
,
4623 .pru_peeraddr
= sctp_peeraddr
,
4624 .pru_send
= sctp_sendm
,
4625 .pru_shutdown
= sctp_shutdown
,
4626 .pru_sockaddr
= sctp_ingetaddr
,
4627 .pru_sosend
= sctp_sosend
,
4628 .pru_soreceive
= sctp_soreceive