2 * Copyright (c) 2000-2019 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * Copyright (c) 1982, 1986, 1988, 1993
30 * The Regents of the University of California. All rights reserved.
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 * From: @(#)tcp_usrreq.c 8.2 (Berkeley) 1/3/94
61 * $FreeBSD: src/sys/netinet/tcp_usrreq.c,v 1.51.2.9 2001/08/22 00:59:12 silby Exp $
65 #include <sys/param.h>
66 #include <sys/systm.h>
67 #include <sys/kernel.h>
68 #include <sys/sysctl.h>
71 #include <sys/domain.h>
77 #include <sys/socket.h>
78 #include <sys/socketvar.h>
79 #include <sys/protosw.h>
80 #include <sys/syslog.h>
83 #include <net/route.h>
84 #include <net/ntstat.h>
85 #include <net/content_filter.h>
86 #include <net/multi_layer_pkt_log.h>
88 #include <netinet/in.h>
89 #include <netinet/in_systm.h>
91 #include <netinet/ip6.h>
93 #include <netinet/in_pcb.h>
95 #include <netinet6/in6_pcb.h>
97 #include <netinet/in_var.h>
98 #include <netinet/ip_var.h>
100 #include <netinet6/ip6_var.h>
102 #include <netinet/tcp.h>
103 #include <netinet/tcp_fsm.h>
104 #include <netinet/tcp_seq.h>
105 #include <netinet/tcp_timer.h>
106 #include <netinet/tcp_var.h>
107 #include <netinet/tcpip.h>
108 #include <netinet/tcp_cc.h>
109 #include <netinet/tcp_log.h>
110 #include <mach/sdt.h>
112 #include <netinet/tcp_debug.h>
115 #include <netinet/mptcp_var.h>
119 #include <netinet6/ipsec.h>
123 #include <netinet/flow_divert.h>
124 #endif /* FLOW_DIVERT */
126 errno_t
tcp_fill_info_for_info_tuple(struct info_tuple
*, struct tcp_info
*);
128 int tcp_sysctl_info(struct sysctl_oid
*, void *, int, struct sysctl_req
*);
129 static void tcp_connection_fill_info(struct tcpcb
*tp
,
130 struct tcp_connection_info
*tci
);
131 static int tcp_get_mpkl_send_info(struct mbuf
*, struct so_mpkl_send_info
*);
134 * TCP protocol interface to socket abstraction.
136 static int tcp_attach(struct socket
*, struct proc
*);
137 static int tcp_connect(struct tcpcb
*, struct sockaddr
*, struct proc
*);
139 static int tcp6_connect(struct tcpcb
*, struct sockaddr
*, struct proc
*);
140 static int tcp6_usr_connect(struct socket
*, struct sockaddr
*,
143 static struct tcpcb
*tcp_disconnect(struct tcpcb
*);
144 static struct tcpcb
*tcp_usrclosed(struct tcpcb
*);
145 extern void tcp_sbrcv_trim(struct tcpcb
*tp
, struct sockbuf
*sb
);
148 #define TCPDEBUG0 int ostate = 0
149 #define TCPDEBUG1() ostate = tp ? tp->t_state : 0
150 #define TCPDEBUG2(req) if (tp && (so->so_options & SO_DEBUG)) \
151 tcp_trace(TA_USER, ostate, tp, 0, 0, req)
155 #define TCPDEBUG2(req)
158 SYSCTL_PROC(_net_inet_tcp
, OID_AUTO
, info
,
159 CTLFLAG_RW
| CTLFLAG_LOCKED
| CTLFLAG_ANYBODY
| CTLFLAG_KERN
,
160 0, 0, tcp_sysctl_info
, "S", "TCP info per tuple");
163 * TCP attaches to socket via pru_attach(), reserving space,
164 * and an internet control block.
170 * tcp_attach:??? [IPSEC specific]
173 tcp_usr_attach(struct socket
*so
, __unused
int proto
, struct proc
*p
)
176 struct inpcb
*inp
= sotoinpcb(so
);
177 struct tcpcb
*tp
= 0;
186 error
= tcp_attach(so
, p
);
191 if ((so
->so_options
& SO_LINGER
) && so
->so_linger
== 0) {
192 so
->so_linger
= TCP_LINGERTIME
* hz
;
196 TCPDEBUG2(PRU_ATTACH
);
201 * pru_detach() detaches the TCP protocol from the socket.
202 * If the protocol state is non-embryonic, then can't
203 * do this directly: have to initiate a pru_disconnect(),
204 * which may finish later; embryonic TCB's can just
208 tcp_usr_detach(struct socket
*so
)
211 struct inpcb
*inp
= sotoinpcb(so
);
215 if (inp
== 0 || (inp
->inp_state
== INPCB_STATE_DEAD
)) {
216 return EINVAL
; /* XXX */
218 socket_lock_assert_owned(so
);
220 /* In case we got disconnected from the peer */
226 calculate_tcp_clock();
228 tp
= tcp_disconnect(tp
);
230 TCPDEBUG2(PRU_DETACH
);
235 #define COMMON_START() TCPDEBUG0; \
237 if (inp == NULL || inp->inp_state == INPCB_STATE_DEAD) \
239 if (necp_socket_should_use_flow_divert(inp)) \
240 return (EPROTOTYPE); \
241 tp = intotcpcb(inp); \
243 calculate_tcp_clock(); \
246 #define COMMON_START() TCPDEBUG0; \
248 if (inp == NULL || inp->inp_state == INPCB_STATE_DEAD) \
250 tp = intotcpcb(inp); \
252 calculate_tcp_clock(); \
256 #define COMMON_END(req) out: TCPDEBUG2(req); return error; goto out
260 * Give the socket an address.
263 * EINVAL Invalid argument [COMMON_START]
264 * EAFNOSUPPORT Address family not supported
265 * in_pcbbind:EADDRNOTAVAIL Address not available.
266 * in_pcbbind:EINVAL Invalid argument
267 * in_pcbbind:EAFNOSUPPORT Address family not supported [notdef]
268 * in_pcbbind:EACCES Permission denied
269 * in_pcbbind:EADDRINUSE Address in use
270 * in_pcbbind:EAGAIN Resource unavailable, try again
271 * in_pcbbind:EPERM Operation not permitted
274 tcp_usr_bind(struct socket
*so
, struct sockaddr
*nam
, struct proc
*p
)
277 struct inpcb
*inp
= sotoinpcb(so
);
279 struct sockaddr_in
*sinp
;
283 if (nam
->sa_family
!= 0 && nam
->sa_family
!= AF_INET
) {
284 error
= EAFNOSUPPORT
;
289 * Must check for multicast addresses and disallow binding
292 sinp
= (struct sockaddr_in
*)(void *)nam
;
293 if (sinp
->sin_family
== AF_INET
&&
294 IN_MULTICAST(ntohl(sinp
->sin_addr
.s_addr
))) {
295 error
= EAFNOSUPPORT
;
298 error
= in_pcbbind(inp
, nam
, p
);
304 /* Update NECP client with bind result if not in middle of connect */
305 if ((inp
->inp_flags2
& INP2_CONNECT_IN_PROGRESS
) &&
306 !uuid_is_null(inp
->necp_client_uuid
)) {
307 socket_unlock(so
, 0);
308 necp_client_assign_from_socket(so
->last_pid
, inp
->necp_client_uuid
, inp
);
313 COMMON_END(PRU_BIND
);
318 tcp6_usr_bind(struct socket
*so
, struct sockaddr
*nam
, struct proc
*p
)
321 struct inpcb
*inp
= sotoinpcb(so
);
323 struct sockaddr_in6
*sin6p
;
327 if (nam
->sa_family
!= 0 && nam
->sa_family
!= AF_INET6
) {
328 error
= EAFNOSUPPORT
;
333 * Must check for multicast addresses and disallow binding
336 sin6p
= (struct sockaddr_in6
*)(void *)nam
;
337 if (sin6p
->sin6_family
== AF_INET6
&&
338 IN6_IS_ADDR_MULTICAST(&sin6p
->sin6_addr
)) {
339 error
= EAFNOSUPPORT
;
342 inp
->inp_vflag
&= ~INP_IPV4
;
343 inp
->inp_vflag
|= INP_IPV6
;
344 if ((inp
->inp_flags
& IN6P_IPV6_V6ONLY
) == 0) {
345 if (IN6_IS_ADDR_UNSPECIFIED(&sin6p
->sin6_addr
)) {
346 inp
->inp_vflag
|= INP_IPV4
;
347 } else if (IN6_IS_ADDR_V4MAPPED(&sin6p
->sin6_addr
)) {
348 struct sockaddr_in sin
;
350 in6_sin6_2_sin(&sin
, sin6p
);
351 inp
->inp_vflag
|= INP_IPV4
;
352 inp
->inp_vflag
&= ~INP_IPV6
;
353 error
= in_pcbbind(inp
, (struct sockaddr
*)&sin
, p
);
357 error
= in6_pcbbind(inp
, nam
, p
);
361 COMMON_END(PRU_BIND
);
366 * Prepare to accept connections.
369 * EINVAL [COMMON_START]
370 * in_pcbbind:EADDRNOTAVAIL Address not available.
371 * in_pcbbind:EINVAL Invalid argument
372 * in_pcbbind:EAFNOSUPPORT Address family not supported [notdef]
373 * in_pcbbind:EACCES Permission denied
374 * in_pcbbind:EADDRINUSE Address in use
375 * in_pcbbind:EAGAIN Resource unavailable, try again
376 * in_pcbbind:EPERM Operation not permitted
379 tcp_usr_listen(struct socket
*so
, struct proc
*p
)
382 struct inpcb
*inp
= sotoinpcb(so
);
386 if (inp
->inp_lport
== 0) {
387 error
= in_pcbbind(inp
, NULL
, p
);
390 tp
->t_state
= TCPS_LISTEN
;
392 TCP_LOG_LISTEN(tp
, error
);
393 COMMON_END(PRU_LISTEN
);
398 tcp6_usr_listen(struct socket
*so
, struct proc
*p
)
401 struct inpcb
*inp
= sotoinpcb(so
);
405 if (inp
->inp_lport
== 0) {
406 inp
->inp_vflag
&= ~INP_IPV4
;
407 if ((inp
->inp_flags
& IN6P_IPV6_V6ONLY
) == 0) {
408 inp
->inp_vflag
|= INP_IPV4
;
410 error
= in6_pcbbind(inp
, NULL
, p
);
413 tp
->t_state
= TCPS_LISTEN
;
415 TCP_LOG_LISTEN(tp
, error
);
416 COMMON_END(PRU_LISTEN
);
421 tcp_connect_complete(struct socket
*so
)
423 struct tcpcb
*tp
= sototcpcb(so
);
424 struct inpcb
*inp
= sotoinpcb(so
);
427 /* TFO delays the tcp_output until later, when the app calls write() */
428 if (so
->so_flags1
& SOF1_PRECONNECT_DATA
) {
429 if (!necp_socket_is_allowed_to_send_recv(sotoinpcb(so
), NULL
, NULL
, NULL
, NULL
)) {
430 TCP_LOG_DROP_NECP(NULL
, NULL
, tp
, true);
434 /* Initialize enough state so that we can actually send data */
435 tcp_mss(tp
, -1, IFSCOPE_NONE
);
436 tp
->snd_wnd
= tp
->t_maxseg
;
437 tp
->max_sndwnd
= tp
->snd_wnd
;
439 error
= tcp_output(tp
);
443 /* Update NECP client with connected five-tuple */
444 if (error
== 0 && !uuid_is_null(inp
->necp_client_uuid
)) {
445 socket_unlock(so
, 0);
446 necp_client_assign_from_socket(so
->last_pid
, inp
->necp_client_uuid
, inp
);
455 * Initiate connection to peer.
456 * Create a template for use in transmissions on this connection.
457 * Enter SYN_SENT state, and mark socket as connecting.
458 * Start keep-alive timer, and seed output sequence space.
459 * Send initial segment on connection.
462 tcp_usr_connect(struct socket
*so
, struct sockaddr
*nam
, struct proc
*p
)
465 struct inpcb
*inp
= sotoinpcb(so
);
467 struct sockaddr_in
*sinp
;
472 } else if (inp
->inp_state
== INPCB_STATE_DEAD
) {
474 error
= so
->so_error
;
483 error
= cfil_sock_attach(so
, NULL
, nam
, CFS_CONNECTION_DIR_OUT
);
487 #endif /* CONTENT_FILTER */
489 if (necp_socket_should_use_flow_divert(inp
)) {
490 uint32_t fd_ctl_unit
= necp_socket_get_flow_divert_control_unit(inp
);
491 if (fd_ctl_unit
> 0) {
492 error
= flow_divert_pcb_init(so
, fd_ctl_unit
);
494 error
= flow_divert_connect_out(so
, nam
, p
);
502 #endif /* FLOW_DIVERT */
507 calculate_tcp_clock();
509 if (nam
->sa_family
!= 0 && nam
->sa_family
!= AF_INET
) {
510 error
= EAFNOSUPPORT
;
514 * Must disallow TCP ``connections'' to multicast addresses.
516 sinp
= (struct sockaddr_in
*)(void *)nam
;
517 if (sinp
->sin_family
== AF_INET
518 && IN_MULTICAST(ntohl(sinp
->sin_addr
.s_addr
))) {
519 error
= EAFNOSUPPORT
;
523 if ((error
= tcp_connect(tp
, nam
, p
)) != 0) {
524 TCP_LOG_CONNECT(tp
, true, error
);
528 error
= tcp_connect_complete(so
);
530 TCP_LOG_CONNECT(tp
, true, error
);
532 COMMON_END(PRU_CONNECT
);
536 tcp_usr_connectx_common(struct socket
*so
, int af
,
537 struct sockaddr
*src
, struct sockaddr
*dst
,
538 struct proc
*p
, uint32_t ifscope
, sae_associd_t aid
, sae_connid_t
*pcid
,
539 uint32_t flags
, void *arg
, uint32_t arglen
, struct uio
*auio
,
540 user_ssize_t
*bytes_written
)
542 #pragma unused(aid, flags, arg, arglen)
543 struct inpcb
*inp
= sotoinpcb(so
);
545 user_ssize_t datalen
= 0;
553 ASSERT(!(inp
->inp_flags2
& INP2_CONNECT_IN_PROGRESS
));
554 inp
->inp_flags2
|= INP2_CONNECT_IN_PROGRESS
;
557 inp_update_necp_policy(inp
, src
, dst
, ifscope
);
560 if ((so
->so_flags1
& SOF1_DATA_IDEMPOTENT
) &&
561 (tcp_fastopen
& TCP_FASTOPEN_CLIENT
)) {
562 sototcpcb(so
)->t_flagsext
|= TF_FASTOPEN
;
565 /* bind socket to the specified interface, if requested */
566 if (ifscope
!= IFSCOPE_NONE
&&
567 (error
= inp_bindif(inp
, ifscope
, NULL
)) != 0) {
571 /* if source address and/or port is specified, bind to it */
573 error
= sobindlock(so
, src
, 0); /* already locked */
581 error
= tcp_usr_connect(so
, dst
, p
);
585 error
= tcp6_usr_connect(so
, dst
, p
);
597 /* if there is data, copy it */
599 socket_unlock(so
, 0);
601 VERIFY(bytes_written
!= NULL
);
603 datalen
= uio_resid(auio
);
604 error
= so
->so_proto
->pr_usrreqs
->pru_sosend(so
, NULL
,
605 (uio_t
)auio
, NULL
, NULL
, 0);
608 if (error
== 0 || error
== EWOULDBLOCK
) {
609 *bytes_written
= datalen
- uio_resid(auio
);
613 * sosend returns EWOULDBLOCK if it's a non-blocking
614 * socket or a timeout occured (this allows to return
615 * the amount of queued data through sendit()).
617 * However, connectx() returns EINPROGRESS in case of a
618 * blocking socket. So we change the return value here.
620 if (error
== EWOULDBLOCK
) {
625 if (error
== 0 && pcid
!= NULL
) {
626 *pcid
= 1; /* there is only one connection in regular TCP */
629 if (error
&& error
!= EINPROGRESS
) {
630 so
->so_flags1
&= ~SOF1_PRECONNECT_DATA
;
633 inp
->inp_flags2
&= ~INP2_CONNECT_IN_PROGRESS
;
638 tcp_usr_connectx(struct socket
*so
, struct sockaddr
*src
,
639 struct sockaddr
*dst
, struct proc
*p
, uint32_t ifscope
,
640 sae_associd_t aid
, sae_connid_t
*pcid
, uint32_t flags
, void *arg
,
641 uint32_t arglen
, struct uio
*uio
, user_ssize_t
*bytes_written
)
643 return tcp_usr_connectx_common(so
, AF_INET
, src
, dst
, p
, ifscope
, aid
,
644 pcid
, flags
, arg
, arglen
, uio
, bytes_written
);
649 tcp6_usr_connect(struct socket
*so
, struct sockaddr
*nam
, struct proc
*p
)
652 struct inpcb
*inp
= sotoinpcb(so
);
654 struct sockaddr_in6
*sin6p
;
659 } else if (inp
->inp_state
== INPCB_STATE_DEAD
) {
661 error
= so
->so_error
;
670 error
= cfil_sock_attach(so
, NULL
, nam
, CFS_CONNECTION_DIR_OUT
);
674 #endif /* CONTENT_FILTER */
676 if (necp_socket_should_use_flow_divert(inp
)) {
677 uint32_t fd_ctl_unit
= necp_socket_get_flow_divert_control_unit(inp
);
678 if (fd_ctl_unit
> 0) {
679 error
= flow_divert_pcb_init(so
, fd_ctl_unit
);
681 error
= flow_divert_connect_out(so
, nam
, p
);
689 #endif /* FLOW_DIVERT */
695 calculate_tcp_clock();
697 if (nam
->sa_family
!= 0 && nam
->sa_family
!= AF_INET6
) {
698 error
= EAFNOSUPPORT
;
703 * Must disallow TCP ``connections'' to multicast addresses.
705 sin6p
= (struct sockaddr_in6
*)(void *)nam
;
706 if (sin6p
->sin6_family
== AF_INET6
707 && IN6_IS_ADDR_MULTICAST(&sin6p
->sin6_addr
)) {
708 error
= EAFNOSUPPORT
;
712 if (IN6_IS_ADDR_V4MAPPED(&sin6p
->sin6_addr
)) {
713 struct sockaddr_in sin
;
715 if ((inp
->inp_flags
& IN6P_IPV6_V6ONLY
) != 0) {
719 in6_sin6_2_sin(&sin
, sin6p
);
720 inp
->inp_vflag
|= INP_IPV4
;
721 inp
->inp_vflag
&= ~INP_IPV6
;
722 if ((error
= tcp_connect(tp
, (struct sockaddr
*)&sin
, p
)) != 0) {
723 TCP_LOG_CONNECT(tp
, true, error
);
727 error
= tcp_connect_complete(so
);
730 inp
->inp_vflag
&= ~INP_IPV4
;
731 inp
->inp_vflag
|= INP_IPV6
;
732 if ((error
= tcp6_connect(tp
, nam
, p
)) != 0) {
733 TCP_LOG_CONNECT(tp
, true, error
);
737 error
= tcp_connect_complete(so
);
739 TCP_LOG_CONNECT(tp
, true, error
);
741 COMMON_END(PRU_CONNECT
);
745 tcp6_usr_connectx(struct socket
*so
, struct sockaddr
*src
,
746 struct sockaddr
*dst
, struct proc
*p
, uint32_t ifscope
,
747 sae_associd_t aid
, sae_connid_t
*pcid
, uint32_t flags
, void *arg
,
748 uint32_t arglen
, struct uio
*uio
, user_ssize_t
*bytes_written
)
750 return tcp_usr_connectx_common(so
, AF_INET6
, src
, dst
, p
, ifscope
, aid
,
751 pcid
, flags
, arg
, arglen
, uio
, bytes_written
);
756 * Initiate disconnect from peer.
757 * If connection never passed embryonic stage, just drop;
758 * else if don't need to let data drain, then can just drop anyways,
759 * else have to begin TCP shutdown process: mark socket disconnecting,
760 * drain unread data, state switch to reflect user close, and
761 * send segment (e.g. FIN) to peer. Socket will be really disconnected
762 * when peer sends FIN and acks ours.
764 * SHOULD IMPLEMENT LATER PRU_CONNECT VIA REALLOC TCPCB.
767 tcp_usr_disconnect(struct socket
*so
)
770 struct inpcb
*inp
= sotoinpcb(so
);
773 socket_lock_assert_owned(so
);
775 /* In case we got disconnected from the peer */
779 tp
= tcp_disconnect(tp
);
780 COMMON_END(PRU_DISCONNECT
);
784 * User-protocol pru_disconnectx callback.
787 tcp_usr_disconnectx(struct socket
*so
, sae_associd_t aid
, sae_connid_t cid
)
790 if (aid
!= SAE_ASSOCID_ANY
&& aid
!= SAE_ASSOCID_ALL
) {
794 return tcp_usr_disconnect(so
);
798 * Accept a connection. Essentially all the work is
799 * done at higher levels; just return the address
800 * of the peer, storing through addr.
803 tcp_usr_accept(struct socket
*so
, struct sockaddr
**nam
)
806 struct inpcb
*inp
= sotoinpcb(so
);
807 struct tcpcb
*tp
= NULL
;
810 in_getpeeraddr(so
, nam
);
812 if (so
->so_state
& SS_ISDISCONNECTED
) {
813 error
= ECONNABORTED
;
816 if (inp
== NULL
|| inp
->inp_state
== INPCB_STATE_DEAD
) {
820 else if (necp_socket_should_use_flow_divert(inp
)) {
829 TCP_LOG_ACCEPT(tp
, 0);
831 calculate_tcp_clock();
833 COMMON_END(PRU_ACCEPT
);
838 tcp6_usr_accept(struct socket
*so
, struct sockaddr
**nam
)
841 struct inpcb
*inp
= sotoinpcb(so
);
842 struct tcpcb
*tp
= NULL
;
845 if (so
->so_state
& SS_ISDISCONNECTED
) {
846 error
= ECONNABORTED
;
849 if (inp
== NULL
|| inp
->inp_state
== INPCB_STATE_DEAD
) {
853 else if (necp_socket_should_use_flow_divert(inp
)) {
862 TCP_LOG_ACCEPT(tp
, 0);
864 calculate_tcp_clock();
866 in6_mapped_peeraddr(so
, nam
);
867 COMMON_END(PRU_ACCEPT
);
872 * Mark the connection as being incapable of further output.
875 * EINVAL [COMMON_START]
876 * tcp_output:EADDRNOTAVAIL
878 * tcp_output:EMSGSIZE
879 * tcp_output:EHOSTUNREACH
880 * tcp_output:ENETUNREACH
881 * tcp_output:ENETDOWN
884 * tcp_output:EMSGSIZE
886 * tcp_output:??? [ignorable: mostly IPSEC/firewall/DLIL]
889 tcp_usr_shutdown(struct socket
*so
)
892 struct inpcb
*inp
= sotoinpcb(so
);
896 if (inp
== NULL
|| inp
->inp_state
== INPCB_STATE_DEAD
) {
903 * In case we got disconnected from the peer, or if this is
904 * a socket that is to be flow-diverted (but not yet).
911 || (necp_socket_should_use_flow_divert(inp
))
920 calculate_tcp_clock();
922 tp
= tcp_usrclosed(tp
);
924 /* A reset has been sent but socket exists, do not send FIN */
925 if ((so
->so_flags
& SOF_MP_SUBFLOW
) &&
926 (tp
) && (tp
->t_mpflags
& TMPF_RESET
)) {
931 /* Don't send a FIN yet */
932 if (tp
&& !(so
->so_state
& SS_ISDISCONNECTED
) &&
933 cfil_sock_data_pending(&so
->so_snd
)) {
936 #endif /* CONTENT_FILTER */
938 error
= tcp_output(tp
);
940 COMMON_END(PRU_SHUTDOWN
);
944 * After a receive, possibly send window update to peer.
947 tcp_usr_rcvd(struct socket
*so
, __unused
int flags
)
950 struct inpcb
*inp
= sotoinpcb(so
);
954 /* In case we got disconnected from the peer */
958 tcp_sbrcv_trim(tp
, &so
->so_rcv
);
961 * This tcp_output is solely there to trigger window-updates.
962 * However, we really do not want these window-updates while we
963 * are still in SYN_SENT or SYN_RECEIVED.
965 if (TCPS_HAVEESTABLISHED(tp
->t_state
)) {
970 cfil_sock_buf_update(&so
->so_rcv
);
971 #endif /* CONTENT_FILTER */
973 COMMON_END(PRU_RCVD
);
977 * Do a send by putting data in output queue and updating urgent
978 * marker if URG set. Possibly send more data. Unlike the other
979 * pru_*() routines, the mbuf chains are our responsibility. We
980 * must either enqueue them or free them. The other pru_* routines
981 * generally are caller-frees.
987 * tcp_connect:EADDRINUSE Address in use
988 * tcp_connect:EADDRNOTAVAIL Address not available.
989 * tcp_connect:EINVAL Invalid argument
990 * tcp_connect:EAFNOSUPPORT Address family not supported [notdef]
991 * tcp_connect:EACCES Permission denied
992 * tcp_connect:EAGAIN Resource unavailable, try again
993 * tcp_connect:EPERM Operation not permitted
994 * tcp_output:EADDRNOTAVAIL
996 * tcp_output:EMSGSIZE
997 * tcp_output:EHOSTUNREACH
998 * tcp_output:ENETUNREACH
999 * tcp_output:ENETDOWN
1002 * tcp_output:EMSGSIZE
1003 * tcp_output:ENOBUFS
1004 * tcp_output:??? [ignorable: mostly IPSEC/firewall/DLIL]
1005 * tcp6_connect:??? [IPV6 only]
1008 tcp_usr_send(struct socket
*so
, int flags
, struct mbuf
*m
,
1009 struct sockaddr
*nam
, struct mbuf
*control
, struct proc
*p
)
1012 struct inpcb
*inp
= sotoinpcb(so
);
1014 uint32_t msgpri
= MSG_PRI_DEFAULT
;
1015 uint32_t mpkl_len
= 0; /* length of mbuf chain */
1016 uint32_t mpkl_seq
; /* sequence number where new data is added */
1017 struct so_mpkl_send_info mpkl_send_info
= {};
1024 if (inp
== NULL
|| inp
->inp_state
== INPCB_STATE_DEAD
1026 || (necp_socket_should_use_flow_divert(inp
))
1030 * OOPS! we lost a race, the TCP session got reset after
1031 * we checked SS_CANTSENDMORE, eg: while doing uiomove or a
1032 * network interrupt in the non-splnet() section of sosend().
1037 if (control
!= NULL
) {
1043 error
= ECONNRESET
; /* XXX EPIPE? */
1052 isipv6
= nam
&& nam
->sa_family
== AF_INET6
;
1054 tp
= intotcpcb(inp
);
1057 calculate_tcp_clock();
1059 if (net_mpklog_enabled
) {
1060 mpkl_seq
= tp
->snd_una
+ so
->so_snd
.sb_cc
;
1062 mpkl_len
= m_length(m
);
1064 if (so
->so_flags1
& SOF1_MPKL_SEND_INFO
) {
1065 uuid_copy(mpkl_send_info
.mpkl_uuid
, so
->so_mpkl_send_uuid
);
1066 mpkl_send_info
.mpkl_proto
= so
->so_mpkl_send_proto
;
1070 if (control
!= NULL
) {
1071 if (so
->so_flags
& SOF_ENABLE_MSGS
) {
1072 /* Get the msg priority from control mbufs */
1073 error
= tcp_get_msg_priority(control
, &msgpri
);
1084 if (control
->m_len
> 0 && net_mpklog_enabled
) {
1085 error
= tcp_get_mpkl_send_info(control
, &mpkl_send_info
);
1087 * Intepretation of the returned code:
1088 * 0: client wants us to use value passed in SCM_MPKL_SEND_INFO
1089 * 1: SCM_MPKL_SEND_INFO was not present
1092 if (error
!= 0 && error
!= ENOMSG
) {
1103 * Silently drop unsupported ancillary data messages
1109 if (so
->so_flags
& SOF_ENABLE_MSGS
) {
1110 VERIFY(m
->m_flags
& M_PKTHDR
);
1111 m
->m_pkthdr
.msg_pri
= msgpri
;
1114 /* MPTCP sublow socket buffers must not be compressed */
1115 VERIFY(!(so
->so_flags
& SOF_MP_SUBFLOW
) ||
1116 (so
->so_snd
.sb_flags
& SB_NOCOMPRESS
));
1118 if (!(flags
& PRUS_OOB
) || (so
->so_flags1
& SOF1_PRECONNECT_DATA
)) {
1119 /* Call msg send if message delivery is enabled */
1120 if (so
->so_flags
& SOF_ENABLE_MSGS
) {
1121 sbappendmsg_snd(&so
->so_snd
, m
);
1123 sbappendstream(&so
->so_snd
, m
);
1126 if (nam
&& tp
->t_state
< TCPS_SYN_SENT
) {
1128 * Do implied connect if not yet connected,
1129 * initialize window to default value, and
1130 * initialize maxseg/maxopd using peer's cached
1135 error
= tcp6_connect(tp
, nam
, p
);
1138 error
= tcp_connect(tp
, nam
, p
);
1140 TCP_LOG_CONNECT(tp
, true, error
);
1143 tp
->snd_wnd
= TTCP_CLIENT_SND_WND
;
1144 tp
->max_sndwnd
= tp
->snd_wnd
;
1145 tcp_mss(tp
, -1, IFSCOPE_NONE
);
1147 TCP_LOG_CONNECT(tp
, true, error
);
1149 /* The sequence number of the data is past the SYN */
1150 mpkl_seq
= tp
->iss
+ 1;
1153 if (flags
& PRUS_EOF
) {
1155 * Close the send side of the connection after
1159 tp
= tcp_usrclosed(tp
);
1162 if (flags
& PRUS_MORETOCOME
) {
1163 tp
->t_flags
|= TF_MORETOCOME
;
1165 error
= tcp_output(tp
);
1166 if (flags
& PRUS_MORETOCOME
) {
1167 tp
->t_flags
&= ~TF_MORETOCOME
;
1171 if (sbspace(&so
->so_snd
) == 0) {
1172 /* if no space is left in sockbuf,
1173 * do not try to squeeze in OOB traffic */
1179 * According to RFC961 (Assigned Protocols),
1180 * the urgent pointer points to the last octet
1181 * of urgent data. We continue, however,
1182 * to consider it to indicate the first octet
1183 * of data past the urgent section.
1184 * Otherwise, snd_up should be one lower.
1186 sbappendstream(&so
->so_snd
, m
);
1187 if (nam
&& tp
->t_state
< TCPS_SYN_SENT
) {
1189 * Do implied connect if not yet connected,
1190 * initialize window to default value, and
1191 * initialize maxseg/maxopd using peer's cached
1196 error
= tcp6_connect(tp
, nam
, p
);
1199 error
= tcp_connect(tp
, nam
, p
);
1201 TCP_LOG_CONNECT(tp
, true, error
);
1204 tp
->snd_wnd
= TTCP_CLIENT_SND_WND
;
1205 tp
->max_sndwnd
= tp
->snd_wnd
;
1206 tcp_mss(tp
, -1, IFSCOPE_NONE
);
1208 TCP_LOG_CONNECT(tp
, true, error
);
1210 tp
->snd_up
= tp
->snd_una
+ so
->so_snd
.sb_cc
;
1211 tp
->t_flagsext
|= TF_FORCE
;
1212 error
= tcp_output(tp
);
1213 tp
->t_flagsext
&= ~TF_FORCE
;
1216 if (net_mpklog_enabled
&& (inp
= tp
->t_inpcb
) != NULL
&&
1217 ((inp
->inp_last_outifp
!= NULL
&&
1218 (inp
->inp_last_outifp
->if_xflags
& IFXF_MPK_LOG
)) ||
1219 (inp
->inp_boundifp
!= NULL
&&
1220 (inp
->inp_boundifp
->if_xflags
& IFXF_MPK_LOG
)))) {
1221 MPKL_TCP_SEND(tcp_mpkl_log_object
,
1222 mpkl_send_info
.mpkl_proto
, mpkl_send_info
.mpkl_uuid
,
1223 ntohs(inp
->inp_lport
), ntohs(inp
->inp_fport
),
1225 so
->last_pid
, so
->so_log_seqn
++);
1229 * We wait for the socket to successfully connect before returning.
1230 * This allows us to signal a timeout to the application.
1232 if (so
->so_state
& SS_ISCONNECTING
) {
1233 if (so
->so_state
& SS_NBIO
) {
1234 error
= EWOULDBLOCK
;
1236 error
= sbwait(&so
->so_snd
);
1240 COMMON_END((flags
& PRUS_OOB
) ? PRU_SENDOOB
:
1241 ((flags
& PRUS_EOF
) ? PRU_SEND_EOF
: PRU_SEND
));
1248 tcp_usr_abort(struct socket
*so
)
1251 struct inpcb
*inp
= sotoinpcb(so
);
1255 /* In case we got disconnected from the peer */
1259 tp
= tcp_drop(tp
, ECONNABORTED
);
1260 VERIFY(so
->so_usecount
> 0);
1262 COMMON_END(PRU_ABORT
);
1266 * Receive out-of-band data.
1268 * Returns: 0 Success
1269 * EINVAL [COMMON_START]
1274 tcp_usr_rcvoob(struct socket
*so
, struct mbuf
*m
, int flags
)
1277 struct inpcb
*inp
= sotoinpcb(so
);
1281 if ((so
->so_oobmark
== 0 &&
1282 (so
->so_state
& SS_RCVATMARK
) == 0) ||
1283 so
->so_options
& SO_OOBINLINE
||
1284 tp
->t_oobflags
& TCPOOB_HADDATA
) {
1288 if ((tp
->t_oobflags
& TCPOOB_HAVEDATA
) == 0) {
1289 error
= EWOULDBLOCK
;
1293 *mtod(m
, caddr_t
) = tp
->t_iobc
;
1294 so
->so_state
&= ~SS_RCVATMARK
;
1295 if ((flags
& MSG_PEEK
) == 0) {
1296 tp
->t_oobflags
^= (TCPOOB_HAVEDATA
| TCPOOB_HADDATA
);
1298 COMMON_END(PRU_RCVOOB
);
1302 tcp_usr_preconnect(struct socket
*so
)
1304 struct inpcb
*inp
= sotoinpcb(so
);
1308 if (necp_socket_should_use_flow_divert(inp
)) {
1309 /* May happen, if in tcp_usr_connect we did not had a chance
1310 * to set the usrreqs (due to some error). So, let's get out
1317 error
= tcp_output(sototcpcb(so
));
1319 soclearfastopen(so
);
1321 COMMON_END(PRU_PRECONNECT
);
1324 /* xxx - should be const */
1325 struct pr_usrreqs tcp_usrreqs
= {
1326 .pru_abort
= tcp_usr_abort
,
1327 .pru_accept
= tcp_usr_accept
,
1328 .pru_attach
= tcp_usr_attach
,
1329 .pru_bind
= tcp_usr_bind
,
1330 .pru_connect
= tcp_usr_connect
,
1331 .pru_connectx
= tcp_usr_connectx
,
1332 .pru_control
= in_control
,
1333 .pru_detach
= tcp_usr_detach
,
1334 .pru_disconnect
= tcp_usr_disconnect
,
1335 .pru_disconnectx
= tcp_usr_disconnectx
,
1336 .pru_listen
= tcp_usr_listen
,
1337 .pru_peeraddr
= in_getpeeraddr
,
1338 .pru_rcvd
= tcp_usr_rcvd
,
1339 .pru_rcvoob
= tcp_usr_rcvoob
,
1340 .pru_send
= tcp_usr_send
,
1341 .pru_shutdown
= tcp_usr_shutdown
,
1342 .pru_sockaddr
= in_getsockaddr
,
1343 .pru_sosend
= sosend
,
1344 .pru_soreceive
= soreceive
,
1345 .pru_preconnect
= tcp_usr_preconnect
,
1349 struct pr_usrreqs tcp6_usrreqs
= {
1350 .pru_abort
= tcp_usr_abort
,
1351 .pru_accept
= tcp6_usr_accept
,
1352 .pru_attach
= tcp_usr_attach
,
1353 .pru_bind
= tcp6_usr_bind
,
1354 .pru_connect
= tcp6_usr_connect
,
1355 .pru_connectx
= tcp6_usr_connectx
,
1356 .pru_control
= in6_control
,
1357 .pru_detach
= tcp_usr_detach
,
1358 .pru_disconnect
= tcp_usr_disconnect
,
1359 .pru_disconnectx
= tcp_usr_disconnectx
,
1360 .pru_listen
= tcp6_usr_listen
,
1361 .pru_peeraddr
= in6_mapped_peeraddr
,
1362 .pru_rcvd
= tcp_usr_rcvd
,
1363 .pru_rcvoob
= tcp_usr_rcvoob
,
1364 .pru_send
= tcp_usr_send
,
1365 .pru_shutdown
= tcp_usr_shutdown
,
1366 .pru_sockaddr
= in6_mapped_sockaddr
,
1367 .pru_sosend
= sosend
,
1368 .pru_soreceive
= soreceive
,
1369 .pru_preconnect
= tcp_usr_preconnect
,
1374 * Common subroutine to open a TCP connection to remote host specified
1375 * by struct sockaddr_in in mbuf *nam. Call in_pcbbind to assign a local
1376 * port number if needed. Call in_pcbladdr to do the routing and to choose
1377 * a local host address (interface). If there is an existing incarnation
1378 * of the same connection in TIME-WAIT state and if the remote host was
1379 * sending CC options and if the connection duration was < MSL, then
1380 * truncate the previous TIME-WAIT state and proceed.
1381 * Initialize connection parameters and enter SYN-SENT state.
1383 * Returns: 0 Success
1386 * in_pcbbind:EADDRNOTAVAIL Address not available.
1387 * in_pcbbind:EINVAL Invalid argument
1388 * in_pcbbind:EAFNOSUPPORT Address family not supported [notdef]
1389 * in_pcbbind:EACCES Permission denied
1390 * in_pcbbind:EADDRINUSE Address in use
1391 * in_pcbbind:EAGAIN Resource unavailable, try again
1392 * in_pcbbind:EPERM Operation not permitted
1393 * in_pcbladdr:EINVAL Invalid argument
1394 * in_pcbladdr:EAFNOSUPPORT Address family not supported
1395 * in_pcbladdr:EADDRNOTAVAIL Address not available
1398 tcp_connect(struct tcpcb
*tp
, struct sockaddr
*nam
, struct proc
*p
)
1400 struct inpcb
*inp
= tp
->t_inpcb
, *oinp
;
1401 struct socket
*so
= inp
->inp_socket
;
1403 struct sockaddr_in
*sin
= (struct sockaddr_in
*)(void *)nam
;
1404 struct in_addr laddr
;
1406 struct ifnet
*outif
= NULL
;
1408 if (inp
->inp_lport
== 0) {
1409 error
= in_pcbbind(inp
, NULL
, p
);
1416 * Cannot simply call in_pcbconnect, because there might be an
1417 * earlier incarnation of this same connection still in
1418 * TIME_WAIT state, creating an ADDRINUSE error.
1420 error
= in_pcbladdr(inp
, nam
, &laddr
, IFSCOPE_NONE
, &outif
, 0);
1425 socket_unlock(inp
->inp_socket
, 0);
1426 oinp
= in_pcblookup_hash(inp
->inp_pcbinfo
,
1427 sin
->sin_addr
, sin
->sin_port
,
1428 inp
->inp_laddr
.s_addr
!= INADDR_ANY
? inp
->inp_laddr
: laddr
,
1429 inp
->inp_lport
, 0, NULL
);
1431 socket_lock(inp
->inp_socket
, 0);
1433 if (oinp
!= inp
) { /* 4143933: avoid deadlock if inp == oinp */
1434 socket_lock(oinp
->inp_socket
, 1);
1436 if (in_pcb_checkstate(oinp
, WNT_RELEASE
, 1) == WNT_STOPUSING
) {
1438 socket_unlock(oinp
->inp_socket
, 1);
1443 if (oinp
!= inp
&& (otp
= intotcpcb(oinp
)) != NULL
&&
1444 otp
->t_state
== TCPS_TIME_WAIT
&&
1445 ((int)(tcp_now
- otp
->t_starttime
)) < tcp_msl
&&
1446 (otp
->t_flags
& TF_RCVD_CC
)) {
1447 otp
= tcp_close(otp
);
1449 printf("tcp_connect: inp=0x%llx err=EADDRINUSE\n",
1450 (uint64_t)VM_KERNEL_ADDRPERM(inp
));
1452 socket_unlock(oinp
->inp_socket
, 1);
1458 socket_unlock(oinp
->inp_socket
, 1);
1462 if ((inp
->inp_laddr
.s_addr
== INADDR_ANY
? laddr
.s_addr
:
1463 inp
->inp_laddr
.s_addr
) == sin
->sin_addr
.s_addr
&&
1464 inp
->inp_lport
== sin
->sin_port
) {
1468 if (!lck_rw_try_lock_exclusive(inp
->inp_pcbinfo
->ipi_lock
)) {
1469 /*lock inversion issue, mostly with udp multicast packets */
1470 socket_unlock(inp
->inp_socket
, 0);
1471 lck_rw_lock_exclusive(inp
->inp_pcbinfo
->ipi_lock
);
1472 socket_lock(inp
->inp_socket
, 0);
1474 if (inp
->inp_laddr
.s_addr
== INADDR_ANY
) {
1475 inp
->inp_laddr
= laddr
;
1476 /* no reference needed */
1477 inp
->inp_last_outifp
= outif
;
1479 inp
->inp_flags
|= INP_INADDR_ANY
;
1481 inp
->inp_faddr
= sin
->sin_addr
;
1482 inp
->inp_fport
= sin
->sin_port
;
1484 lck_rw_done(inp
->inp_pcbinfo
->ipi_lock
);
1486 if (inp
->inp_flowhash
== 0) {
1487 inp
->inp_flowhash
= inp_calc_flowhash(inp
);
1490 tcp_set_max_rwinscale(tp
, so
, outif
);
1493 tcpstat
.tcps_connattempt
++;
1494 tp
->t_state
= TCPS_SYN_SENT
;
1495 tp
->t_timer
[TCPT_KEEP
] = OFFSET_FROM_START(tp
, TCP_CONN_KEEPINIT(tp
));
1496 tp
->iss
= tcp_new_isn(tp
);
1497 tcp_sendseqinit(tp
);
1498 tp
->t_connect_time
= tcp_now
;
1499 if (nstat_collect
) {
1500 nstat_route_connect_attempt(inp
->inp_route
.ro_rt
);
1504 if (outif
!= NULL
) {
1505 ifnet_release(outif
);
1513 tcp6_connect(struct tcpcb
*tp
, struct sockaddr
*nam
, struct proc
*p
)
1515 struct inpcb
*inp
= tp
->t_inpcb
, *oinp
;
1516 struct socket
*so
= inp
->inp_socket
;
1518 struct sockaddr_in6
*sin6
= (struct sockaddr_in6
*)(void *)nam
;
1519 struct in6_addr addr6
;
1521 struct ifnet
*outif
= NULL
;
1523 if (inp
->inp_lport
== 0) {
1524 error
= in6_pcbbind(inp
, NULL
, p
);
1531 * Cannot simply call in_pcbconnect, because there might be an
1532 * earlier incarnation of this same connection still in
1533 * TIME_WAIT state, creating an ADDRINUSE error.
1535 * in6_pcbladdr() might return an ifp with its reference held
1536 * even in the error case, so make sure that it's released
1537 * whenever it's non-NULL.
1539 error
= in6_pcbladdr(inp
, nam
, &addr6
, &outif
);
1543 socket_unlock(inp
->inp_socket
, 0);
1544 oinp
= in6_pcblookup_hash(inp
->inp_pcbinfo
,
1545 &sin6
->sin6_addr
, sin6
->sin6_port
,
1546 IN6_IS_ADDR_UNSPECIFIED(&inp
->in6p_laddr
)
1549 inp
->inp_lport
, 0, NULL
);
1550 socket_lock(inp
->inp_socket
, 0);
1552 if (oinp
!= inp
&& (otp
= intotcpcb(oinp
)) != NULL
&&
1553 otp
->t_state
== TCPS_TIME_WAIT
&&
1554 ((int)(tcp_now
- otp
->t_starttime
)) < tcp_msl
&&
1555 (otp
->t_flags
& TF_RCVD_CC
)) {
1556 otp
= tcp_close(otp
);
1562 if (!lck_rw_try_lock_exclusive(inp
->inp_pcbinfo
->ipi_lock
)) {
1563 /*lock inversion issue, mostly with udp multicast packets */
1564 socket_unlock(inp
->inp_socket
, 0);
1565 lck_rw_lock_exclusive(inp
->inp_pcbinfo
->ipi_lock
);
1566 socket_lock(inp
->inp_socket
, 0);
1568 if (IN6_IS_ADDR_UNSPECIFIED(&inp
->in6p_laddr
)) {
1569 inp
->in6p_laddr
= addr6
;
1570 inp
->in6p_last_outifp
= outif
; /* no reference needed */
1571 inp
->in6p_flags
|= INP_IN6ADDR_ANY
;
1573 inp
->in6p_faddr
= sin6
->sin6_addr
;
1574 inp
->inp_fport
= sin6
->sin6_port
;
1575 if ((sin6
->sin6_flowinfo
& IPV6_FLOWINFO_MASK
) != 0) {
1576 inp
->inp_flow
= sin6
->sin6_flowinfo
;
1579 lck_rw_done(inp
->inp_pcbinfo
->ipi_lock
);
1581 if (inp
->inp_flowhash
== 0) {
1582 inp
->inp_flowhash
= inp_calc_flowhash(inp
);
1584 /* update flowinfo - RFC 6437 */
1585 if (inp
->inp_flow
== 0 && inp
->in6p_flags
& IN6P_AUTOFLOWLABEL
) {
1586 inp
->inp_flow
&= ~IPV6_FLOWLABEL_MASK
;
1588 (htonl(inp
->inp_flowhash
) & IPV6_FLOWLABEL_MASK
);
1591 tcp_set_max_rwinscale(tp
, so
, outif
);
1594 tcpstat
.tcps_connattempt
++;
1595 tp
->t_state
= TCPS_SYN_SENT
;
1596 tp
->t_timer
[TCPT_KEEP
] = OFFSET_FROM_START(tp
,
1597 TCP_CONN_KEEPINIT(tp
));
1598 tp
->iss
= tcp_new_isn(tp
);
1599 tcp_sendseqinit(tp
);
1600 tp
->t_connect_time
= tcp_now
;
1601 if (nstat_collect
) {
1602 nstat_route_connect_attempt(inp
->inp_route
.ro_rt
);
1606 if (outif
!= NULL
) {
1607 ifnet_release(outif
);
1615 * Export TCP internal state information via a struct tcp_info
1618 tcp_fill_info(struct tcpcb
*tp
, struct tcp_info
*ti
)
1620 struct inpcb
*inp
= tp
->t_inpcb
;
1622 bzero(ti
, sizeof(*ti
));
1624 ti
->tcpi_state
= tp
->t_state
;
1625 ti
->tcpi_flowhash
= inp
->inp_flowhash
;
1627 if (tp
->t_state
> TCPS_LISTEN
) {
1628 if (TSTMP_SUPPORTED(tp
)) {
1629 ti
->tcpi_options
|= TCPI_OPT_TIMESTAMPS
;
1631 if (SACK_ENABLED(tp
)) {
1632 ti
->tcpi_options
|= TCPI_OPT_SACK
;
1634 if (TCP_WINDOW_SCALE_ENABLED(tp
)) {
1635 ti
->tcpi_options
|= TCPI_OPT_WSCALE
;
1636 ti
->tcpi_snd_wscale
= tp
->snd_scale
;
1637 ti
->tcpi_rcv_wscale
= tp
->rcv_scale
;
1639 if (TCP_ECN_ENABLED(tp
)) {
1640 ti
->tcpi_options
|= TCPI_OPT_ECN
;
1643 /* Are we in retranmission episode */
1644 if (IN_FASTRECOVERY(tp
) || tp
->t_rxtshift
> 0) {
1645 ti
->tcpi_flags
|= TCPI_FLAG_LOSSRECOVERY
;
1648 if (tp
->t_flags
& TF_STREAMING_ON
) {
1649 ti
->tcpi_flags
|= TCPI_FLAG_STREAMING_ON
;
1652 ti
->tcpi_rto
= tp
->t_timer
[TCPT_REXMT
] ? tp
->t_rxtcur
: 0;
1653 ti
->tcpi_snd_mss
= tp
->t_maxseg
;
1654 ti
->tcpi_rcv_mss
= tp
->t_maxseg
;
1656 ti
->tcpi_rttcur
= tp
->t_rttcur
;
1657 ti
->tcpi_srtt
= tp
->t_srtt
>> TCP_RTT_SHIFT
;
1658 ti
->tcpi_rttvar
= tp
->t_rttvar
>> TCP_RTTVAR_SHIFT
;
1659 ti
->tcpi_rttbest
= tp
->t_rttbest
>> TCP_RTT_SHIFT
;
1661 ti
->tcpi_snd_ssthresh
= tp
->snd_ssthresh
;
1662 ti
->tcpi_snd_cwnd
= tp
->snd_cwnd
;
1663 ti
->tcpi_snd_sbbytes
= inp
->inp_socket
->so_snd
.sb_cc
;
1665 ti
->tcpi_rcv_space
= tp
->rcv_wnd
;
1667 ti
->tcpi_snd_wnd
= tp
->snd_wnd
;
1668 ti
->tcpi_snd_nxt
= tp
->snd_nxt
;
1669 ti
->tcpi_rcv_nxt
= tp
->rcv_nxt
;
1671 /* convert bytes/msec to bits/sec */
1672 if ((tp
->t_flagsext
& TF_MEASURESNDBW
) != 0 &&
1673 tp
->t_bwmeas
!= NULL
) {
1674 ti
->tcpi_snd_bw
= (tp
->t_bwmeas
->bw_sndbw
* 8000);
1677 ti
->tcpi_last_outif
= (tp
->t_inpcb
->inp_last_outifp
== NULL
) ? 0 :
1678 tp
->t_inpcb
->inp_last_outifp
->if_index
;
1680 //atomic_get_64(ti->tcpi_txbytes, &inp->inp_stat->txbytes);
1681 ti
->tcpi_txpackets
= inp
->inp_stat
->txpackets
;
1682 ti
->tcpi_txbytes
= inp
->inp_stat
->txbytes
;
1683 ti
->tcpi_txretransmitbytes
= tp
->t_stat
.txretransmitbytes
;
1684 ti
->tcpi_txretransmitpackets
= tp
->t_stat
.rxmitpkts
;
1685 ti
->tcpi_txunacked
= tp
->snd_max
- tp
->snd_una
;
1687 //atomic_get_64(ti->tcpi_rxbytes, &inp->inp_stat->rxbytes);
1688 ti
->tcpi_rxpackets
= inp
->inp_stat
->rxpackets
;
1689 ti
->tcpi_rxbytes
= inp
->inp_stat
->rxbytes
;
1690 ti
->tcpi_rxduplicatebytes
= tp
->t_stat
.rxduplicatebytes
;
1691 ti
->tcpi_rxoutoforderbytes
= tp
->t_stat
.rxoutoforderbytes
;
1693 if (tp
->t_state
> TCPS_LISTEN
) {
1694 ti
->tcpi_synrexmits
= tp
->t_stat
.rxmitsyns
;
1696 ti
->tcpi_cell_rxpackets
= inp
->inp_cstat
->rxpackets
;
1697 ti
->tcpi_cell_rxbytes
= inp
->inp_cstat
->rxbytes
;
1698 ti
->tcpi_cell_txpackets
= inp
->inp_cstat
->txpackets
;
1699 ti
->tcpi_cell_txbytes
= inp
->inp_cstat
->txbytes
;
1701 ti
->tcpi_wifi_rxpackets
= inp
->inp_wstat
->rxpackets
;
1702 ti
->tcpi_wifi_rxbytes
= inp
->inp_wstat
->rxbytes
;
1703 ti
->tcpi_wifi_txpackets
= inp
->inp_wstat
->txpackets
;
1704 ti
->tcpi_wifi_txbytes
= inp
->inp_wstat
->txbytes
;
1706 ti
->tcpi_wired_rxpackets
= inp
->inp_Wstat
->rxpackets
;
1707 ti
->tcpi_wired_rxbytes
= inp
->inp_Wstat
->rxbytes
;
1708 ti
->tcpi_wired_txpackets
= inp
->inp_Wstat
->txpackets
;
1709 ti
->tcpi_wired_txbytes
= inp
->inp_Wstat
->txbytes
;
1710 tcp_get_connectivity_status(tp
, &ti
->tcpi_connstatus
);
1712 ti
->tcpi_tfo_syn_data_rcv
= !!(tp
->t_tfo_stats
& TFO_S_SYNDATA_RCV
);
1713 ti
->tcpi_tfo_cookie_req_rcv
= !!(tp
->t_tfo_stats
& TFO_S_COOKIEREQ_RECV
);
1714 ti
->tcpi_tfo_cookie_sent
= !!(tp
->t_tfo_stats
& TFO_S_COOKIE_SENT
);
1715 ti
->tcpi_tfo_cookie_invalid
= !!(tp
->t_tfo_stats
& TFO_S_COOKIE_INVALID
);
1717 ti
->tcpi_tfo_cookie_req
= !!(tp
->t_tfo_stats
& TFO_S_COOKIE_REQ
);
1718 ti
->tcpi_tfo_cookie_rcv
= !!(tp
->t_tfo_stats
& TFO_S_COOKIE_RCV
);
1719 ti
->tcpi_tfo_syn_data_sent
= !!(tp
->t_tfo_stats
& TFO_S_SYN_DATA_SENT
);
1720 ti
->tcpi_tfo_syn_data_acked
= !!(tp
->t_tfo_stats
& TFO_S_SYN_DATA_ACKED
);
1721 ti
->tcpi_tfo_syn_loss
= !!(tp
->t_tfo_stats
& TFO_S_SYN_LOSS
);
1722 ti
->tcpi_tfo_cookie_wrong
= !!(tp
->t_tfo_stats
& TFO_S_COOKIE_WRONG
);
1723 ti
->tcpi_tfo_no_cookie_rcv
= !!(tp
->t_tfo_stats
& TFO_S_NO_COOKIE_RCV
);
1724 ti
->tcpi_tfo_heuristics_disable
= !!(tp
->t_tfo_stats
& TFO_S_HEURISTICS_DISABLE
);
1725 ti
->tcpi_tfo_send_blackhole
= !!(tp
->t_tfo_stats
& TFO_S_SEND_BLACKHOLE
);
1726 ti
->tcpi_tfo_recv_blackhole
= !!(tp
->t_tfo_stats
& TFO_S_RECV_BLACKHOLE
);
1727 ti
->tcpi_tfo_onebyte_proxy
= !!(tp
->t_tfo_stats
& TFO_S_ONE_BYTE_PROXY
);
1729 ti
->tcpi_ecn_client_setup
= !!(tp
->ecn_flags
& TE_SETUPSENT
);
1730 ti
->tcpi_ecn_server_setup
= !!(tp
->ecn_flags
& TE_SETUPRECEIVED
);
1731 ti
->tcpi_ecn_success
= (tp
->ecn_flags
& TE_ECN_ON
) == TE_ECN_ON
? 1 : 0;
1732 ti
->tcpi_ecn_lost_syn
= !!(tp
->ecn_flags
& TE_LOST_SYN
);
1733 ti
->tcpi_ecn_lost_synack
= !!(tp
->ecn_flags
& TE_LOST_SYNACK
);
1735 ti
->tcpi_local_peer
= !!(tp
->t_flags
& TF_LOCAL
);
1737 if (tp
->t_inpcb
->inp_last_outifp
!= NULL
) {
1738 if (IFNET_IS_CELLULAR(tp
->t_inpcb
->inp_last_outifp
)) {
1739 ti
->tcpi_if_cell
= 1;
1741 if (IFNET_IS_WIFI(tp
->t_inpcb
->inp_last_outifp
)) {
1742 ti
->tcpi_if_wifi
= 1;
1744 if (IFNET_IS_WIRED(tp
->t_inpcb
->inp_last_outifp
)) {
1745 ti
->tcpi_if_wired
= 1;
1747 if (IFNET_IS_WIFI_INFRA(tp
->t_inpcb
->inp_last_outifp
)) {
1748 ti
->tcpi_if_wifi_infra
= 1;
1750 if (tp
->t_inpcb
->inp_last_outifp
->if_eflags
& IFEF_AWDL
) {
1751 ti
->tcpi_if_wifi_awdl
= 1;
1754 if (tp
->tcp_cc_index
== TCP_CC_ALGO_BACKGROUND_INDEX
) {
1755 ti
->tcpi_snd_background
= 1;
1757 if (tcp_recv_bg
== 1 ||
1758 IS_TCP_RECV_BG(tp
->t_inpcb
->inp_socket
)) {
1759 ti
->tcpi_rcv_background
= 1;
1762 ti
->tcpi_ecn_recv_ce
= tp
->t_ecn_recv_ce
;
1763 ti
->tcpi_ecn_recv_cwr
= tp
->t_ecn_recv_cwr
;
1765 ti
->tcpi_rcvoopack
= tp
->t_rcvoopack
;
1766 ti
->tcpi_pawsdrop
= tp
->t_pawsdrop
;
1767 ti
->tcpi_sack_recovery_episode
= tp
->t_sack_recovery_episode
;
1768 ti
->tcpi_reordered_pkts
= tp
->t_reordered_pkts
;
1769 ti
->tcpi_dsack_sent
= tp
->t_dsack_sent
;
1770 ti
->tcpi_dsack_recvd
= tp
->t_dsack_recvd
;
1774 __private_extern__ errno_t
1775 tcp_fill_info_for_info_tuple(struct info_tuple
*itpl
, struct tcp_info
*ti
)
1777 struct inpcbinfo
*pcbinfo
= NULL
;
1778 struct inpcb
*inp
= NULL
;
1782 if (itpl
->itpl_proto
== IPPROTO_TCP
) {
1788 if (itpl
->itpl_local_sa
.sa_family
== AF_INET
&&
1789 itpl
->itpl_remote_sa
.sa_family
== AF_INET
) {
1790 inp
= in_pcblookup_hash(pcbinfo
,
1791 itpl
->itpl_remote_sin
.sin_addr
,
1792 itpl
->itpl_remote_sin
.sin_port
,
1793 itpl
->itpl_local_sin
.sin_addr
,
1794 itpl
->itpl_local_sin
.sin_port
,
1796 } else if (itpl
->itpl_local_sa
.sa_family
== AF_INET6
&&
1797 itpl
->itpl_remote_sa
.sa_family
== AF_INET6
) {
1798 struct in6_addr ina6_local
;
1799 struct in6_addr ina6_remote
;
1801 ina6_local
= itpl
->itpl_local_sin6
.sin6_addr
;
1802 if (IN6_IS_SCOPE_LINKLOCAL(&ina6_local
) &&
1803 itpl
->itpl_local_sin6
.sin6_scope_id
) {
1804 ina6_local
.s6_addr16
[1] = htons(itpl
->itpl_local_sin6
.sin6_scope_id
);
1807 ina6_remote
= itpl
->itpl_remote_sin6
.sin6_addr
;
1808 if (IN6_IS_SCOPE_LINKLOCAL(&ina6_remote
) &&
1809 itpl
->itpl_remote_sin6
.sin6_scope_id
) {
1810 ina6_remote
.s6_addr16
[1] = htons(itpl
->itpl_remote_sin6
.sin6_scope_id
);
1813 inp
= in6_pcblookup_hash(pcbinfo
,
1815 itpl
->itpl_remote_sin6
.sin6_port
,
1817 itpl
->itpl_local_sin6
.sin6_port
,
1822 if (inp
== NULL
|| (so
= inp
->inp_socket
) == NULL
) {
1827 if (in_pcb_checkstate(inp
, WNT_RELEASE
, 1) == WNT_STOPUSING
) {
1828 socket_unlock(so
, 0);
1831 tp
= intotcpcb(inp
);
1833 tcp_fill_info(tp
, ti
);
1834 socket_unlock(so
, 0);
1840 tcp_connection_fill_info(struct tcpcb
*tp
, struct tcp_connection_info
*tci
)
1842 struct inpcb
*inp
= tp
->t_inpcb
;
1844 bzero(tci
, sizeof(*tci
));
1845 tci
->tcpi_state
= tp
->t_state
;
1846 if (tp
->t_state
> TCPS_LISTEN
) {
1847 if (TSTMP_SUPPORTED(tp
)) {
1848 tci
->tcpi_options
|= TCPCI_OPT_TIMESTAMPS
;
1850 if (SACK_ENABLED(tp
)) {
1851 tci
->tcpi_options
|= TCPCI_OPT_SACK
;
1853 if (TCP_WINDOW_SCALE_ENABLED(tp
)) {
1854 tci
->tcpi_options
|= TCPCI_OPT_WSCALE
;
1855 tci
->tcpi_snd_wscale
= tp
->snd_scale
;
1856 tci
->tcpi_rcv_wscale
= tp
->rcv_scale
;
1858 if (TCP_ECN_ENABLED(tp
)) {
1859 tci
->tcpi_options
|= TCPCI_OPT_ECN
;
1861 if (IN_FASTRECOVERY(tp
) || tp
->t_rxtshift
> 0) {
1862 tci
->tcpi_flags
|= TCPCI_FLAG_LOSSRECOVERY
;
1864 if (tp
->t_flagsext
& TF_PKTS_REORDERED
) {
1865 tci
->tcpi_flags
|= TCPCI_FLAG_REORDERING_DETECTED
;
1867 tci
->tcpi_rto
= (tp
->t_timer
[TCPT_REXMT
] > 0) ?
1869 tci
->tcpi_maxseg
= tp
->t_maxseg
;
1870 tci
->tcpi_snd_ssthresh
= tp
->snd_ssthresh
;
1871 tci
->tcpi_snd_cwnd
= tp
->snd_cwnd
;
1872 tci
->tcpi_snd_wnd
= tp
->snd_wnd
;
1873 tci
->tcpi_snd_sbbytes
= inp
->inp_socket
->so_snd
.sb_cc
;
1874 tci
->tcpi_rcv_wnd
= tp
->rcv_wnd
;
1875 tci
->tcpi_rttcur
= tp
->t_rttcur
;
1876 tci
->tcpi_srtt
= (tp
->t_srtt
>> TCP_RTT_SHIFT
);
1877 tci
->tcpi_rttvar
= (tp
->t_rttvar
>> TCP_RTTVAR_SHIFT
);
1878 tci
->tcpi_txpackets
= inp
->inp_stat
->txpackets
;
1879 tci
->tcpi_txbytes
= inp
->inp_stat
->txbytes
;
1880 tci
->tcpi_txretransmitbytes
= tp
->t_stat
.txretransmitbytes
;
1881 tci
->tcpi_txretransmitpackets
= tp
->t_stat
.rxmitpkts
;
1882 tci
->tcpi_rxpackets
= inp
->inp_stat
->rxpackets
;
1883 tci
->tcpi_rxbytes
= inp
->inp_stat
->rxbytes
;
1884 tci
->tcpi_rxoutoforderbytes
= tp
->t_stat
.rxoutoforderbytes
;
1886 tci
->tcpi_tfo_syn_data_rcv
= !!(tp
->t_tfo_stats
& TFO_S_SYNDATA_RCV
);
1887 tci
->tcpi_tfo_cookie_req_rcv
= !!(tp
->t_tfo_stats
& TFO_S_COOKIEREQ_RECV
);
1888 tci
->tcpi_tfo_cookie_sent
= !!(tp
->t_tfo_stats
& TFO_S_COOKIE_SENT
);
1889 tci
->tcpi_tfo_cookie_invalid
= !!(tp
->t_tfo_stats
& TFO_S_COOKIE_INVALID
);
1890 tci
->tcpi_tfo_cookie_req
= !!(tp
->t_tfo_stats
& TFO_S_COOKIE_REQ
);
1891 tci
->tcpi_tfo_cookie_rcv
= !!(tp
->t_tfo_stats
& TFO_S_COOKIE_RCV
);
1892 tci
->tcpi_tfo_syn_data_sent
= !!(tp
->t_tfo_stats
& TFO_S_SYN_DATA_SENT
);
1893 tci
->tcpi_tfo_syn_data_acked
= !!(tp
->t_tfo_stats
& TFO_S_SYN_DATA_ACKED
);
1894 tci
->tcpi_tfo_syn_loss
= !!(tp
->t_tfo_stats
& TFO_S_SYN_LOSS
);
1895 tci
->tcpi_tfo_cookie_wrong
= !!(tp
->t_tfo_stats
& TFO_S_COOKIE_WRONG
);
1896 tci
->tcpi_tfo_no_cookie_rcv
= !!(tp
->t_tfo_stats
& TFO_S_NO_COOKIE_RCV
);
1897 tci
->tcpi_tfo_heuristics_disable
= !!(tp
->t_tfo_stats
& TFO_S_HEURISTICS_DISABLE
);
1898 tci
->tcpi_tfo_send_blackhole
= !!(tp
->t_tfo_stats
& TFO_S_SEND_BLACKHOLE
);
1899 tci
->tcpi_tfo_recv_blackhole
= !!(tp
->t_tfo_stats
& TFO_S_RECV_BLACKHOLE
);
1900 tci
->tcpi_tfo_onebyte_proxy
= !!(tp
->t_tfo_stats
& TFO_S_ONE_BYTE_PROXY
);
1905 __private_extern__
int
1906 tcp_sysctl_info(__unused
struct sysctl_oid
*oidp
, __unused
void *arg1
, __unused
int arg2
, struct sysctl_req
*req
)
1909 struct tcp_info ti
= {};
1910 struct info_tuple itpl
;
1912 if (req
->newptr
== USER_ADDR_NULL
) {
1915 if (req
->newlen
< sizeof(struct info_tuple
)) {
1918 error
= SYSCTL_IN(req
, &itpl
, sizeof(struct info_tuple
));
1922 error
= tcp_fill_info_for_info_tuple(&itpl
, &ti
);
1926 error
= SYSCTL_OUT(req
, &ti
, sizeof(struct tcp_info
));
1935 tcp_lookup_peer_pid_locked(struct socket
*so
, pid_t
*out_pid
)
1937 int error
= EHOSTUNREACH
;
1939 if ((so
->so_state
& SS_ISCONNECTED
) == 0) {
1943 struct inpcb
*inp
= (struct inpcb
*)so
->so_pcb
;
1944 uint16_t lport
= inp
->inp_lport
;
1945 uint16_t fport
= inp
->inp_fport
;
1946 struct inpcb
*finp
= NULL
;
1947 struct in6_addr laddr6
, faddr6
;
1948 struct in_addr laddr4
, faddr4
;
1950 if (inp
->inp_vflag
& INP_IPV6
) {
1951 laddr6
= inp
->in6p_laddr
;
1952 faddr6
= inp
->in6p_faddr
;
1953 } else if (inp
->inp_vflag
& INP_IPV4
) {
1954 laddr4
= inp
->inp_laddr
;
1955 faddr4
= inp
->inp_faddr
;
1958 socket_unlock(so
, 0);
1959 if (inp
->inp_vflag
& INP_IPV6
) {
1960 finp
= in6_pcblookup_hash(&tcbinfo
, &laddr6
, lport
, &faddr6
, fport
, 0, NULL
);
1961 } else if (inp
->inp_vflag
& INP_IPV4
) {
1962 finp
= in_pcblookup_hash(&tcbinfo
, laddr4
, lport
, faddr4
, fport
, 0, NULL
);
1966 *out_pid
= finp
->inp_socket
->last_pid
;
1968 in_pcb_checkstate(finp
, WNT_RELEASE
, 0);
1976 tcp_getconninfo(struct socket
*so
, struct conninfo_tcp
*tcp_ci
)
1978 (void) tcp_lookup_peer_pid_locked(so
, &tcp_ci
->tcpci_peer_pid
);
1979 tcp_fill_info(sototcpcb(so
), &tcp_ci
->tcpci_tcp_info
);
1983 tcp_clear_keep_alive_offload(struct socket
*so
)
1988 inp
= sotoinpcb(so
);
1993 if ((inp
->inp_flags2
& INP2_KEEPALIVE_OFFLOAD
) == 0) {
1997 ifp
= inp
->inp_boundifp
!= NULL
? inp
->inp_boundifp
:
1998 inp
->inp_last_outifp
;
2000 panic("%s: so %p inp %p ifp NULL",
2004 ifnet_lock_exclusive(ifp
);
2006 if (ifp
->if_tcp_kao_cnt
== 0) {
2007 panic("%s: so %p inp %p ifp %p if_tcp_kao_cnt == 0",
2008 __func__
, so
, inp
, ifp
);
2010 ifp
->if_tcp_kao_cnt
--;
2011 inp
->inp_flags2
&= ~INP2_KEEPALIVE_OFFLOAD
;
2013 ifnet_lock_done(ifp
);
2017 tcp_set_keep_alive_offload(struct socket
*so
, struct proc
*proc
)
2023 inp
= sotoinpcb(so
);
2027 if ((inp
->inp_flags2
& INP2_KEEPALIVE_OFFLOAD
) != 0) {
2031 ifp
= inp
->inp_boundifp
!= NULL
? inp
->inp_boundifp
:
2032 inp
->inp_last_outifp
;
2035 os_log_info(OS_LOG_DEFAULT
,
2036 "%s: error %d for proc %s[%u] out ifp is not set\n",
2038 proc
!= NULL
? proc
->p_comm
: "kernel",
2039 proc
!= NULL
? proc
->p_pid
: 0);
2043 error
= if_get_tcp_kao_max(ifp
);
2048 ifnet_lock_exclusive(ifp
);
2049 if (ifp
->if_tcp_kao_cnt
< ifp
->if_tcp_kao_max
) {
2050 ifp
->if_tcp_kao_cnt
++;
2051 inp
->inp_flags2
|= INP2_KEEPALIVE_OFFLOAD
;
2053 error
= ETOOMANYREFS
;
2054 os_log_info(OS_LOG_DEFAULT
,
2055 "%s: error %d for proc %s[%u] if_tcp_kao_max %u\n",
2057 proc
!= NULL
? proc
->p_comm
: "kernel",
2058 proc
!= NULL
? proc
->p_pid
: 0,
2059 ifp
->if_tcp_kao_max
);
2061 ifnet_lock_done(ifp
);
2067 * The new sockopt interface makes it possible for us to block in the
2068 * copyin/out step (if we take a page fault). Taking a page fault at
2069 * splnet() is probably a Bad Thing. (Since sockets and pcbs both now
2070 * use TSM, there probably isn't any need for this function to run at
2071 * splnet() any more. This needs more examination.)
2074 tcp_ctloutput(struct socket
*so
, struct sockopt
*sopt
)
2076 int error
= 0, opt
= 0, optval
= 0;
2080 inp
= sotoinpcb(so
);
2084 /* Allow <SOL_SOCKET,SO_FLUSH/SO_TRAFFIC_MGT_BACKGROUND> at this level */
2085 if (sopt
->sopt_level
!= IPPROTO_TCP
&&
2086 !(sopt
->sopt_level
== SOL_SOCKET
&& (sopt
->sopt_name
== SO_FLUSH
||
2087 sopt
->sopt_name
== SO_TRAFFIC_MGT_BACKGROUND
))) {
2089 if (SOCK_CHECK_DOM(so
, PF_INET6
)) {
2090 error
= ip6_ctloutput(so
, sopt
);
2093 error
= ip_ctloutput(so
, sopt
);
2096 tp
= intotcpcb(inp
);
2101 calculate_tcp_clock();
2103 switch (sopt
->sopt_dir
) {
2105 switch (sopt
->sopt_name
) {
2109 error
= sooptcopyin(sopt
, &optval
, sizeof optval
,
2115 switch (sopt
->sopt_name
) {
2126 opt
= 0; /* dead code to fool gcc */
2133 tp
->t_flags
&= ~opt
;
2136 case TCP_RXT_FINDROP
:
2137 case TCP_NOTIMEWAIT
:
2138 error
= sooptcopyin(sopt
, &optval
, sizeof optval
,
2143 switch (sopt
->sopt_name
) {
2144 case TCP_RXT_FINDROP
:
2145 opt
= TF_RXTFINDROP
;
2147 case TCP_NOTIMEWAIT
:
2148 opt
= TF_NOTIMEWAIT
;
2155 tp
->t_flagsext
|= opt
;
2157 tp
->t_flagsext
&= ~opt
;
2160 case TCP_MEASURE_SND_BW
:
2161 error
= sooptcopyin(sopt
, &optval
, sizeof optval
,
2166 opt
= TF_MEASURESNDBW
;
2168 if (tp
->t_bwmeas
== NULL
) {
2169 tp
->t_bwmeas
= tcp_bwmeas_alloc(tp
);
2170 if (tp
->t_bwmeas
== NULL
) {
2175 tp
->t_flagsext
|= opt
;
2177 tp
->t_flagsext
&= ~opt
;
2178 /* Reset snd bw measurement state */
2179 tp
->t_flagsext
&= ~(TF_BWMEAS_INPROGRESS
);
2180 if (tp
->t_bwmeas
!= NULL
) {
2181 tcp_bwmeas_free(tp
);
2185 case TCP_MEASURE_BW_BURST
: {
2186 struct tcp_measure_bw_burst in
;
2187 uint32_t minpkts
, maxpkts
;
2188 bzero(&in
, sizeof(in
));
2190 error
= sooptcopyin(sopt
, &in
, sizeof(in
),
2195 if ((tp
->t_flagsext
& TF_MEASURESNDBW
) == 0 ||
2196 tp
->t_bwmeas
== NULL
) {
2200 minpkts
= (in
.min_burst_size
!= 0) ? in
.min_burst_size
:
2201 tp
->t_bwmeas
->bw_minsizepkts
;
2202 maxpkts
= (in
.max_burst_size
!= 0) ? in
.max_burst_size
:
2203 tp
->t_bwmeas
->bw_maxsizepkts
;
2204 if (minpkts
> maxpkts
) {
2208 tp
->t_bwmeas
->bw_minsizepkts
= minpkts
;
2209 tp
->t_bwmeas
->bw_maxsizepkts
= maxpkts
;
2210 tp
->t_bwmeas
->bw_minsize
= (minpkts
* tp
->t_maxseg
);
2211 tp
->t_bwmeas
->bw_maxsize
= (maxpkts
* tp
->t_maxseg
);
2215 error
= sooptcopyin(sopt
, &optval
, sizeof optval
,
2221 if (optval
> 0 && optval
<= tp
->t_maxseg
&&
2222 optval
+ 40 >= tcp_minmss
) {
2223 tp
->t_maxseg
= optval
;
2230 error
= sooptcopyin(sopt
, &optval
, sizeof optval
,
2235 if (optval
< 0 || optval
> UINT32_MAX
/ TCP_RETRANSHZ
) {
2238 tp
->t_keepidle
= optval
* TCP_RETRANSHZ
;
2239 /* reset the timer to new value */
2240 tp
->t_timer
[TCPT_KEEP
] = OFFSET_FROM_START(tp
,
2241 TCP_CONN_KEEPIDLE(tp
));
2242 tcp_check_timer_state(tp
);
2246 case TCP_CONNECTIONTIMEOUT
:
2247 error
= sooptcopyin(sopt
, &optval
, sizeof optval
,
2252 if (optval
< 0 || optval
> UINT32_MAX
/ TCP_RETRANSHZ
) {
2255 tp
->t_keepinit
= optval
* TCP_RETRANSHZ
;
2256 if (tp
->t_state
== TCPS_SYN_RECEIVED
||
2257 tp
->t_state
== TCPS_SYN_SENT
) {
2258 tp
->t_timer
[TCPT_KEEP
] = OFFSET_FROM_START(tp
,
2259 TCP_CONN_KEEPINIT(tp
));
2260 tcp_check_timer_state(tp
);
2266 error
= sooptcopyin(sopt
, &optval
, sizeof(optval
),
2271 if (optval
< 0 || optval
> UINT32_MAX
/ TCP_RETRANSHZ
) {
2274 tp
->t_keepintvl
= optval
* TCP_RETRANSHZ
;
2275 if (tp
->t_state
== TCPS_FIN_WAIT_2
&&
2276 TCP_CONN_MAXIDLE(tp
) > 0) {
2277 tp
->t_timer
[TCPT_2MSL
] = OFFSET_FROM_START(tp
,
2278 TCP_CONN_MAXIDLE(tp
));
2279 tcp_check_timer_state(tp
);
2285 error
= sooptcopyin(sopt
, &optval
, sizeof(optval
),
2290 if (optval
< 0 || optval
> INT32_MAX
) {
2293 tp
->t_keepcnt
= optval
;
2294 if (tp
->t_state
== TCPS_FIN_WAIT_2
&&
2295 TCP_CONN_MAXIDLE(tp
) > 0) {
2296 tp
->t_timer
[TCPT_2MSL
] = OFFSET_FROM_START(tp
,
2297 TCP_CONN_MAXIDLE(tp
));
2298 tcp_check_timer_state(tp
);
2303 case TCP_KEEPALIVE_OFFLOAD
:
2304 if ((error
= priv_check_cred(kauth_cred_get(),
2305 PRIV_NETINET_TCP_KA_OFFLOAD
, 0)) != 0) {
2308 error
= sooptcopyin(sopt
, &optval
, sizeof(optval
),
2313 if (optval
< 0 || optval
> INT32_MAX
) {
2318 error
= tcp_set_keep_alive_offload(so
,
2321 tcp_clear_keep_alive_offload(so
);
2325 case PERSIST_TIMEOUT
:
2326 error
= sooptcopyin(sopt
, &optval
, sizeof optval
,
2334 tp
->t_persist_timeout
= optval
* TCP_RETRANSHZ
;
2337 case TCP_RXT_CONNDROPTIME
:
2338 error
= sooptcopyin(sopt
, &optval
, sizeof(optval
),
2346 tp
->t_rxt_conndroptime
= optval
* TCP_RETRANSHZ
;
2349 case TCP_NOTSENT_LOWAT
:
2350 error
= sooptcopyin(sopt
, &optval
, sizeof(optval
),
2360 so
->so_flags
&= ~(SOF_NOTSENT_LOWAT
);
2361 tp
->t_notsent_lowat
= 0;
2363 so
->so_flags
|= SOF_NOTSENT_LOWAT
;
2364 tp
->t_notsent_lowat
= optval
;
2368 case TCP_ADAPTIVE_READ_TIMEOUT
:
2369 error
= sooptcopyin(sopt
, &optval
, sizeof(optval
),
2375 optval
> TCP_ADAPTIVE_TIMEOUT_MAX
) {
2378 } else if (optval
== 0) {
2379 tp
->t_adaptive_rtimo
= 0;
2380 tcp_keepalive_reset(tp
);
2383 mptcp_reset_keepalive(tp
);
2386 tp
->t_adaptive_rtimo
= optval
;
2389 case TCP_ADAPTIVE_WRITE_TIMEOUT
:
2390 error
= sooptcopyin(sopt
, &optval
, sizeof(optval
),
2396 optval
> TCP_ADAPTIVE_TIMEOUT_MAX
) {
2400 tp
->t_adaptive_wtimo
= optval
;
2403 case TCP_ENABLE_MSGS
:
2404 error
= sooptcopyin(sopt
, &optval
, sizeof(optval
),
2409 if (optval
< 0 || optval
> 1) {
2411 } else if (optval
== 1) {
2413 * Check if messages option is already
2414 * enabled, if so return.
2416 if (so
->so_flags
& SOF_ENABLE_MSGS
) {
2417 VERIFY(so
->so_msg_state
!= NULL
);
2422 * allocate memory for storing message
2425 VERIFY(so
->so_msg_state
== NULL
);
2426 MALLOC(so
->so_msg_state
,
2428 sizeof(struct msg_state
),
2429 M_TEMP
, M_WAITOK
| M_ZERO
);
2430 if (so
->so_msg_state
== NULL
) {
2435 /* Enable message delivery */
2436 so
->so_flags
|= SOF_ENABLE_MSGS
;
2439 * Can't disable message delivery on socket
2440 * because of restrictions imposed by
2446 case TCP_SENDMOREACKS
:
2447 error
= sooptcopyin(sopt
, &optval
, sizeof(optval
),
2452 if (optval
< 0 || optval
> 1) {
2454 } else if (optval
== 0) {
2455 tp
->t_flagsext
&= ~(TF_NOSTRETCHACK
);
2457 tp
->t_flagsext
|= TF_NOSTRETCHACK
;
2460 case TCP_DISABLE_BLACKHOLE_DETECTION
:
2461 error
= sooptcopyin(sopt
, &optval
, sizeof(optval
),
2466 if (optval
< 0 || optval
> 1) {
2468 } else if (optval
== 0) {
2469 tp
->t_flagsext
&= ~TF_NOBLACKHOLE_DETECTION
;
2471 tp
->t_flagsext
|= TF_NOBLACKHOLE_DETECTION
;
2472 if ((tp
->t_flags
& TF_BLACKHOLE
) &&
2473 tp
->t_pmtud_saved_maxopd
> 0) {
2474 tcp_pmtud_revert_segment_size(tp
);
2479 if (!(tcp_fastopen
& TCP_FASTOPEN_SERVER
)) {
2484 error
= sooptcopyin(sopt
, &optval
, sizeof(optval
),
2489 if (optval
< 0 || optval
> 1) {
2493 if (tp
->t_state
!= TCPS_LISTEN
) {
2498 tp
->t_flagsext
|= TF_FASTOPEN
;
2500 tcp_disable_tfo(tp
);
2503 case TCP_FASTOPEN_FORCE_HEURISTICS
:
2506 case TCP_FASTOPEN_FORCE_ENABLE
:
2507 error
= sooptcopyin(sopt
, &optval
, sizeof(optval
),
2513 if (optval
< 0 || optval
> 1) {
2518 if (tp
->t_state
!= TCPS_CLOSED
) {
2523 tp
->t_flagsext
|= TF_FASTOPEN_FORCE_ENABLE
;
2525 tp
->t_flagsext
&= ~TF_FASTOPEN_FORCE_ENABLE
;
2529 case TCP_ENABLE_ECN
:
2530 error
= sooptcopyin(sopt
, &optval
, sizeof optval
,
2536 tp
->ecn_flags
|= TE_ECN_MODE_ENABLE
;
2537 tp
->ecn_flags
&= ~TE_ECN_MODE_DISABLE
;
2539 tp
->ecn_flags
&= ~TE_ECN_MODE_ENABLE
;
2540 tp
->ecn_flags
|= TE_ECN_MODE_DISABLE
;
2544 error
= sooptcopyin(sopt
, &optval
, sizeof optval
,
2549 if (optval
== ECN_MODE_DEFAULT
) {
2550 tp
->ecn_flags
&= ~TE_ECN_MODE_ENABLE
;
2551 tp
->ecn_flags
&= ~TE_ECN_MODE_DISABLE
;
2552 } else if (optval
== ECN_MODE_ENABLE
) {
2553 tp
->ecn_flags
|= TE_ECN_MODE_ENABLE
;
2554 tp
->ecn_flags
&= ~TE_ECN_MODE_DISABLE
;
2555 } else if (optval
== ECN_MODE_DISABLE
) {
2556 tp
->ecn_flags
&= ~TE_ECN_MODE_ENABLE
;
2557 tp
->ecn_flags
|= TE_ECN_MODE_DISABLE
;
2562 case TCP_NOTIFY_ACKNOWLEDGEMENT
:
2563 error
= sooptcopyin(sopt
, &optval
,
2564 sizeof(optval
), sizeof(optval
));
2572 if (tp
->t_notify_ack_count
>= TCP_MAX_NOTIFY_ACK
) {
2573 error
= ETOOMANYREFS
;
2578 * validate that the given marker id is not
2579 * a duplicate to avoid ambiguity
2581 if ((error
= tcp_notify_ack_id_valid(tp
, so
,
2585 error
= tcp_add_notify_ack_marker(tp
, optval
);
2588 if ((error
= sooptcopyin(sopt
, &optval
, sizeof(optval
),
2589 sizeof(optval
))) != 0) {
2593 error
= inp_flush(inp
, optval
);
2596 case SO_TRAFFIC_MGT_BACKGROUND
:
2597 if ((error
= sooptcopyin(sopt
, &optval
, sizeof(optval
),
2598 sizeof(optval
))) != 0) {
2603 socket_set_traffic_mgt_flags_locked(so
,
2604 TRAFFIC_MGT_SO_BACKGROUND
);
2606 socket_clear_traffic_mgt_flags_locked(so
,
2607 TRAFFIC_MGT_SO_BACKGROUND
);
2610 case TCP_RXT_MINIMUM_TIMEOUT
:
2611 error
= sooptcopyin(sopt
, &optval
, sizeof(optval
),
2621 tp
->t_rxt_minimum_timeout
= 0;
2623 tp
->t_rxt_minimum_timeout
= min(optval
,
2624 TCP_RXT_MINIMUM_TIMEOUT_LIMIT
);
2625 /* convert to milliseconds */
2626 tp
->t_rxt_minimum_timeout
*= TCP_RETRANSHZ
;
2630 error
= ENOPROTOOPT
;
2636 switch (sopt
->sopt_name
) {
2638 optval
= tp
->t_flags
& TF_NODELAY
;
2641 optval
= tp
->t_maxseg
;
2644 if (tp
->t_keepidle
> 0) {
2645 optval
= tp
->t_keepidle
/ TCP_RETRANSHZ
;
2647 optval
= tcp_keepidle
/ TCP_RETRANSHZ
;
2651 if (tp
->t_keepintvl
> 0) {
2652 optval
= tp
->t_keepintvl
/ TCP_RETRANSHZ
;
2654 optval
= tcp_keepintvl
/ TCP_RETRANSHZ
;
2658 if (tp
->t_keepcnt
> 0) {
2659 optval
= tp
->t_keepcnt
;
2661 optval
= tcp_keepcnt
;
2664 case TCP_KEEPALIVE_OFFLOAD
:
2665 optval
= !!(inp
->inp_flags2
& INP2_KEEPALIVE_OFFLOAD
);
2668 optval
= tp
->t_flags
& TF_NOOPT
;
2671 optval
= tp
->t_flags
& TF_NOPUSH
;
2673 case TCP_ENABLE_ECN
:
2674 optval
= (tp
->ecn_flags
& TE_ECN_MODE_ENABLE
) ? 1 : 0;
2677 if (tp
->ecn_flags
& TE_ECN_MODE_ENABLE
) {
2678 optval
= ECN_MODE_ENABLE
;
2679 } else if (tp
->ecn_flags
& TE_ECN_MODE_DISABLE
) {
2680 optval
= ECN_MODE_DISABLE
;
2682 optval
= ECN_MODE_DEFAULT
;
2685 case TCP_CONNECTIONTIMEOUT
:
2686 optval
= tp
->t_keepinit
/ TCP_RETRANSHZ
;
2688 case PERSIST_TIMEOUT
:
2689 optval
= tp
->t_persist_timeout
/ TCP_RETRANSHZ
;
2691 case TCP_RXT_CONNDROPTIME
:
2692 optval
= tp
->t_rxt_conndroptime
/ TCP_RETRANSHZ
;
2694 case TCP_RXT_FINDROP
:
2695 optval
= tp
->t_flagsext
& TF_RXTFINDROP
;
2697 case TCP_NOTIMEWAIT
:
2698 optval
= (tp
->t_flagsext
& TF_NOTIMEWAIT
) ? 1 : 0;
2701 if (tp
->t_state
!= TCPS_LISTEN
||
2702 !(tcp_fastopen
& TCP_FASTOPEN_SERVER
)) {
2706 optval
= tfo_enabled(tp
);
2708 case TCP_FASTOPEN_FORCE_HEURISTICS
:
2711 case TCP_FASTOPEN_FORCE_ENABLE
:
2712 optval
= (tp
->t_flagsext
& TF_FASTOPEN_FORCE_ENABLE
) ? 1 : 0;
2714 case TCP_MEASURE_SND_BW
:
2715 optval
= tp
->t_flagsext
& TF_MEASURESNDBW
;
2720 tcp_fill_info(tp
, &ti
);
2721 error
= sooptcopyout(sopt
, &ti
, sizeof(struct tcp_info
));
2725 case TCP_CONNECTION_INFO
: {
2726 struct tcp_connection_info tci
;
2727 tcp_connection_fill_info(tp
, &tci
);
2728 error
= sooptcopyout(sopt
, &tci
,
2729 sizeof(struct tcp_connection_info
));
2732 case TCP_MEASURE_BW_BURST
: {
2733 struct tcp_measure_bw_burst out
= {};
2734 if ((tp
->t_flagsext
& TF_MEASURESNDBW
) == 0 ||
2735 tp
->t_bwmeas
== NULL
) {
2739 out
.min_burst_size
= tp
->t_bwmeas
->bw_minsizepkts
;
2740 out
.max_burst_size
= tp
->t_bwmeas
->bw_maxsizepkts
;
2741 error
= sooptcopyout(sopt
, &out
, sizeof(out
));
2744 case TCP_NOTSENT_LOWAT
:
2745 if ((so
->so_flags
& SOF_NOTSENT_LOWAT
) != 0) {
2746 optval
= tp
->t_notsent_lowat
;
2752 case TCP_ENABLE_MSGS
:
2753 if (so
->so_flags
& SOF_ENABLE_MSGS
) {
2759 case TCP_SENDMOREACKS
:
2760 if (tp
->t_flagsext
& TF_NOSTRETCHACK
) {
2766 case TCP_DISABLE_BLACKHOLE_DETECTION
:
2767 if (tp
->t_flagsext
& TF_NOBLACKHOLE_DETECTION
) {
2773 case TCP_PEER_PID
: {
2775 error
= tcp_lookup_peer_pid_locked(so
, &pid
);
2777 error
= sooptcopyout(sopt
, &pid
, sizeof(pid
));
2781 case TCP_ADAPTIVE_READ_TIMEOUT
:
2782 optval
= tp
->t_adaptive_rtimo
;
2784 case TCP_ADAPTIVE_WRITE_TIMEOUT
:
2785 optval
= tp
->t_adaptive_wtimo
;
2787 case SO_TRAFFIC_MGT_BACKGROUND
:
2788 optval
= (so
->so_flags1
&
2789 SOF1_TRAFFIC_MGT_SO_BACKGROUND
) ? 1 : 0;
2791 case TCP_NOTIFY_ACKNOWLEDGEMENT
: {
2792 struct tcp_notify_ack_complete retid
;
2794 if (sopt
->sopt_valsize
!= sizeof(retid
)) {
2798 bzero(&retid
, sizeof(retid
));
2799 tcp_get_notify_ack_count(tp
, &retid
);
2800 if (retid
.notify_complete_count
> 0) {
2801 tcp_get_notify_ack_ids(tp
, &retid
);
2804 error
= sooptcopyout(sopt
, &retid
, sizeof(retid
));
2807 case TCP_RXT_MINIMUM_TIMEOUT
:
2808 optval
= tp
->t_rxt_minimum_timeout
/ TCP_RETRANSHZ
;
2811 error
= ENOPROTOOPT
;
2815 error
= sooptcopyout(sopt
, &optval
, sizeof optval
);
2824 * tcp_sendspace and tcp_recvspace are the default send and receive window
2825 * sizes, respectively. These are obsolescent (this information should
2826 * be set by the route).
2828 u_int32_t tcp_sendspace
= 1448 * 256;
2829 u_int32_t tcp_recvspace
= 1448 * 384;
2831 /* During attach, the size of socket buffer allocated is limited to
2832 * sb_max in sbreserve. Disallow setting the tcp send and recv space
2833 * to be more than sb_max because that will cause tcp_attach to fail
2834 * (see radar 5713060)
2837 sysctl_tcp_sospace(struct sysctl_oid
*oidp
, __unused
void *arg1
,
2838 int arg2
, struct sysctl_req
*req
)
2840 #pragma unused(arg2)
2841 u_int32_t new_value
= 0, *space_p
= NULL
;
2842 int changed
= 0, error
= 0;
2843 u_quad_t sb_effective_max
= (sb_max
/ (MSIZE
+ MCLBYTES
)) * MCLBYTES
;
2845 switch (oidp
->oid_number
) {
2846 case TCPCTL_SENDSPACE
:
2847 space_p
= &tcp_sendspace
;
2849 case TCPCTL_RECVSPACE
:
2850 space_p
= &tcp_recvspace
;
2855 error
= sysctl_io_number(req
, *space_p
, sizeof(u_int32_t
),
2856 &new_value
, &changed
);
2858 if (new_value
> 0 && new_value
<= sb_effective_max
) {
2859 *space_p
= new_value
;
2860 SYSCTL_SKMEM_UPDATE_AT_OFFSET(arg2
, new_value
);
2869 SYSCTL_PROC(_net_inet_tcp
, TCPCTL_SENDSPACE
, sendspace
,
2870 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_LOCKED
, &tcp_sendspace
,
2871 offsetof(skmem_sysctl
, tcp
.sendspace
), sysctl_tcp_sospace
,
2872 "IU", "Maximum outgoing TCP datagram size");
2873 SYSCTL_PROC(_net_inet_tcp
, TCPCTL_RECVSPACE
, recvspace
,
2874 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_LOCKED
, &tcp_recvspace
,
2875 offsetof(skmem_sysctl
, tcp
.recvspace
), sysctl_tcp_sospace
,
2876 "IU", "Maximum incoming TCP datagram size");
2877 #else /* SYSCTL_SKMEM */
2878 SYSCTL_PROC(_net_inet_tcp
, TCPCTL_SENDSPACE
, sendspace
, CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_LOCKED
,
2879 &tcp_sendspace
, 0, &sysctl_tcp_sospace
, "IU", "Maximum outgoing TCP datagram size");
2880 SYSCTL_PROC(_net_inet_tcp
, TCPCTL_RECVSPACE
, recvspace
, CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_LOCKED
,
2881 &tcp_recvspace
, 0, &sysctl_tcp_sospace
, "IU", "Maximum incoming TCP datagram size");
2882 #endif /* SYSCTL_SKMEM */
2885 * Attach TCP protocol to socket, allocating
2886 * internet protocol control block, tcp control block,
2887 * bufer space, and entering LISTEN state if to accept connections.
2889 * Returns: 0 Success
2890 * in_pcballoc:ENOBUFS
2891 * in_pcballoc:ENOMEM
2892 * in_pcballoc:??? [IPSEC specific]
2896 tcp_attach(struct socket
*so
, struct proc
*p
)
2902 int isipv6
= SOCK_CHECK_DOM(so
, PF_INET6
) != 0;
2905 error
= in_pcballoc(so
, &tcbinfo
, p
);
2910 inp
= sotoinpcb(so
);
2912 if (so
->so_snd
.sb_hiwat
== 0 || so
->so_rcv
.sb_hiwat
== 0) {
2913 error
= soreserve(so
, tcp_sendspace
, tcp_recvspace
);
2919 if (so
->so_snd
.sb_preconn_hiwat
== 0) {
2920 soreserve_preconnect(so
, 2048);
2923 if ((so
->so_rcv
.sb_flags
& SB_USRSIZE
) == 0) {
2924 so
->so_rcv
.sb_flags
|= SB_AUTOSIZE
;
2926 if ((so
->so_snd
.sb_flags
& SB_USRSIZE
) == 0) {
2927 so
->so_snd
.sb_flags
|= SB_AUTOSIZE
;
2932 inp
->inp_vflag
|= INP_IPV6
;
2933 inp
->in6p_hops
= -1; /* use kernel default */
2936 inp
->inp_vflag
|= INP_IPV4
;
2937 tp
= tcp_newtcpcb(inp
);
2939 int nofd
= so
->so_state
& SS_NOFDREF
; /* XXX */
2941 so
->so_state
&= ~SS_NOFDREF
; /* don't free the socket yet */
2948 so
->so_state
|= nofd
;
2951 if (nstat_collect
) {
2952 nstat_tcp_new_pcb(inp
);
2954 tp
->t_state
= TCPS_CLOSED
;
2959 * Initiate (or continue) disconnect.
2960 * If embryonic state, just send reset (once).
2961 * If in ``let data drain'' option and linger null, just drop.
2962 * Otherwise (hard), mark socket disconnecting and drop
2963 * current input data; switch states based on user close, and
2964 * send segment to peer (with FIN).
2966 static struct tcpcb
*
2967 tcp_disconnect(struct tcpcb
*tp
)
2969 struct socket
*so
= tp
->t_inpcb
->inp_socket
;
2971 if (so
->so_rcv
.sb_cc
!= 0 || tp
->t_reassqlen
!= 0) {
2972 return tcp_drop(tp
, 0);
2975 if (tp
->t_state
< TCPS_ESTABLISHED
) {
2977 } else if ((so
->so_options
& SO_LINGER
) && so
->so_linger
== 0) {
2978 tp
= tcp_drop(tp
, 0);
2980 soisdisconnecting(so
);
2981 sbflush(&so
->so_rcv
);
2982 tp
= tcp_usrclosed(tp
);
2984 /* A reset has been sent but socket exists, do not send FIN */
2985 if ((so
->so_flags
& SOF_MP_SUBFLOW
) &&
2986 (tp
) && (tp
->t_mpflags
& TMPF_RESET
)) {
2991 (void) tcp_output(tp
);
2998 * User issued close, and wish to trail through shutdown states:
2999 * if never received SYN, just forget it. If got a SYN from peer,
3000 * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN.
3001 * If already got a FIN from peer, then almost done; go to LAST_ACK
3002 * state. In all other cases, have already sent FIN to peer (e.g.
3003 * after PRU_SHUTDOWN), and just have to play tedious game waiting
3004 * for peer to send FIN or not respond to keep-alives, etc.
3005 * We can let the user exit from the close as soon as the FIN is acked.
3007 static struct tcpcb
*
3008 tcp_usrclosed(struct tcpcb
*tp
)
3010 switch (tp
->t_state
) {
3017 case TCPS_SYN_RECEIVED
:
3018 tp
->t_flags
|= TF_NEEDFIN
;
3021 case TCPS_ESTABLISHED
:
3022 DTRACE_TCP4(state__change
, void, NULL
,
3023 struct inpcb
*, tp
->t_inpcb
,
3025 int32_t, TCPS_FIN_WAIT_1
);
3026 tp
->t_state
= TCPS_FIN_WAIT_1
;
3027 TCP_LOG_CONNECTION_SUMMARY(tp
);
3030 case TCPS_CLOSE_WAIT
:
3031 DTRACE_TCP4(state__change
, void, NULL
,
3032 struct inpcb
*, tp
->t_inpcb
,
3034 int32_t, TCPS_LAST_ACK
);
3035 tp
->t_state
= TCPS_LAST_ACK
;
3036 TCP_LOG_CONNECTION_SUMMARY(tp
);
3039 if (tp
&& tp
->t_state
>= TCPS_FIN_WAIT_2
) {
3040 soisdisconnected(tp
->t_inpcb
->inp_socket
);
3041 /* To prevent the connection hanging in FIN_WAIT_2 forever. */
3042 if (tp
->t_state
== TCPS_FIN_WAIT_2
) {
3043 tp
->t_timer
[TCPT_2MSL
] = OFFSET_FROM_START(tp
,
3044 TCP_CONN_MAXIDLE(tp
));
3051 tcp_in_cksum_stats(u_int32_t len
)
3053 tcpstat
.tcps_rcv_swcsum
++;
3054 tcpstat
.tcps_rcv_swcsum_bytes
+= len
;
3058 tcp_out_cksum_stats(u_int32_t len
)
3060 tcpstat
.tcps_snd_swcsum
++;
3061 tcpstat
.tcps_snd_swcsum_bytes
+= len
;
3066 tcp_in6_cksum_stats(u_int32_t len
)
3068 tcpstat
.tcps_rcv6_swcsum
++;
3069 tcpstat
.tcps_rcv6_swcsum_bytes
+= len
;
3073 tcp_out6_cksum_stats(u_int32_t len
)
3075 tcpstat
.tcps_snd6_swcsum
++;
3076 tcpstat
.tcps_snd6_swcsum_bytes
+= len
;
3081 * When messages are enabled on a TCP socket, the message priority
3082 * is sent as a control message. This function will extract it.
3085 tcp_get_msg_priority(struct mbuf
*control
, uint32_t *msgpri
)
3089 if (control
== NULL
) {
3093 for (cm
= M_FIRST_CMSGHDR(control
);
3094 is_cmsg_valid(control
, cm
);
3095 cm
= M_NXT_CMSGHDR(control
, cm
)) {
3096 if (cm
->cmsg_level
== SOL_SOCKET
&&
3097 cm
->cmsg_type
== SCM_MSG_PRIORITY
) {
3098 if (cm
->cmsg_len
!= CMSG_LEN(sizeof(uint32_t))) {
3101 *msgpri
= *(uint32_t *)(void *)CMSG_DATA(cm
);
3102 if (*msgpri
< MSG_PRI_MIN
|| *msgpri
> MSG_PRI_MAX
) {
3112 tcp_get_mpkl_send_info(struct mbuf
*control
,
3113 struct so_mpkl_send_info
*mpkl_send_info
)
3117 if (control
== NULL
|| mpkl_send_info
== NULL
) {
3121 for (cm
= M_FIRST_CMSGHDR(control
); cm
;
3122 cm
= M_NXT_CMSGHDR(control
, cm
)) {
3123 if (cm
->cmsg_len
< sizeof(struct cmsghdr
) ||
3124 cm
->cmsg_len
> control
->m_len
) {
3127 if (cm
->cmsg_level
!= SOL_SOCKET
||
3128 cm
->cmsg_type
!= SCM_MPKL_SEND_INFO
) {
3131 if (cm
->cmsg_len
!= CMSG_LEN(sizeof(struct so_mpkl_send_info
))) {
3134 memcpy(mpkl_send_info
, CMSG_DATA(cm
),
3135 sizeof(struct so_mpkl_send_info
));