2 * Copyright (c) 2012-2020 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 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/kernel.h>
32 #include <sys/socket.h>
33 #include <sys/socketvar.h>
34 #include <sys/protosw.h>
35 #include <sys/mcache.h>
36 #include <sys/syslog.h>
38 #include <sys/proc_internal.h>
39 #include <sys/resourcevar.h>
40 #include <sys/kauth.h>
44 #include <netinet/in.h>
45 #include <netinet/in_var.h>
46 #include <netinet/tcp.h>
47 #include <netinet/tcp_fsm.h>
48 #include <netinet/tcp_seq.h>
49 #include <netinet/tcp_var.h>
50 #include <netinet/tcp_timer.h>
51 #include <netinet/mptcp_var.h>
52 #include <netinet/mptcp_timer.h>
56 static int mptcp_usr_attach(struct socket
*, int, struct proc
*);
57 static int mptcp_usr_detach(struct socket
*);
58 static int mptcp_attach(struct socket
*, struct proc
*);
59 static int mptcp_usr_connectx(struct socket
*, struct sockaddr
*,
60 struct sockaddr
*, struct proc
*, uint32_t, sae_associd_t
,
61 sae_connid_t
*, uint32_t, void *, uint32_t, struct uio
*, user_ssize_t
*);
62 static int mptcp_getassocids(struct mptses
*, uint32_t *, user_addr_t
);
63 static int mptcp_getconnids(struct mptses
*, sae_associd_t
, uint32_t *,
65 static int mptcp_getconninfo(struct mptses
*, sae_connid_t
*, uint32_t *,
66 uint32_t *, int32_t *, user_addr_t
, socklen_t
*, user_addr_t
, socklen_t
*,
67 uint32_t *, user_addr_t
, uint32_t *);
68 static int mptcp_usr_control(struct socket
*, u_long
, caddr_t
, struct ifnet
*,
70 static int mptcp_disconnect(struct mptses
*);
71 static int mptcp_usr_disconnect(struct socket
*);
72 static int mptcp_usr_disconnectx(struct socket
*, sae_associd_t
, sae_connid_t
);
73 static struct mptses
*mptcp_usrclosed(struct mptses
*);
74 static int mptcp_usr_rcvd(struct socket
*, int);
75 static int mptcp_usr_send(struct socket
*, int, struct mbuf
*,
76 struct sockaddr
*, struct mbuf
*, struct proc
*);
77 static int mptcp_usr_shutdown(struct socket
*);
78 static int mptcp_usr_sosend(struct socket
*, struct sockaddr
*, struct uio
*,
79 struct mbuf
*, struct mbuf
*, int);
80 static int mptcp_usr_socheckopt(struct socket
*, struct sockopt
*);
81 static int mptcp_usr_preconnect(struct socket
*so
);
83 struct pr_usrreqs mptcp_usrreqs
= {
84 .pru_attach
= mptcp_usr_attach
,
85 .pru_connectx
= mptcp_usr_connectx
,
86 .pru_control
= mptcp_usr_control
,
87 .pru_detach
= mptcp_usr_detach
,
88 .pru_disconnect
= mptcp_usr_disconnect
,
89 .pru_disconnectx
= mptcp_usr_disconnectx
,
90 .pru_peeraddr
= mp_getpeeraddr
,
91 .pru_rcvd
= mptcp_usr_rcvd
,
92 .pru_send
= mptcp_usr_send
,
93 .pru_shutdown
= mptcp_usr_shutdown
,
94 .pru_sockaddr
= mp_getsockaddr
,
95 .pru_sosend
= mptcp_usr_sosend
,
96 .pru_soreceive
= soreceive
,
97 .pru_socheckopt
= mptcp_usr_socheckopt
,
98 .pru_preconnect
= mptcp_usr_preconnect
,
102 #if (DEVELOPMENT || DEBUG)
103 static int mptcp_disable_entitlements
= 0;
104 SYSCTL_INT(_net_inet_mptcp
, OID_AUTO
, disable_entitlements
, CTLFLAG_RW
| CTLFLAG_LOCKED
,
105 &mptcp_disable_entitlements
, 0, "Disable Multipath TCP Entitlement Checking");
108 int mptcp_developer_mode
= 0;
109 SYSCTL_INT(_net_inet_mptcp
, OID_AUTO
, allow_aggregate
, CTLFLAG_RW
| CTLFLAG_LOCKED
,
110 &mptcp_developer_mode
, 0, "Allow the Multipath aggregation mode");
112 int mptcp_no_first_party
= 0;
113 SYSCTL_INT(_net_inet_mptcp
, OID_AUTO
, no_first_party
, CTLFLAG_RW
| CTLFLAG_LOCKED
,
114 &mptcp_no_first_party
, 0, "Do not do first-party app exemptions");
116 static unsigned long mptcp_expected_progress_headstart
= 5000;
117 SYSCTL_ULONG(_net_inet_mptcp
, OID_AUTO
, expected_progress_headstart
, CTLFLAG_RW
| CTLFLAG_LOCKED
,
118 &mptcp_expected_progress_headstart
, "Headstart to give MPTCP before meeting the progress deadline");
122 * Attaches an MPTCP control block to a socket.
125 mptcp_usr_attach(struct socket
*mp_so
, int proto
, struct proc
*p
)
127 #pragma unused(proto)
130 VERIFY(mpsotomppcb(mp_so
) == NULL
);
132 error
= mptcp_attach(mp_so
, p
);
137 if ((mp_so
->so_options
& SO_LINGER
) && mp_so
->so_linger
== 0) {
138 mp_so
->so_linger
= (short)(TCP_LINGERTIME
* hz
);
145 * Detaches an MPTCP control block from a socket.
148 mptcp_usr_detach(struct socket
*mp_so
)
150 struct mptses
*mpte
= mpsotompte(mp_so
);
151 struct mppcb
*mpp
= mpsotomppcb(mp_so
);
153 if (mpp
== NULL
|| mpp
->mpp_state
== MPPCB_STATE_DEAD
) {
154 os_log_error(mptcp_log_handle
, "%s - %lx: state: %d\n",
155 __func__
, (unsigned long)VM_KERNEL_ADDRPERM(mpte
),
156 mpp
? mpp
->mpp_state
: -1);
161 * We are done with this MPTCP socket (it has been closed);
162 * trigger all subflows to be disconnected, if not already,
163 * by initiating the PCB detach sequence (SOF_PCBCLEARING
168 mptcp_disconnect(mpte
);
174 * Attach MPTCP protocol to socket, allocating MP control block,
175 * MPTCP session, control block, buffer space, etc.
178 mptcp_attach(struct socket
*mp_so
, struct proc
*p
)
181 struct mptses
*mpte
= NULL
;
182 struct mptcb
*mp_tp
= NULL
;
183 struct mppcb
*mpp
= NULL
;
186 if (mp_so
->so_snd
.sb_hiwat
== 0 || mp_so
->so_rcv
.sb_hiwat
== 0) {
187 error
= soreserve(mp_so
, tcp_sendspace
, tcp_recvspace
);
193 if (mp_so
->so_snd
.sb_preconn_hiwat
== 0) {
194 soreserve_preconnect(mp_so
, 2048);
197 if ((mp_so
->so_rcv
.sb_flags
& SB_USRSIZE
) == 0) {
198 mp_so
->so_rcv
.sb_flags
|= SB_AUTOSIZE
;
200 if ((mp_so
->so_snd
.sb_flags
& SB_USRSIZE
) == 0) {
201 mp_so
->so_snd
.sb_flags
|= SB_AUTOSIZE
;
205 * MPTCP send-socket buffers cannot be compressed, due to the
206 * fact that each mbuf chained via m_next is a M_PKTHDR
207 * which carries some MPTCP metadata.
209 mp_so
->so_snd
.sb_flags
|= SB_NOCOMPRESS
;
211 if ((error
= mp_pcballoc(mp_so
, &mtcbinfo
)) != 0) {
215 mpp
= mpsotomppcb(mp_so
);
216 mpte
= (struct mptses
*)mpp
->mpp_pcbe
;
217 mp_tp
= mpte
->mpte_mptcb
;
219 VERIFY(mp_tp
!= NULL
);
225 mptcp_entitlement_check(struct socket
*mp_so
, uint8_t svctype
)
227 struct mptses
*mpte
= mpsotompte(mp_so
);
229 if (mptcp_no_first_party
) {
233 /* First, check for mptcp_extended without delegation */
234 if (soopt_cred_check(mp_so
, PRIV_NET_RESTRICTED_MULTIPATH_EXTENDED
, TRUE
, FALSE
) == 0) {
236 * This means the app has the extended entitlement. Thus,
237 * it's a first party app and can run without restrictions.
239 mpte
->mpte_flags
|= MPTE_FIRSTPARTY
;
243 /* Now with delegation */
244 if (mp_so
->so_flags
& SOF_DELEGATED
&&
245 soopt_cred_check(mp_so
, PRIV_NET_RESTRICTED_MULTIPATH_EXTENDED
, TRUE
, TRUE
) == 0) {
247 * This means the app has the extended entitlement. Thus,
248 * it's a first party app and can run without restrictions.
250 mpte
->mpte_flags
|= MPTE_FIRSTPARTY
;
254 if (svctype
== MPTCP_SVCTYPE_AGGREGATE
) {
255 if (mptcp_developer_mode
) {
259 os_log_error(mptcp_log_handle
, "%s - %lx: MPTCP prohibited on svc %u\n",
260 __func__
, (unsigned long)VM_KERNEL_ADDRPERM(mpte
), mpte
->mpte_svctype
);
268 * Common subroutine to open a MPTCP connection to one of the remote hosts
269 * specified by dst_sl. This includes allocating and establishing a
270 * subflow TCP connection, either initially to establish MPTCP connection,
271 * or to join an existing one. Returns a connection handle upon success.
274 mptcp_connectx(struct mptses
*mpte
, struct sockaddr
*src
,
275 struct sockaddr
*dst
, uint32_t ifscope
, sae_connid_t
*pcid
)
280 VERIFY(pcid
!= NULL
);
282 error
= mptcp_subflow_add(mpte
, src
, dst
, ifscope
, pcid
);
288 * User-protocol pru_connectx callback.
291 mptcp_usr_connectx(struct socket
*mp_so
, struct sockaddr
*src
,
292 struct sockaddr
*dst
, struct proc
*p
, uint32_t ifscope
,
293 sae_associd_t aid
, sae_connid_t
*pcid
, uint32_t flags
, void *arg
,
294 uint32_t arglen
, struct uio
*auio
, user_ssize_t
*bytes_written
)
296 #pragma unused(p, aid, flags, arg, arglen)
297 struct mppcb
*mpp
= mpsotomppcb(mp_so
);
298 struct mptses
*mpte
= NULL
;
299 struct mptcb
*mp_tp
= NULL
;
300 user_ssize_t datalen
;
303 if (mpp
== NULL
|| mpp
->mpp_state
== MPPCB_STATE_DEAD
) {
304 os_log_error(mptcp_log_handle
, "%s - %lx: state %d\n",
305 __func__
, (unsigned long)VM_KERNEL_ADDRPERM(mpte
),
306 mpp
? mpp
->mpp_state
: -1);
310 mpte
= mptompte(mpp
);
311 mp_tp
= mpte
->mpte_mptcb
;
313 if (mp_tp
->mpt_flags
& MPTCPF_FALLBACK_TO_TCP
) {
314 os_log_error(mptcp_log_handle
, "%s - %lx: fell back to TCP\n",
315 __func__
, (unsigned long)VM_KERNEL_ADDRPERM(mpte
));
320 if (dst
->sa_family
!= AF_INET
&& dst
->sa_family
!= AF_INET6
) {
321 error
= EAFNOSUPPORT
;
325 if (dst
->sa_family
== AF_INET
&&
326 dst
->sa_len
!= sizeof(mpte
->__mpte_dst_v4
)) {
327 os_log_error(mptcp_log_handle
, "%s - %lx: IPv4 dst len %u\n",
328 __func__
, (unsigned long)VM_KERNEL_ADDRPERM(mpte
), dst
->sa_len
);
333 if (dst
->sa_family
== AF_INET6
&&
334 dst
->sa_len
!= sizeof(mpte
->__mpte_dst_v6
)) {
335 os_log_error(mptcp_log_handle
, "%s - %lx: IPv6 dst len %u\n",
336 __func__
, (unsigned long)VM_KERNEL_ADDRPERM(mpte
), dst
->sa_len
);
341 if (!(mpte
->mpte_flags
& MPTE_SVCTYPE_CHECKED
)) {
342 if (mptcp_entitlement_check(mp_so
, mpte
->mpte_svctype
) < 0) {
347 mpte
->mpte_flags
|= MPTE_SVCTYPE_CHECKED
;
350 if ((mp_so
->so_state
& (SS_ISCONNECTED
| SS_ISCONNECTING
)) == 0) {
351 memcpy(&mpte
->mpte_u_dst
, dst
, dst
->sa_len
);
353 if (dst
->sa_family
== AF_INET
) {
354 memcpy(&mpte
->mpte_sub_dst_v4
, dst
, dst
->sa_len
);
356 memcpy(&mpte
->mpte_sub_dst_v6
, dst
, dst
->sa_len
);
361 if (src
->sa_family
!= AF_INET
&& src
->sa_family
!= AF_INET6
) {
362 error
= EAFNOSUPPORT
;
366 if (src
->sa_family
== AF_INET
&&
367 src
->sa_len
!= sizeof(mpte
->__mpte_src_v4
)) {
368 os_log_error(mptcp_log_handle
, "%s - %lx: IPv4 src len %u\n",
369 __func__
, (unsigned long)VM_KERNEL_ADDRPERM(mpte
), src
->sa_len
);
374 if (src
->sa_family
== AF_INET6
&&
375 src
->sa_len
!= sizeof(mpte
->__mpte_src_v6
)) {
376 os_log_error(mptcp_log_handle
, "%s - %lx: IPv6 src len %u\n",
377 __func__
, (unsigned long)VM_KERNEL_ADDRPERM(mpte
), src
->sa_len
);
382 if ((mp_so
->so_state
& (SS_ISCONNECTED
| SS_ISCONNECTING
)) == 0) {
383 memcpy(&mpte
->mpte_u_src
, src
, src
->sa_len
);
387 error
= mptcp_connectx(mpte
, src
, dst
, ifscope
, pcid
);
389 /* If there is data, copy it */
391 datalen
= uio_resid(auio
);
392 socket_unlock(mp_so
, 0);
393 error
= mp_so
->so_proto
->pr_usrreqs
->pru_sosend(mp_so
, NULL
,
394 (uio_t
) auio
, NULL
, NULL
, 0);
396 if (error
== 0 || error
== EWOULDBLOCK
) {
397 *bytes_written
= datalen
- uio_resid(auio
);
400 if (error
== EWOULDBLOCK
) {
404 socket_lock(mp_so
, 0);
412 * Handle SIOCGASSOCIDS ioctl for PF_MULTIPATH domain.
415 mptcp_getassocids(struct mptses
*mpte
, uint32_t *cnt
, user_addr_t aidp
)
417 /* MPTCP has at most 1 association */
418 *cnt
= (mpte
->mpte_associd
!= SAE_ASSOCID_ANY
) ? 1 : 0;
420 /* just asking how many there are? */
421 if (aidp
== USER_ADDR_NULL
) {
425 return copyout(&mpte
->mpte_associd
, aidp
,
426 sizeof(mpte
->mpte_associd
));
430 * Handle SIOCGCONNIDS ioctl for PF_MULTIPATH domain.
433 mptcp_getconnids(struct mptses
*mpte
, sae_associd_t aid
, uint32_t *cnt
,
439 if (aid
!= SAE_ASSOCID_ANY
&& aid
!= SAE_ASSOCID_ALL
&&
440 aid
!= mpte
->mpte_associd
) {
444 *cnt
= mpte
->mpte_numflows
;
446 /* just asking how many there are? */
447 if (cidp
== USER_ADDR_NULL
) {
451 TAILQ_FOREACH(mpts
, &mpte
->mpte_subflows
, mpts_entry
) {
452 if ((error
= copyout(&mpts
->mpts_connid
, cidp
,
453 sizeof(mpts
->mpts_connid
))) != 0) {
457 cidp
+= sizeof(mpts
->mpts_connid
);
464 * Handle SIOCGCONNINFO ioctl for PF_MULTIPATH domain.
467 mptcp_getconninfo(struct mptses
*mpte
, sae_connid_t
*cid
, uint32_t *flags
,
468 uint32_t *ifindex
, int32_t *soerror
, user_addr_t src
, socklen_t
*src_len
,
469 user_addr_t dst
, socklen_t
*dst_len
, uint32_t *aux_type
,
470 user_addr_t aux_data
, uint32_t *aux_len
)
477 /* MPTCP-level global stats */
478 if (*cid
== SAE_CONNID_ALL
) {
479 struct socket
*mp_so
= mptetoso(mpte
);
480 struct mptcb
*mp_tp
= mpte
->mpte_mptcb
;
481 struct conninfo_multipathtcp mptcp_ci
;
484 if (*aux_len
!= 0 && *aux_len
!= sizeof(mptcp_ci
)) {
488 if (mp_so
->so_state
& SS_ISCONNECTING
) {
489 *flags
|= CIF_CONNECTING
;
491 if (mp_so
->so_state
& SS_ISCONNECTED
) {
492 *flags
|= CIF_CONNECTED
;
494 if (mp_so
->so_state
& SS_ISDISCONNECTING
) {
495 *flags
|= CIF_DISCONNECTING
;
497 if (mp_so
->so_state
& SS_ISDISCONNECTED
) {
498 *flags
|= CIF_DISCONNECTED
;
500 if (!(mp_tp
->mpt_flags
& MPTCPF_FALLBACK_TO_TCP
)) {
501 *flags
|= CIF_MP_CAPABLE
;
503 if (mp_tp
->mpt_flags
& MPTCPF_FALLBACK_TO_TCP
) {
504 *flags
|= CIF_MP_DEGRADED
;
510 *aux_type
= CIAUX_MPTCP
;
511 *aux_len
= sizeof(mptcp_ci
);
513 if (aux_data
!= USER_ADDR_NULL
) {
514 const struct mptsub
*mpts
;
515 int initial_info_set
= 0;
518 bzero(&mptcp_ci
, sizeof(mptcp_ci
));
519 mptcp_ci
.mptcpci_subflow_count
= mpte
->mpte_numflows
;
520 mptcp_ci
.mptcpci_switch_count
= mpte
->mpte_subflow_switches
;
522 VERIFY(sizeof(mptcp_ci
.mptcpci_itfstats
) == sizeof(mpte
->mpte_itfstats
));
523 memcpy(mptcp_ci
.mptcpci_itfstats
, mpte
->mpte_itfstats
, sizeof(mptcp_ci
.mptcpci_itfstats
));
525 TAILQ_FOREACH(mpts
, &mpte
->mpte_subflows
, mpts_entry
) {
526 if (i
>= sizeof(mptcp_ci
.mptcpci_subflow_connids
) / sizeof(sae_connid_t
)) {
529 mptcp_ci
.mptcpci_subflow_connids
[i
] = mpts
->mpts_connid
;
531 if (mpts
->mpts_flags
& MPTSF_INITIAL_SUB
) {
532 const struct inpcb
*inp
;
534 inp
= sotoinpcb(mpts
->mpts_socket
);
536 mptcp_ci
.mptcpci_init_rxbytes
= inp
->inp_stat
->rxbytes
;
537 mptcp_ci
.mptcpci_init_txbytes
= inp
->inp_stat
->txbytes
;
538 initial_info_set
= 1;
541 mptcpstats_update(mptcp_ci
.mptcpci_itfstats
, mpts
);
546 if (initial_info_set
== 0) {
547 mptcp_ci
.mptcpci_init_rxbytes
= mpte
->mpte_init_rxbytes
;
548 mptcp_ci
.mptcpci_init_txbytes
= mpte
->mpte_init_txbytes
;
551 if (mpte
->mpte_flags
& MPTE_FIRSTPARTY
) {
552 mptcp_ci
.mptcpci_flags
|= MPTCPCI_FIRSTPARTY
;
555 error
= copyout(&mptcp_ci
, aux_data
, sizeof(mptcp_ci
));
557 os_log_error(mptcp_log_handle
, "%s - %lx: copyout failed: %d\n",
558 __func__
, (unsigned long)VM_KERNEL_ADDRPERM(mpte
), error
);
566 /* Any stats of any subflow */
567 if (*cid
== SAE_CONNID_ANY
) {
568 const struct mptsub
*mpts
;
570 const struct inpcb
*inp
;
573 mpts
= TAILQ_FIRST(&mpte
->mpte_subflows
);
578 so
= mpts
->mpts_socket
;
581 if (inp
->inp_vflag
& INP_IPV4
) {
582 error
= in_getconninfo(so
, SAE_CONNID_ANY
, flags
, ifindex
,
583 soerror
, src
, src_len
, dst
, dst_len
,
584 aux_type
, aux_data
, aux_len
);
586 error
= in6_getconninfo(so
, SAE_CONNID_ANY
, flags
, ifindex
,
587 soerror
, src
, src_len
, dst
, dst_len
,
588 aux_type
, aux_data
, aux_len
);
592 os_log_error(mptcp_log_handle
, "%s - %lx:error from in_getconninfo %d\n",
593 __func__
, (unsigned long)VM_KERNEL_ADDRPERM(mpte
), error
);
597 if (mpts
->mpts_flags
& MPTSF_MP_CAPABLE
) {
598 *flags
|= CIF_MP_CAPABLE
;
600 if (mpts
->mpts_flags
& MPTSF_MP_DEGRADED
) {
601 *flags
|= CIF_MP_DEGRADED
;
603 if (mpts
->mpts_flags
& MPTSF_MP_READY
) {
604 *flags
|= CIF_MP_READY
;
606 if (mpts
->mpts_flags
& MPTSF_ACTIVE
) {
607 *flags
|= CIF_MP_ACTIVE
;
612 /* Per-interface stats */
613 const struct mptsub
*mpts
, *orig_mpts
= NULL
;
614 struct conninfo_tcp tcp_ci
;
615 const struct inpcb
*inp
;
620 /* cid is thus an ifindex - range-check first! */
621 if (*cid
> USHRT_MAX
) {
625 bzero(&tcp_ci
, sizeof(tcp_ci
));
627 /* First, get a subflow to fill in the "regular" info. */
628 TAILQ_FOREACH(mpts
, &mpte
->mpte_subflows
, mpts_entry
) {
629 const struct ifnet
*ifp
= sotoinpcb(mpts
->mpts_socket
)->inp_last_outifp
;
631 if (ifp
&& ifp
->if_index
== *cid
) {
637 /* No subflow there - well, let's just get the basic itf-info */
641 so
= mpts
->mpts_socket
;
644 /* Give it USER_ADDR_NULL, because we are doing this on our own */
645 if (inp
->inp_vflag
& INP_IPV4
) {
646 error
= in_getconninfo(so
, SAE_CONNID_ANY
, flags
, ifindex
,
647 soerror
, src
, src_len
, dst
, dst_len
,
648 aux_type
, USER_ADDR_NULL
, aux_len
);
650 error
= in6_getconninfo(so
, SAE_CONNID_ANY
, flags
, ifindex
,
651 soerror
, src
, src_len
, dst
, dst_len
,
652 aux_type
, USER_ADDR_NULL
, aux_len
);
656 os_log_error(mptcp_log_handle
, "%s - %lx:error from in_getconninfo %d\n",
657 __func__
, (unsigned long)VM_KERNEL_ADDRPERM(mpte
), error
);
661 /* ToDo: Nobody is reading these flags on subflows. Why bother ? */
662 if (mpts
->mpts_flags
& MPTSF_MP_CAPABLE
) {
663 *flags
|= CIF_MP_CAPABLE
;
665 if (mpts
->mpts_flags
& MPTSF_MP_DEGRADED
) {
666 *flags
|= CIF_MP_DEGRADED
;
668 if (mpts
->mpts_flags
& MPTSF_MP_READY
) {
669 *flags
|= CIF_MP_READY
;
671 if (mpts
->mpts_flags
& MPTSF_ACTIVE
) {
672 *flags
|= CIF_MP_ACTIVE
;
676 * Now, we gather the metrics (aka., tcp_info) and roll them in
677 * across all subflows of this interface to build an aggregated
680 * We take the TCP_INFO from the first subflow as the "master",
681 * feeding into those fields that we do not roll.
683 if (aux_data
!= USER_ADDR_NULL
) {
684 tcp_getconninfo(so
, &tcp_ci
);
687 TAILQ_FOREACH(mpts
, &mpte
->mpte_subflows
, mpts_entry
) {
688 const struct inpcb
*mptsinp
= sotoinpcb(mpts
->mpts_socket
);
689 const struct ifnet
*ifp
;
691 ifp
= mptsinp
->inp_last_outifp
;
693 if (ifp
== NULL
|| ifp
->if_index
!= *cid
|| mpts
== orig_mpts
) {
697 /* Roll the itf-stats into the tcp_info */
698 tcp_ci
.tcpci_tcp_info
.tcpi_txbytes
+=
699 mptsinp
->inp_stat
->txbytes
;
700 tcp_ci
.tcpci_tcp_info
.tcpi_rxbytes
+=
701 mptsinp
->inp_stat
->rxbytes
;
703 tcp_ci
.tcpci_tcp_info
.tcpi_wifi_txbytes
+=
704 mptsinp
->inp_wstat
->txbytes
;
705 tcp_ci
.tcpci_tcp_info
.tcpi_wifi_rxbytes
+=
706 mptsinp
->inp_wstat
->rxbytes
;
708 tcp_ci
.tcpci_tcp_info
.tcpi_wired_txbytes
+=
709 mptsinp
->inp_Wstat
->txbytes
;
710 tcp_ci
.tcpci_tcp_info
.tcpi_wired_rxbytes
+=
711 mptsinp
->inp_Wstat
->rxbytes
;
713 tcp_ci
.tcpci_tcp_info
.tcpi_cell_txbytes
+=
714 mptsinp
->inp_cstat
->txbytes
;
715 tcp_ci
.tcpci_tcp_info
.tcpi_cell_rxbytes
+=
716 mptsinp
->inp_cstat
->rxbytes
;
721 *aux_type
= CIAUX_TCP
;
723 *aux_len
= sizeof(tcp_ci
);
724 } else if (aux_data
!= USER_ADDR_NULL
) {
728 * Finally, old subflows might have been closed - we
729 * want this data as well, so grab it from the interface
732 create
= orig_mpts
!= NULL
;
735 * When we found a subflow, we are willing to create a stats-index
736 * because we have some data to return. If there isn't a subflow,
737 * nor anything in the stats, return EINVAL. Because the
738 * ifindex belongs to something that doesn't exist.
740 index
= mptcpstats_get_index_by_ifindex(mpte
->mpte_itfstats
, (u_short
)(*cid
), false);
742 os_log_error(mptcp_log_handle
,
743 "%s - %lx: Asking for too many ifindex: %u subcount %u, mpts? %s\n",
744 __func__
, (unsigned long)VM_KERNEL_ADDRPERM(mpte
),
745 *cid
, mpte
->mpte_numflows
,
746 orig_mpts
? "yes" : "no");
748 if (orig_mpts
== NULL
) {
752 struct mptcp_itf_stats
*stats
;
754 stats
= &mpte
->mpte_itfstats
[index
];
756 /* Roll the itf-stats into the tcp_info */
757 tcp_ci
.tcpci_tcp_info
.tcpi_last_outif
= *cid
;
758 tcp_ci
.tcpci_tcp_info
.tcpi_txbytes
+=
760 tcp_ci
.tcpci_tcp_info
.tcpi_rxbytes
+=
763 tcp_ci
.tcpci_tcp_info
.tcpi_wifi_txbytes
+=
764 stats
->mpis_wifi_txbytes
;
765 tcp_ci
.tcpci_tcp_info
.tcpi_wifi_rxbytes
+=
766 stats
->mpis_wifi_rxbytes
;
768 tcp_ci
.tcpci_tcp_info
.tcpi_wired_txbytes
+=
769 stats
->mpis_wired_txbytes
;
770 tcp_ci
.tcpci_tcp_info
.tcpi_wired_rxbytes
+=
771 stats
->mpis_wired_rxbytes
;
773 tcp_ci
.tcpci_tcp_info
.tcpi_cell_txbytes
+=
774 stats
->mpis_cell_txbytes
;
775 tcp_ci
.tcpci_tcp_info
.tcpi_cell_rxbytes
+=
776 stats
->mpis_cell_rxbytes
;
779 *aux_len
= min(*aux_len
, sizeof(tcp_ci
));
780 error
= copyout(&tcp_ci
, aux_data
, *aux_len
);
791 * User-protocol pru_control callback.
794 mptcp_usr_control(struct socket
*mp_so
, u_long cmd
, caddr_t data
,
795 struct ifnet
*ifp
, struct proc
*p
)
797 #pragma unused(ifp, p)
798 struct mppcb
*mpp
= mpsotomppcb(mp_so
);
802 if (mpp
== NULL
|| mpp
->mpp_state
== MPPCB_STATE_DEAD
) {
806 mpte
= mptompte(mpp
);
809 case SIOCGASSOCIDS32
: { /* struct so_aidreq32 */
810 struct so_aidreq32 aidr
;
811 bcopy(data
, &aidr
, sizeof(aidr
));
812 error
= mptcp_getassocids(mpte
, &aidr
.sar_cnt
,
815 bcopy(&aidr
, data
, sizeof(aidr
));
820 case SIOCGASSOCIDS64
: { /* struct so_aidreq64 */
821 struct so_aidreq64 aidr
;
822 bcopy(data
, &aidr
, sizeof(aidr
));
823 error
= mptcp_getassocids(mpte
, &aidr
.sar_cnt
,
824 (user_addr_t
)aidr
.sar_aidp
);
826 bcopy(&aidr
, data
, sizeof(aidr
));
831 case SIOCGCONNIDS32
: { /* struct so_cidreq32 */
832 struct so_cidreq32 cidr
;
833 bcopy(data
, &cidr
, sizeof(cidr
));
834 error
= mptcp_getconnids(mpte
, cidr
.scr_aid
, &cidr
.scr_cnt
,
837 bcopy(&cidr
, data
, sizeof(cidr
));
842 case SIOCGCONNIDS64
: { /* struct so_cidreq64 */
843 struct so_cidreq64 cidr
;
844 bcopy(data
, &cidr
, sizeof(cidr
));
845 error
= mptcp_getconnids(mpte
, cidr
.scr_aid
, &cidr
.scr_cnt
,
846 (user_addr_t
)cidr
.scr_cidp
);
848 bcopy(&cidr
, data
, sizeof(cidr
));
853 case SIOCGCONNINFO32
: { /* struct so_cinforeq32 */
854 struct so_cinforeq32 cifr
;
855 bcopy(data
, &cifr
, sizeof(cifr
));
856 error
= mptcp_getconninfo(mpte
, &cifr
.scir_cid
,
857 &cifr
.scir_flags
, &cifr
.scir_ifindex
, &cifr
.scir_error
,
858 cifr
.scir_src
, &cifr
.scir_src_len
, cifr
.scir_dst
,
859 &cifr
.scir_dst_len
, &cifr
.scir_aux_type
, cifr
.scir_aux_data
,
862 bcopy(&cifr
, data
, sizeof(cifr
));
867 case SIOCGCONNINFO64
: { /* struct so_cinforeq64 */
868 struct so_cinforeq64 cifr
;
869 bcopy(data
, &cifr
, sizeof(cifr
));
870 error
= mptcp_getconninfo(mpte
, &cifr
.scir_cid
,
871 &cifr
.scir_flags
, &cifr
.scir_ifindex
, &cifr
.scir_error
,
872 (user_addr_t
)cifr
.scir_src
, &cifr
.scir_src_len
,
873 (user_addr_t
)cifr
.scir_dst
, &cifr
.scir_dst_len
,
874 &cifr
.scir_aux_type
, (user_addr_t
)cifr
.scir_aux_data
,
877 bcopy(&cifr
, data
, sizeof(cifr
));
891 mptcp_disconnect(struct mptses
*mpte
)
893 struct socket
*mp_so
;
897 mp_so
= mptetoso(mpte
);
898 mp_tp
= mpte
->mpte_mptcb
;
900 DTRACE_MPTCP3(disconnectx
, struct mptses
*, mpte
,
901 struct socket
*, mp_so
, struct mptcb
*, mp_tp
);
903 /* if we're not detached, go thru socket state checks */
904 if (!(mp_so
->so_flags
& SOF_PCBCLEARING
) && !(mp_so
->so_flags
& SOF_DEFUNCT
)) {
905 if (!(mp_so
->so_state
& (SS_ISCONNECTED
|
910 if (mp_so
->so_state
& SS_ISDISCONNECTING
) {
916 mptcp_cancel_all_timers(mp_tp
);
917 if (mp_tp
->mpt_state
< MPTCPS_ESTABLISHED
) {
918 mptcp_close(mpte
, mp_tp
);
919 } else if ((mp_so
->so_options
& SO_LINGER
) &&
920 mp_so
->so_linger
== 0) {
921 mptcp_drop(mpte
, mp_tp
, 0);
923 soisdisconnecting(mp_so
);
924 sbflush(&mp_so
->so_rcv
);
925 if (mptcp_usrclosed(mpte
) != NULL
) {
931 mptcp_subflow_workloop(mpte
);
939 * Wrapper function to support disconnect on socket
942 mptcp_usr_disconnect(struct socket
*mp_so
)
944 return mptcp_disconnect(mpsotompte(mp_so
));
948 * User-protocol pru_disconnectx callback.
951 mptcp_usr_disconnectx(struct socket
*mp_so
, sae_associd_t aid
, sae_connid_t cid
)
953 if (aid
!= SAE_ASSOCID_ANY
&& aid
!= SAE_ASSOCID_ALL
) {
957 if (cid
!= SAE_CONNID_ANY
&& cid
!= SAE_CONNID_ALL
) {
961 return mptcp_usr_disconnect(mp_so
);
965 mptcp_finish_usrclosed(struct mptses
*mpte
)
967 struct mptcb
*mp_tp
= mpte
->mpte_mptcb
;
968 struct socket
*mp_so
= mptetoso(mpte
);
970 if (mp_tp
->mpt_state
== MPTCPS_CLOSED
|| mp_tp
->mpt_state
== MPTCPS_TERMINATE
) {
971 mpte
= mptcp_close(mpte
, mp_tp
);
972 } else if (mp_tp
->mpt_state
>= MPTCPS_FIN_WAIT_2
) {
973 soisdisconnected(mp_so
);
977 TAILQ_FOREACH(mpts
, &mpte
->mpte_subflows
, mpts_entry
) {
978 if ((mp_so
->so_state
& (SS_CANTRCVMORE
| SS_CANTSENDMORE
)) ==
979 (SS_CANTRCVMORE
| SS_CANTSENDMORE
)) {
980 mptcp_subflow_disconnect(mpte
, mpts
);
982 mptcp_subflow_shutdown(mpte
, mpts
);
989 * User issued close, and wish to trail thru shutdown states.
991 static struct mptses
*
992 mptcp_usrclosed(struct mptses
*mpte
)
994 struct mptcb
*mp_tp
= mpte
->mpte_mptcb
;
996 mptcp_close_fsm(mp_tp
, MPCE_CLOSE
);
998 /* Not everything has been acknowledged - don't close the subflows! */
999 if (mp_tp
->mpt_state
!= MPTCPS_TERMINATE
&&
1000 mp_tp
->mpt_sndnxt
+ 1 != mp_tp
->mpt_sndmax
) {
1004 mptcp_finish_usrclosed(mpte
);
1010 * After a receive, possible send some update to peer.
1013 mptcp_usr_rcvd(struct socket
*mp_so
, int flags
)
1015 #pragma unused(flags)
1016 struct mppcb
*mpp
= mpsotomppcb(mp_so
);
1017 struct mptses
*mpte
;
1018 struct mptsub
*mpts
;
1021 if (mpp
== NULL
|| mpp
->mpp_state
== MPPCB_STATE_DEAD
) {
1026 mpte
= mptompte(mpp
);
1028 TAILQ_FOREACH(mpts
, &mpte
->mpte_subflows
, mpts_entry
) {
1029 struct socket
*so
= mpts
->mpts_socket
;
1031 if (so
->so_proto
->pr_flags
& PR_WANTRCVD
&& so
->so_pcb
!= NULL
) {
1032 (*so
->so_proto
->pr_usrreqs
->pru_rcvd
)(so
, 0);
1036 error
= mptcp_output(mpte
);
1042 * Do a send by putting data in the output queue.
1045 mptcp_usr_send(struct socket
*mp_so
, int prus_flags
, struct mbuf
*m
,
1046 struct sockaddr
*nam
, struct mbuf
*control
, struct proc
*p
)
1048 #pragma unused(nam, p)
1049 struct mppcb
*mpp
= mpsotomppcb(mp_so
);
1050 struct mptses
*mpte
;
1053 if (prus_flags
& (PRUS_OOB
| PRUS_EOF
)) {
1063 if (control
!= NULL
&& control
->m_len
!= 0) {
1068 if (mpp
== NULL
|| mpp
->mpp_state
== MPPCB_STATE_DEAD
) {
1072 mpte
= mptompte(mpp
);
1073 VERIFY(mpte
!= NULL
);
1075 if (!(mp_so
->so_state
& SS_ISCONNECTED
) &&
1076 !(mp_so
->so_flags1
& SOF1_PRECONNECT_DATA
)) {
1081 mptcp_insert_dsn(mpp
, m
);
1082 VERIFY(mp_so
->so_snd
.sb_flags
& SB_NOCOMPRESS
);
1083 sbappendstream(&mp_so
->so_snd
, m
);
1086 error
= mptcp_output(mpte
);
1091 if (mp_so
->so_state
& SS_ISCONNECTING
) {
1092 if (mp_so
->so_state
& SS_NBIO
) {
1093 error
= EWOULDBLOCK
;
1095 error
= sbwait(&mp_so
->so_snd
);
1104 if (control
!= NULL
) {
1112 * Mark the MPTCP connection as being incapable of further output.
1115 mptcp_usr_shutdown(struct socket
*mp_so
)
1117 struct mppcb
*mpp
= mpsotomppcb(mp_so
);
1118 struct mptses
*mpte
;
1121 if (mpp
== NULL
|| mpp
->mpp_state
== MPPCB_STATE_DEAD
) {
1125 mpte
= mptompte(mpp
);
1126 VERIFY(mpte
!= NULL
);
1128 socantsendmore(mp_so
);
1130 mpte
= mptcp_usrclosed(mpte
);
1132 error
= mptcp_output(mpte
);
1139 * Copy the contents of uio into a properly sized mbuf chain.
1142 mptcp_uiotombuf(struct uio
*uio
, int how
, user_ssize_t space
, struct mbuf
**top
)
1144 struct mbuf
*m
, *mb
, *nm
= NULL
, *mtail
= NULL
;
1145 int progress
, len
, error
;
1146 user_ssize_t resid
, tot
;
1148 VERIFY(top
!= NULL
&& *top
== NULL
);
1151 * space can be zero or an arbitrary large value bound by
1152 * the total data supplied by the uio.
1154 resid
= uio_resid(uio
);
1156 tot
= MIN(resid
, space
);
1161 if (tot
< 0 || tot
> INT_MAX
) {
1170 /* Loop and append maximum sized mbufs to the chain tail. */
1172 uint32_t m_needed
= 1;
1174 if (njcl
> 0 && len
> MBIGCLBYTES
) {
1175 mb
= m_getpackets_internal(&m_needed
, 1,
1176 how
, 1, M16KCLBYTES
);
1177 } else if (len
> MCLBYTES
) {
1178 mb
= m_getpackets_internal(&m_needed
, 1,
1179 how
, 1, MBIGCLBYTES
);
1180 } else if (len
>= (signed)MINCLSIZE
) {
1181 mb
= m_getpackets_internal(&m_needed
, 1,
1184 mb
= m_gethdr(how
, MT_DATA
);
1187 /* Fail the whole operation if one mbuf can't be allocated. */
1196 VERIFY(mb
->m_flags
& M_PKTHDR
);
1197 len
-= ((mb
->m_flags
& M_EXT
) ? mb
->m_ext
.ext_size
: MHLEN
);
1198 if (mtail
!= NULL
) {
1209 /* Fill all mbufs with uio data and update header information. */
1210 for (mb
= m
; mb
!= NULL
; mb
= mb
->m_next
) {
1211 /* tot >= 0 && tot <= INT_MAX (see above) */
1212 len
= MIN((int)M_TRAILINGSPACE(mb
), (int)(tot
- progress
));
1214 error
= uiomove(mtod(mb
, char *), len
, uio
);
1220 /* each mbuf is M_PKTHDR chained via m_next */
1222 mb
->m_pkthdr
.len
= len
;
1226 VERIFY(progress
== tot
);
1232 * MPTCP socket protocol-user socket send routine, derived from sosend().
1235 mptcp_usr_sosend(struct socket
*mp_so
, struct sockaddr
*addr
, struct uio
*uio
,
1236 struct mbuf
*top
, struct mbuf
*control
, int flags
)
1238 #pragma unused(addr)
1239 user_ssize_t resid
, space
;
1240 int error
, sendflags
;
1241 struct proc
*p
= current_proc();
1244 /* UIO is required for now, due to per-mbuf M_PKTHDR constrains */
1245 if (uio
== NULL
|| top
!= NULL
) {
1249 resid
= uio_resid(uio
);
1251 socket_lock(mp_so
, 1);
1252 so_update_last_owner_locked(mp_so
, p
);
1253 so_update_policy(mp_so
);
1255 VERIFY(mp_so
->so_type
== SOCK_STREAM
);
1256 VERIFY(!(mp_so
->so_flags
& SOF_MP_SUBFLOW
));
1258 if (flags
& (MSG_OOB
| MSG_DONTROUTE
)) {
1260 socket_unlock(mp_so
, 1);
1265 * In theory resid should be unsigned. However, space must be
1266 * signed, as it might be less than 0 if we over-committed, and we
1267 * must use a signed comparison of space and resid. On the other
1268 * hand, a negative resid causes us to loop sending 0-length
1269 * segments to the protocol.
1271 if (resid
< 0 || resid
> INT_MAX
||
1272 (flags
& MSG_EOR
) || control
!= NULL
) {
1274 socket_unlock(mp_so
, 1);
1278 OSIncrementAtomicLong(&p
->p_stats
->p_ru
.ru_msgsnd
);
1281 error
= sosendcheck(mp_so
, NULL
, resid
, 0, 0, flags
,
1287 space
= sbspace(&mp_so
->so_snd
);
1289 socket_unlock(mp_so
, 0);
1291 * Copy the data from userland into an mbuf chain.
1293 error
= mptcp_uiotombuf(uio
, M_WAITOK
, space
, &top
);
1295 socket_lock(mp_so
, 0);
1298 VERIFY(top
!= NULL
);
1299 space
-= resid
- uio_resid(uio
);
1300 resid
= uio_resid(uio
);
1301 socket_lock(mp_so
, 0);
1304 * Compute flags here, for pru_send and NKEs.
1306 sendflags
= (resid
> 0 && space
> 0) ?
1307 PRUS_MORETOCOME
: 0;
1310 * Socket filter processing
1312 VERIFY(control
== NULL
);
1313 error
= sflt_data_out(mp_so
, NULL
, &top
, &control
, 0);
1315 if (error
== EJUSTRETURN
) {
1318 /* always free control if any */
1322 if (control
!= NULL
) {
1328 * Pass data to protocol.
1330 error
= (*mp_so
->so_proto
->pr_usrreqs
->pru_send
)
1331 (mp_so
, sendflags
, top
, NULL
, NULL
, p
);
1337 } while (resid
!= 0 && space
> 0);
1338 } while (resid
!= 0);
1342 sbunlock(&mp_so
->so_snd
, FALSE
); /* will unlock socket */
1344 socket_unlock(mp_so
, 1);
1350 if (control
!= NULL
) {
1354 soclearfastopen(mp_so
);
1360 * Called to filter SOPT_{SET,GET} for SOL_SOCKET level socket options.
1361 * This routine simply indicates to the caller whether or not to proceed
1362 * further with the given socket option. This is invoked by sosetoptlock()
1363 * and sogetoptlock().
1366 mptcp_usr_socheckopt(struct socket
*mp_so
, struct sockopt
*sopt
)
1368 #pragma unused(mp_so)
1371 VERIFY(sopt
->sopt_level
== SOL_SOCKET
);
1374 * We could check for sopt_dir (set/get) here, but we'll just
1375 * let the caller deal with it as appropriate; therefore the
1376 * following is a superset of the socket options which we
1377 * allow for set/get.
1379 * XXX: adi@apple.com
1381 * Need to consider the following cases:
1383 * a. Certain socket options don't have a clear definition
1384 * on the expected behavior post connect(2). At the time
1385 * those options are issued on the MP socket, there may
1386 * be existing subflow sockets that are already connected.
1388 switch (sopt
->sopt_name
) {
1389 case SO_LINGER
: /* MP */
1390 case SO_LINGER_SEC
: /* MP */
1391 case SO_TYPE
: /* MP */
1392 case SO_NREAD
: /* MP */
1393 case SO_NWRITE
: /* MP */
1394 case SO_ERROR
: /* MP */
1395 case SO_SNDBUF
: /* MP */
1396 case SO_RCVBUF
: /* MP */
1397 case SO_SNDLOWAT
: /* MP */
1398 case SO_RCVLOWAT
: /* MP */
1399 case SO_SNDTIMEO
: /* MP */
1400 case SO_RCVTIMEO
: /* MP */
1401 case SO_NKE
: /* MP */
1402 case SO_NOSIGPIPE
: /* MP */
1403 case SO_NOADDRERR
: /* MP */
1404 case SO_LABEL
: /* MP */
1405 case SO_PEERLABEL
: /* MP */
1406 case SO_DEFUNCTIT
: /* MP */
1407 case SO_DEFUNCTOK
: /* MP */
1408 case SO_ISDEFUNCT
: /* MP */
1409 case SO_TRAFFIC_CLASS_DBG
: /* MP */
1410 case SO_DELEGATED
: /* MP */
1411 case SO_DELEGATED_UUID
: /* MP */
1413 case SO_NECP_ATTRIBUTES
:
1414 case SO_NECP_CLIENTUUID
:
1416 case SO_MPKL_SEND_INFO
:
1418 * Tell the caller that these options are to be processed.
1422 case SO_DEBUG
: /* MP + subflow */
1423 case SO_KEEPALIVE
: /* MP + subflow */
1424 case SO_USELOOPBACK
: /* MP + subflow */
1425 case SO_RANDOMPORT
: /* MP + subflow */
1426 case SO_TRAFFIC_CLASS
: /* MP + subflow */
1427 case SO_RECV_TRAFFIC_CLASS
: /* MP + subflow */
1428 case SO_PRIVILEGED_TRAFFIC_CLASS
: /* MP + subflow */
1429 case SO_RECV_ANYIF
: /* MP + subflow */
1430 case SO_RESTRICTIONS
: /* MP + subflow */
1431 case SO_FLUSH
: /* MP + subflow */
1432 case SO_NOWAKEFROMSLEEP
:
1433 case SO_NOAPNFALLBK
:
1434 case SO_MARK_CELLFALLBACK
:
1436 * Tell the caller that these options are to be processed;
1437 * these will also be recorded later by mptcp_setopt().
1439 * NOTE: Only support integer option value for now.
1441 if (sopt
->sopt_valsize
!= sizeof(int)) {
1448 * Tell the caller to stop immediately and return an error.
1450 error
= ENOPROTOOPT
;
1458 * Issue SOPT_SET for all MPTCP subflows (for integer option values.)
1461 mptcp_setopt_apply(struct mptses
*mpte
, struct mptopt
*mpo
)
1463 struct socket
*mp_so
;
1464 struct mptsub
*mpts
;
1468 /* just bail now if this isn't applicable to subflow sockets */
1469 if (!(mpo
->mpo_flags
& MPOF_SUBFLOW_OK
)) {
1470 error
= ENOPROTOOPT
;
1475 * Skip those that are handled internally; these options
1476 * should not have been recorded and marked with the
1477 * MPOF_SUBFLOW_OK by mptcp_setopt(), but just in case.
1479 if (mpo
->mpo_level
== SOL_SOCKET
&&
1480 (mpo
->mpo_name
== SO_NOSIGPIPE
|| mpo
->mpo_name
== SO_NOADDRERR
)) {
1481 error
= ENOPROTOOPT
;
1485 mp_so
= mptetoso(mpte
);
1488 * Don't bother going further if there's no subflow; mark the option
1489 * with MPOF_INTERIM so that we know whether or not to remove this
1490 * option upon encountering an error while issuing it during subflow
1493 if (mpte
->mpte_numflows
== 0) {
1494 VERIFY(TAILQ_EMPTY(&mpte
->mpte_subflows
));
1495 mpo
->mpo_flags
|= MPOF_INTERIM
;
1496 /* return success */
1500 bzero(&smpo
, sizeof(smpo
));
1501 smpo
.mpo_flags
|= MPOF_SUBFLOW_OK
;
1502 smpo
.mpo_level
= mpo
->mpo_level
;
1503 smpo
.mpo_name
= mpo
->mpo_name
;
1505 /* grab exisiting values in case we need to rollback */
1506 TAILQ_FOREACH(mpts
, &mpte
->mpte_subflows
, mpts_entry
) {
1509 mpts
->mpts_flags
&= ~(MPTSF_SOPT_OLDVAL
| MPTSF_SOPT_INPROG
);
1510 mpts
->mpts_oldintval
= 0;
1511 smpo
.mpo_intval
= 0;
1512 VERIFY(mpts
->mpts_socket
!= NULL
);
1513 so
= mpts
->mpts_socket
;
1514 if (mptcp_subflow_sogetopt(mpte
, so
, &smpo
) == 0) {
1515 mpts
->mpts_flags
|= MPTSF_SOPT_OLDVAL
;
1516 mpts
->mpts_oldintval
= smpo
.mpo_intval
;
1520 /* apply socket option */
1521 TAILQ_FOREACH(mpts
, &mpte
->mpte_subflows
, mpts_entry
) {
1524 mpts
->mpts_flags
|= MPTSF_SOPT_INPROG
;
1525 VERIFY(mpts
->mpts_socket
!= NULL
);
1526 so
= mpts
->mpts_socket
;
1527 error
= mptcp_subflow_sosetopt(mpte
, mpts
, mpo
);
1533 /* cleanup, and rollback if needed */
1534 TAILQ_FOREACH(mpts
, &mpte
->mpte_subflows
, mpts_entry
) {
1537 if (!(mpts
->mpts_flags
& MPTSF_SOPT_INPROG
)) {
1538 /* clear in case it's set */
1539 mpts
->mpts_flags
&= ~MPTSF_SOPT_OLDVAL
;
1540 mpts
->mpts_oldintval
= 0;
1543 if (!(mpts
->mpts_flags
& MPTSF_SOPT_OLDVAL
)) {
1544 mpts
->mpts_flags
&= ~MPTSF_SOPT_INPROG
;
1545 VERIFY(mpts
->mpts_oldintval
== 0);
1548 /* error during sosetopt, so roll it back */
1550 VERIFY(mpts
->mpts_socket
!= NULL
);
1551 so
= mpts
->mpts_socket
;
1552 smpo
.mpo_intval
= mpts
->mpts_oldintval
;
1553 mptcp_subflow_sosetopt(mpte
, mpts
, &smpo
);
1555 mpts
->mpts_oldintval
= 0;
1556 mpts
->mpts_flags
&= ~(MPTSF_SOPT_OLDVAL
| MPTSF_SOPT_INPROG
);
1564 * Handle SOPT_SET for socket options issued on MP socket.
1567 mptcp_setopt(struct mptses
*mpte
, struct sockopt
*sopt
)
1569 int error
= 0, optval
= 0, level
, optname
, rec
= 1;
1570 struct mptopt smpo
, *mpo
= NULL
;
1571 struct socket
*mp_so
;
1573 level
= sopt
->sopt_level
;
1574 optname
= sopt
->sopt_name
;
1576 mp_so
= mptetoso(mpte
);
1579 * Record socket options which are applicable to subflow sockets so
1580 * that we can replay them for new ones; see mptcp_usr_socheckopt()
1581 * for the list of eligible socket-level options.
1583 if (level
== SOL_SOCKET
) {
1587 case SO_USELOOPBACK
:
1589 case SO_TRAFFIC_CLASS
:
1590 case SO_RECV_TRAFFIC_CLASS
:
1591 case SO_PRIVILEGED_TRAFFIC_CLASS
:
1593 case SO_RESTRICTIONS
:
1594 case SO_NOWAKEFROMSLEEP
:
1595 case SO_NOAPNFALLBK
:
1596 case SO_MARK_CELLFALLBACK
:
1600 /* don't record it */
1604 /* Next ones, record at MPTCP-level */
1606 error
= sooptcopyin(sopt
, &mpte
->mpte_epid
,
1607 sizeof(int), sizeof(int));
1613 case SO_DELEGATED_UUID
:
1614 error
= sooptcopyin(sopt
, &mpte
->mpte_euuid
,
1615 sizeof(uuid_t
), sizeof(uuid_t
));
1622 case SO_NECP_CLIENTUUID
:
1623 if (!uuid_is_null(mpsotomppcb(mp_so
)->necp_client_uuid
)) {
1628 error
= sooptcopyin(sopt
, &mpsotomppcb(mp_so
)->necp_client_uuid
,
1629 sizeof(uuid_t
), sizeof(uuid_t
));
1634 mpsotomppcb(mp_so
)->necp_cb
= mptcp_session_necp_cb
;
1635 error
= necp_client_register_multipath_cb(mp_so
->last_pid
,
1636 mpsotomppcb(mp_so
)->necp_client_uuid
,
1637 mpsotomppcb(mp_so
));
1642 if (uuid_is_null(mpsotomppcb(mp_so
)->necp_client_uuid
)) {
1648 case SO_NECP_ATTRIBUTES
:
1651 /* nothing to do; just return */
1657 case TCP_RXT_FINDROP
:
1661 case TCP_CONNECTIONTIMEOUT
:
1662 case TCP_RXT_CONNDROPTIME
:
1663 case PERSIST_TIMEOUT
:
1664 case TCP_ADAPTIVE_READ_TIMEOUT
:
1665 case TCP_ADAPTIVE_WRITE_TIMEOUT
:
1666 case TCP_FASTOPEN_FORCE_ENABLE
:
1667 /* eligible; record it */
1669 case TCP_NOTSENT_LOWAT
:
1670 /* record at MPTCP level */
1671 error
= sooptcopyin(sopt
, &optval
, sizeof(optval
),
1681 mp_so
->so_flags
&= ~SOF_NOTSENT_LOWAT
;
1682 error
= mptcp_set_notsent_lowat(mpte
, 0);
1684 mp_so
->so_flags
|= SOF_NOTSENT_LOWAT
;
1685 error
= mptcp_set_notsent_lowat(mpte
,
1694 case MPTCP_SERVICE_TYPE
:
1695 /* record at MPTCP level */
1696 error
= sooptcopyin(sopt
, &optval
, sizeof(optval
),
1701 if (optval
< 0 || optval
>= MPTCP_SVCTYPE_MAX
) {
1706 if (mptcp_entitlement_check(mp_so
, (uint8_t)optval
) < 0) {
1711 mpte
->mpte_svctype
= (uint8_t)optval
;
1712 mpte
->mpte_flags
|= MPTE_SVCTYPE_CHECKED
;
1715 case MPTCP_ALTERNATE_PORT
:
1716 /* record at MPTCP level */
1717 error
= sooptcopyin(sopt
, &optval
, sizeof(optval
),
1723 if (optval
< 0 || optval
> UINT16_MAX
) {
1728 mpte
->mpte_alternate_port
= (uint16_t)optval
;
1731 case MPTCP_FORCE_ENABLE
:
1732 /* record at MPTCP level */
1733 error
= sooptcopyin(sopt
, &optval
, sizeof(optval
),
1739 if (optval
< 0 || optval
> 1) {
1745 mpte
->mpte_flags
|= MPTE_FORCE_ENABLE
;
1747 mpte
->mpte_flags
&= ~MPTE_FORCE_ENABLE
;
1751 case MPTCP_EXPECTED_PROGRESS_TARGET
:
1753 struct mptcb
*mp_tp
= mpte
->mpte_mptcb
;
1754 uint64_t mach_time_target
;
1755 uint64_t nanoseconds
;
1757 if (mpte
->mpte_svctype
!= MPTCP_SVCTYPE_TARGET_BASED
) {
1758 os_log(mptcp_log_handle
, "%s - %lx: Can't set urgent activity when svctype is %u\n",
1759 __func__
, (unsigned long)VM_KERNEL_ADDRPERM(mpte
), mpte
->mpte_svctype
);
1764 error
= sooptcopyin(sopt
, &mach_time_target
, sizeof(mach_time_target
), sizeof(mach_time_target
));
1769 if (!mptcp_ok_to_create_subflows(mp_tp
)) {
1770 os_log(mptcp_log_handle
, "%s - %lx: Not ok to create subflows, state %u flags %#x\n",
1771 __func__
, (unsigned long)VM_KERNEL_ADDRPERM(mpte
), mp_tp
->mpt_state
, mp_tp
->mpt_flags
);
1776 if (mach_time_target
) {
1777 uint64_t time_now
= 0;
1778 uint64_t time_now_nanoseconds
;
1780 absolutetime_to_nanoseconds(mach_time_target
, &nanoseconds
);
1781 nanoseconds
= nanoseconds
- (mptcp_expected_progress_headstart
* NSEC_PER_MSEC
);
1783 time_now
= mach_continuous_time();
1784 absolutetime_to_nanoseconds(time_now
, &time_now_nanoseconds
);
1786 nanoseconds_to_absolutetime(nanoseconds
, &mach_time_target
);
1787 /* If the timer is already running and it would
1788 * fire in less than mptcp_expected_progress_headstart
1789 * seconds, then it's not worth canceling it.
1791 if (mpte
->mpte_time_target
&&
1792 mpte
->mpte_time_target
< time_now
&&
1793 time_now_nanoseconds
> nanoseconds
- (mptcp_expected_progress_headstart
* NSEC_PER_MSEC
)) {
1794 os_log(mptcp_log_handle
, "%s - %lx: Not rescheduling timer %llu now %llu target %llu\n",
1795 __func__
, (unsigned long)VM_KERNEL_ADDRPERM(mpte
),
1796 mpte
->mpte_time_target
,
1803 mpte
->mpte_time_target
= mach_time_target
;
1804 mptcp_set_urgency_timer(mpte
);
1810 error
= ENOPROTOOPT
;
1815 if ((error
= sooptcopyin(sopt
, &optval
, sizeof(optval
),
1816 sizeof(optval
))) != 0) {
1821 /* search for an existing one; if not found, allocate */
1822 if ((mpo
= mptcp_sopt_find(mpte
, sopt
)) == NULL
) {
1823 mpo
= mptcp_sopt_alloc(Z_WAITOK
);
1830 /* initialize or update, as needed */
1831 mpo
->mpo_intval
= optval
;
1832 if (!(mpo
->mpo_flags
& MPOF_ATTACHED
)) {
1833 mpo
->mpo_level
= level
;
1834 mpo
->mpo_name
= optname
;
1835 mptcp_sopt_insert(mpte
, mpo
);
1837 /* this can be issued on the subflow socket */
1838 mpo
->mpo_flags
|= MPOF_SUBFLOW_OK
;
1841 bzero(&smpo
, sizeof(smpo
));
1843 mpo
->mpo_flags
|= MPOF_SUBFLOW_OK
;
1844 mpo
->mpo_level
= level
;
1845 mpo
->mpo_name
= optname
;
1846 mpo
->mpo_intval
= optval
;
1849 /* issue this socket option on existing subflows */
1850 error
= mptcp_setopt_apply(mpte
, mpo
);
1851 if (error
!= 0 && (mpo
->mpo_flags
& MPOF_ATTACHED
)) {
1852 VERIFY(mpo
!= &smpo
);
1853 mptcp_sopt_remove(mpte
, mpo
);
1854 mptcp_sopt_free(mpo
);
1857 mpo
->mpo_flags
&= ~MPOF_INTERIM
;
1869 os_log_error(mptcp_log_handle
, "%s - %lx: sopt %s (%d, %d) val %d can't be issued error %d\n",
1870 __func__
, (unsigned long)VM_KERNEL_ADDRPERM(mpte
),
1871 mptcp_sopt2str(level
, optname
), level
, optname
, optval
, error
);
1876 mptcp_fill_info_bytestats(struct tcp_info
*ti
, struct mptses
*mpte
)
1878 struct mptsub
*mpts
;
1881 TAILQ_FOREACH(mpts
, &mpte
->mpte_subflows
, mpts_entry
) {
1882 const struct inpcb
*inp
= sotoinpcb(mpts
->mpts_socket
);
1888 ti
->tcpi_txbytes
+= inp
->inp_stat
->txbytes
;
1889 ti
->tcpi_rxbytes
+= inp
->inp_stat
->rxbytes
;
1890 ti
->tcpi_cell_txbytes
+= inp
->inp_cstat
->txbytes
;
1891 ti
->tcpi_cell_rxbytes
+= inp
->inp_cstat
->rxbytes
;
1892 ti
->tcpi_wifi_txbytes
+= inp
->inp_wstat
->txbytes
;
1893 ti
->tcpi_wifi_rxbytes
+= inp
->inp_wstat
->rxbytes
;
1894 ti
->tcpi_wired_txbytes
+= inp
->inp_Wstat
->txbytes
;
1895 ti
->tcpi_wired_rxbytes
+= inp
->inp_Wstat
->rxbytes
;
1898 for (i
= 0; i
< MPTCP_ITFSTATS_SIZE
; i
++) {
1899 struct mptcp_itf_stats
*stats
= &mpte
->mpte_itfstats
[i
];
1901 ti
->tcpi_txbytes
+= stats
->mpis_txbytes
;
1902 ti
->tcpi_rxbytes
+= stats
->mpis_rxbytes
;
1904 ti
->tcpi_wifi_txbytes
+= stats
->mpis_wifi_txbytes
;
1905 ti
->tcpi_wifi_rxbytes
+= stats
->mpis_wifi_rxbytes
;
1907 ti
->tcpi_wired_txbytes
+= stats
->mpis_wired_txbytes
;
1908 ti
->tcpi_wired_rxbytes
+= stats
->mpis_wired_rxbytes
;
1910 ti
->tcpi_cell_txbytes
+= stats
->mpis_cell_txbytes
;
1911 ti
->tcpi_cell_rxbytes
+= stats
->mpis_cell_rxbytes
;
1916 mptcp_fill_info(struct mptses
*mpte
, struct tcp_info
*ti
)
1918 struct mptsub
*actsub
= mpte
->mpte_active_sub
;
1919 struct mptcb
*mp_tp
= mpte
->mpte_mptcb
;
1920 struct tcpcb
*acttp
= NULL
;
1923 acttp
= sototcpcb(actsub
->mpts_socket
);
1926 bzero(ti
, sizeof(*ti
));
1928 ti
->tcpi_state
= (uint8_t)mp_tp
->mpt_state
;
1930 /* tcpi_snd_wscale */
1931 /* tcpi_rcv_wscale */
1934 ti
->tcpi_rto
= acttp
->t_timer
[TCPT_REXMT
] ? acttp
->t_rxtcur
: 0;
1940 ti
->tcpi_rttcur
= acttp
->t_rttcur
;
1941 ti
->tcpi_srtt
= acttp
->t_srtt
>> TCP_RTT_SHIFT
;
1942 ti
->tcpi_rttvar
= acttp
->t_rttvar
>> TCP_RTTVAR_SHIFT
;
1943 ti
->tcpi_rttbest
= acttp
->t_rttbest
>> TCP_RTT_SHIFT
;
1945 /* tcpi_snd_ssthresh */
1947 /* tcpi_rcv_space */
1948 ti
->tcpi_snd_wnd
= mp_tp
->mpt_sndwnd
;
1949 ti
->tcpi_snd_nxt
= (uint32_t)mp_tp
->mpt_sndnxt
;
1950 ti
->tcpi_rcv_nxt
= (uint32_t)mp_tp
->mpt_rcvnxt
;
1952 ti
->tcpi_last_outif
= (acttp
->t_inpcb
->inp_last_outifp
== NULL
) ? 0 :
1953 acttp
->t_inpcb
->inp_last_outifp
->if_index
;
1956 mptcp_fill_info_bytestats(ti
, mpte
);
1957 /* tcpi_txpackets */
1959 /* tcpi_txretransmitbytes */
1960 /* tcpi_txunacked */
1961 /* tcpi_rxpackets */
1963 /* tcpi_rxduplicatebytes */
1964 /* tcpi_rxoutoforderbytes */
1966 /* tcpi_synrexmits */
1969 /* tcpi_cell_rxpackets */
1971 /* tcpi_cell_txpackets */
1973 /* tcpi_wifi_rxpackets */
1975 /* tcpi_wifi_txpackets */
1977 /* tcpi_wired_rxpackets */
1978 /* tcpi_wired_txpackets */
1979 /* tcpi_connstatus */
1982 /* tcpi_ecn_recv_ce */
1983 /* tcpi_ecn_recv_cwr */
1985 ti
->tcpi_rcvoopack
= acttp
->t_rcvoopack
;
1988 /* tcpi_sack_recovery_episode */
1989 /* tcpi_reordered_pkts */
1990 /* tcpi_dsack_sent */
1991 /* tcpi_dsack_recvd */
1994 ti
->tcpi_txretransmitpackets
= acttp
->t_stat
.rxmitpkts
;
1999 * Handle SOPT_GET for socket options issued on MP socket.
2002 mptcp_getopt(struct mptses
*mpte
, struct sockopt
*sopt
)
2004 int error
= 0, optval
= 0;
2007 * We only handle SOPT_GET for TCP level socket options; we should
2008 * not get here for socket level options since they are already
2009 * handled at the socket layer.
2011 if (sopt
->sopt_level
!= IPPROTO_TCP
) {
2012 error
= ENOPROTOOPT
;
2016 switch (sopt
->sopt_name
) {
2017 case PERSIST_TIMEOUT
:
2018 /* Only case for which we have a non-zero default */
2019 optval
= tcp_max_persist_timeout
;
2022 case TCP_RXT_FINDROP
:
2026 case TCP_CONNECTIONTIMEOUT
:
2027 case TCP_RXT_CONNDROPTIME
:
2028 case TCP_ADAPTIVE_READ_TIMEOUT
:
2029 case TCP_ADAPTIVE_WRITE_TIMEOUT
:
2030 case TCP_FASTOPEN_FORCE_ENABLE
:
2032 struct mptopt
*mpo
= mptcp_sopt_find(mpte
, sopt
);
2035 optval
= mpo
->mpo_intval
;
2040 /* The next ones are stored at the MPTCP-level */
2041 case TCP_NOTSENT_LOWAT
:
2042 if (mptetoso(mpte
)->so_flags
& SOF_NOTSENT_LOWAT
) {
2043 optval
= mptcp_get_notsent_lowat(mpte
);
2052 mptcp_fill_info(mpte
, &ti
);
2053 error
= sooptcopyout(sopt
, &ti
, sizeof(struct tcp_info
));
2057 case MPTCP_SERVICE_TYPE
:
2058 optval
= mpte
->mpte_svctype
;
2060 case MPTCP_ALTERNATE_PORT
:
2061 optval
= mpte
->mpte_alternate_port
;
2063 case MPTCP_FORCE_ENABLE
:
2064 optval
= !!(mpte
->mpte_flags
& MPTE_FORCE_ENABLE
);
2066 case MPTCP_EXPECTED_PROGRESS_TARGET
:
2067 error
= sooptcopyout(sopt
, &mpte
->mpte_time_target
, sizeof(mpte
->mpte_time_target
));
2072 error
= ENOPROTOOPT
;
2077 error
= sooptcopyout(sopt
, &optval
, sizeof(int));
2085 * MPTCP SOPT_{SET,GET} socket option handler, for options issued on the MP
2086 * socket, at SOL_SOCKET and IPPROTO_TCP levels. The former is restricted
2087 * to those that are allowed by mptcp_usr_socheckopt().
2090 mptcp_ctloutput(struct socket
*mp_so
, struct sockopt
*sopt
)
2092 struct mppcb
*mpp
= mpsotomppcb(mp_so
);
2093 struct mptses
*mpte
;
2096 if (mpp
== NULL
|| mpp
->mpp_state
== MPPCB_STATE_DEAD
) {
2100 mpte
= mptompte(mpp
);
2101 socket_lock_assert_owned(mp_so
);
2103 /* we only handle socket and TCP-level socket options for MPTCP */
2104 if (sopt
->sopt_level
!= SOL_SOCKET
&& sopt
->sopt_level
!= IPPROTO_TCP
) {
2109 switch (sopt
->sopt_dir
) {
2111 error
= mptcp_setopt(mpte
, sopt
);
2115 error
= mptcp_getopt(mpte
, sopt
);
2123 mptcp_sopt2str(int level
, int optname
)
2131 return "SO_LINGER_SEC";
2135 return "SO_KEEPALIVE";
2136 case SO_USELOOPBACK
:
2137 return "SO_USELOOPBACK";
2151 return "SO_SNDLOWAT";
2153 return "SO_RCVLOWAT";
2155 return "SO_SNDTIMEO";
2157 return "SO_RCVTIMEO";
2161 return "SO_NOSIGPIPE";
2163 return "SO_NOADDRERR";
2164 case SO_RESTRICTIONS
:
2165 return "SO_RESTRICTIONS";
2169 return "SO_PEERLABEL";
2171 return "SO_RANDOMPORT";
2172 case SO_TRAFFIC_CLASS
:
2173 return "SO_TRAFFIC_CLASS";
2174 case SO_RECV_TRAFFIC_CLASS
:
2175 return "SO_RECV_TRAFFIC_CLASS";
2176 case SO_TRAFFIC_CLASS_DBG
:
2177 return "SO_TRAFFIC_CLASS_DBG";
2178 case SO_PRIVILEGED_TRAFFIC_CLASS
:
2179 return "SO_PRIVILEGED_TRAFFIC_CLASS";
2181 return "SO_DEFUNCTIT";
2183 return "SO_DEFUNCTOK";
2185 return "SO_ISDEFUNCT";
2186 case SO_OPPORTUNISTIC
:
2187 return "SO_OPPORTUNISTIC";
2191 return "SO_RECV_ANYIF";
2192 case SO_NOWAKEFROMSLEEP
:
2193 return "SO_NOWAKEFROMSLEEP";
2194 case SO_NOAPNFALLBK
:
2195 return "SO_NOAPNFALLBK";
2196 case SO_MARK_CELLFALLBACK
:
2197 return "SO_CELLFALLBACK";
2199 return "SO_DELEGATED";
2200 case SO_DELEGATED_UUID
:
2201 return "SO_DELEGATED_UUID";
2203 case SO_NECP_ATTRIBUTES
:
2204 return "SO_NECP_ATTRIBUTES";
2205 case SO_NECP_CLIENTUUID
:
2206 return "SO_NECP_CLIENTUUID";
2214 return "TCP_NODELAY";
2216 return "TCP_KEEPALIVE";
2218 return "TCP_KEEPINTVL";
2220 return "TCP_KEEPCNT";
2221 case TCP_CONNECTIONTIMEOUT
:
2222 return "TCP_CONNECTIONTIMEOUT";
2223 case TCP_RXT_CONNDROPTIME
:
2224 return "TCP_RXT_CONNDROPTIME";
2225 case PERSIST_TIMEOUT
:
2226 return "PERSIST_TIMEOUT";
2227 case TCP_NOTSENT_LOWAT
:
2228 return "NOTSENT_LOWAT";
2229 case TCP_ADAPTIVE_READ_TIMEOUT
:
2230 return "ADAPTIVE_READ_TIMEOUT";
2231 case TCP_ADAPTIVE_WRITE_TIMEOUT
:
2232 return "ADAPTIVE_WRITE_TIMEOUT";
2233 case TCP_FASTOPEN_FORCE_ENABLE
:
2234 return "TCP_FASTOPEN_FORCE_ENABLE";
2235 case MPTCP_SERVICE_TYPE
:
2236 return "MPTCP_SERVICE_TYPE";
2237 case MPTCP_ALTERNATE_PORT
:
2238 return "MPTCP_ALTERNATE_PORT";
2239 case MPTCP_FORCE_ENABLE
:
2240 return "MPTCP_FORCE_ENABLE";
2241 case MPTCP_EXPECTED_PROGRESS_TARGET
:
2242 return "MPTCP_EXPECTED_PROGRESS_TARGET";
2252 mptcp_usr_preconnect(struct socket
*mp_so
)
2254 struct mptsub
*mpts
= NULL
;
2255 struct mppcb
*mpp
= mpsotomppcb(mp_so
);
2256 struct mptses
*mpte
;
2258 struct tcpcb
*tp
= NULL
;
2261 mpte
= mptompte(mpp
);
2263 mpts
= mptcp_get_subflow(mpte
, NULL
);
2265 os_log_error(mptcp_log_handle
, "%s - %lx: invalid preconnect ",
2266 __func__
, (unsigned long)VM_KERNEL_ADDRPERM(mpte
));
2269 mpts
->mpts_flags
&= ~MPTSF_TFO_REQD
;
2270 so
= mpts
->mpts_socket
;
2271 tp
= intotcpcb(sotoinpcb(so
));
2272 tp
->t_mpflags
&= ~TMPF_TFO_REQUEST
;
2273 error
= tcp_output(sototcpcb(so
));
2275 soclearfastopen(mp_so
);