]> git.saurik.com Git - apple/xnu.git/blame - bsd/netinet/mptcp_usrreq.c
xnu-7195.81.3.tar.gz
[apple/xnu.git] / bsd / netinet / mptcp_usrreq.c
CommitLineData
39236c6e 1/*
f427ee49 2 * Copyright (c) 2012-2020 Apple Inc. All rights reserved.
39236c6e
A
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
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>
37#include <sys/proc.h>
38#include <sys/proc_internal.h>
39#include <sys/resourcevar.h>
5ba3f43e
A
40#include <sys/kauth.h>
41#include <sys/priv.h>
39236c6e
A
42
43#include <net/if.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>
53
54#include <mach/sdt.h>
55
56static int mptcp_usr_attach(struct socket *, int, struct proc *);
57static int mptcp_usr_detach(struct socket *);
58static int mptcp_attach(struct socket *, struct proc *);
813fb2f6
A
59static int mptcp_usr_connectx(struct socket *, struct sockaddr *,
60 struct sockaddr *, struct proc *, uint32_t, sae_associd_t,
3e170ce0 61 sae_connid_t *, uint32_t, void *, uint32_t, struct uio *, user_ssize_t *);
39236c6e 62static int mptcp_getassocids(struct mptses *, uint32_t *, user_addr_t);
3e170ce0 63static int mptcp_getconnids(struct mptses *, sae_associd_t, uint32_t *,
39236c6e 64 user_addr_t);
3e170ce0 65static int mptcp_getconninfo(struct mptses *, sae_connid_t *, uint32_t *,
39236c6e
A
66 uint32_t *, int32_t *, user_addr_t, socklen_t *, user_addr_t, socklen_t *,
67 uint32_t *, user_addr_t, uint32_t *);
68static int mptcp_usr_control(struct socket *, u_long, caddr_t, struct ifnet *,
69 struct proc *);
5ba3f43e 70static int mptcp_disconnect(struct mptses *);
fe8ab488 71static int mptcp_usr_disconnect(struct socket *);
3e170ce0 72static int mptcp_usr_disconnectx(struct socket *, sae_associd_t, sae_connid_t);
39236c6e 73static struct mptses *mptcp_usrclosed(struct mptses *);
39236c6e
A
74static int mptcp_usr_rcvd(struct socket *, int);
75static int mptcp_usr_send(struct socket *, int, struct mbuf *,
76 struct sockaddr *, struct mbuf *, struct proc *);
77static int mptcp_usr_shutdown(struct socket *);
39236c6e
A
78static int mptcp_usr_sosend(struct socket *, struct sockaddr *, struct uio *,
79 struct mbuf *, struct mbuf *, int);
80static int mptcp_usr_socheckopt(struct socket *, struct sockopt *);
490019cf 81static int mptcp_usr_preconnect(struct socket *so);
39236c6e
A
82
83struct pr_usrreqs mptcp_usrreqs = {
0a7de745
A
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,
39236c6e
A
99};
100
5ba3f43e
A
101
102#if (DEVELOPMENT || DEBUG)
103static int mptcp_disable_entitlements = 0;
104SYSCTL_INT(_net_inet_mptcp, OID_AUTO, disable_entitlements, CTLFLAG_RW | CTLFLAG_LOCKED,
0a7de745 105 &mptcp_disable_entitlements, 0, "Disable Multipath TCP Entitlement Checking");
5ba3f43e
A
106#endif
107
108int mptcp_developer_mode = 0;
109SYSCTL_INT(_net_inet_mptcp, OID_AUTO, allow_aggregate, CTLFLAG_RW | CTLFLAG_LOCKED,
0a7de745 110 &mptcp_developer_mode, 0, "Allow the Multipath aggregation mode");
5ba3f43e 111
cb323159
A
112static unsigned long mptcp_expected_progress_headstart = 5000;
113SYSCTL_ULONG(_net_inet_mptcp, OID_AUTO, expected_progress_headstart, CTLFLAG_RW | CTLFLAG_LOCKED,
114 &mptcp_expected_progress_headstart, "Headstart to give MPTCP before meeting the progress deadline");
115
5ba3f43e 116
39236c6e
A
117/*
118 * Attaches an MPTCP control block to a socket.
119 */
120static int
121mptcp_usr_attach(struct socket *mp_so, int proto, struct proc *p)
122{
123#pragma unused(proto)
124 int error;
125
5ba3f43e 126 VERIFY(mpsotomppcb(mp_so) == NULL);
39236c6e
A
127
128 error = mptcp_attach(mp_so, p);
f427ee49 129 if (error) {
39236c6e 130 goto out;
0a7de745 131 }
f427ee49 132
0a7de745 133 if ((mp_so->so_options & SO_LINGER) && mp_so->so_linger == 0) {
f427ee49 134 mp_so->so_linger = (short)(TCP_LINGERTIME * hz);
0a7de745 135 }
39236c6e 136out:
0a7de745 137 return error;
39236c6e
A
138}
139
140/*
141 * Detaches an MPTCP control block from a socket.
142 */
143static int
144mptcp_usr_detach(struct socket *mp_so)
145{
5ba3f43e
A
146 struct mptses *mpte = mpsotompte(mp_so);
147 struct mppcb *mpp = mpsotomppcb(mp_so);
39236c6e 148
5ba3f43e 149 if (mpp == NULL || mpp->mpp_state == MPPCB_STATE_DEAD) {
cb323159
A
150 os_log_error(mptcp_log_handle, "%s - %lx: state: %d\n",
151 __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte),
152 mpp ? mpp->mpp_state : -1);
0a7de745 153 return EINVAL;
5ba3f43e 154 }
39236c6e 155
5ba3f43e
A
156 /*
157 * We are done with this MPTCP socket (it has been closed);
158 * trigger all subflows to be disconnected, if not already,
159 * by initiating the PCB detach sequence (SOF_PCBCLEARING
160 * will be set.)
161 */
162 mp_pcbdetach(mp_so);
163
164 mptcp_disconnect(mpte);
165
0a7de745 166 return 0;
39236c6e
A
167}
168
169/*
170 * Attach MPTCP protocol to socket, allocating MP control block,
171 * MPTCP session, control block, buffer space, etc.
172 */
173static int
174mptcp_attach(struct socket *mp_so, struct proc *p)
175{
176#pragma unused(p)
3e170ce0
A
177 struct mptses *mpte = NULL;
178 struct mptcb *mp_tp = NULL;
179 struct mppcb *mpp = NULL;
39236c6e
A
180 int error = 0;
181
182 if (mp_so->so_snd.sb_hiwat == 0 || mp_so->so_rcv.sb_hiwat == 0) {
5ba3f43e 183 error = soreserve(mp_so, tcp_sendspace, tcp_recvspace);
0a7de745 184 if (error != 0) {
39236c6e 185 goto out;
0a7de745 186 }
39236c6e
A
187 }
188
490019cf 189 if (mp_so->so_snd.sb_preconn_hiwat == 0) {
39037602 190 soreserve_preconnect(mp_so, 2048);
490019cf
A
191 }
192
0a7de745 193 if ((mp_so->so_rcv.sb_flags & SB_USRSIZE) == 0) {
5ba3f43e 194 mp_so->so_rcv.sb_flags |= SB_AUTOSIZE;
0a7de745
A
195 }
196 if ((mp_so->so_snd.sb_flags & SB_USRSIZE) == 0) {
5ba3f43e 197 mp_so->so_snd.sb_flags |= SB_AUTOSIZE;
0a7de745 198 }
5ba3f43e 199
39236c6e 200 /*
cb323159 201 * MPTCP send-socket buffers cannot be compressed, due to the
39236c6e
A
202 * fact that each mbuf chained via m_next is a M_PKTHDR
203 * which carries some MPTCP metadata.
204 */
205 mp_so->so_snd.sb_flags |= SB_NOCOMPRESS;
39236c6e 206
3e170ce0 207 if ((error = mp_pcballoc(mp_so, &mtcbinfo)) != 0) {
39236c6e 208 goto out;
3e170ce0 209 }
39236c6e 210
5ba3f43e 211 mpp = mpsotomppcb(mp_so);
3e170ce0 212 mpte = (struct mptses *)mpp->mpp_pcbe;
39236c6e 213 mp_tp = mpte->mpte_mptcb;
cb323159 214
39236c6e 215 VERIFY(mp_tp != NULL);
39236c6e 216out:
0a7de745 217 return error;
39236c6e
A
218}
219
39236c6e 220static int
bca245ac 221mptcp_entitlement_check(struct socket *mp_so, uint8_t svctype)
39236c6e 222{
5ba3f43e 223 struct mptses *mpte = mpsotompte(mp_so);
39236c6e 224
cb323159
A
225 /* First, check for mptcp_extended without delegation */
226 if (soopt_cred_check(mp_so, PRIV_NET_RESTRICTED_MULTIPATH_EXTENDED, TRUE, FALSE) == 0) {
227 /*
228 * This means the app has the extended entitlement. Thus,
229 * it's a first party app and can run without restrictions.
230 */
231 mpte->mpte_flags |= MPTE_FIRSTPARTY;
232 return 0;
233 }
234
235 /* Now with delegation */
236 if (mp_so->so_flags & SOF_DELEGATED &&
237 soopt_cred_check(mp_so, PRIV_NET_RESTRICTED_MULTIPATH_EXTENDED, TRUE, TRUE) == 0) {
5ba3f43e
A
238 /*
239 * This means the app has the extended entitlement. Thus,
240 * it's a first party app and can run without restrictions.
241 */
242 mpte->mpte_flags |= MPTE_FIRSTPARTY;
cb323159 243 return 0;
5ba3f43e 244 }
39236c6e 245
bca245ac 246 if (svctype == MPTCP_SVCTYPE_AGGREGATE) {
cb323159
A
247 if (mptcp_developer_mode) {
248 return 0;
249 }
250
f427ee49
A
251 os_log_error(mptcp_log_handle, "%s - %lx: MPTCP prohibited on svc %u\n",
252 __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte), mpte->mpte_svctype);
253 return -1;
5ba3f43e 254 }
39236c6e 255
f427ee49 256 return 0;
39236c6e
A
257}
258
259/*
260 * Common subroutine to open a MPTCP connection to one of the remote hosts
261 * specified by dst_sl. This includes allocating and establishing a
262 * subflow TCP connection, either initially to establish MPTCP connection,
263 * or to join an existing one. Returns a connection handle upon success.
264 */
265static int
813fb2f6 266mptcp_connectx(struct mptses *mpte, struct sockaddr *src,
5ba3f43e 267 struct sockaddr *dst, uint32_t ifscope, sae_connid_t *pcid)
39236c6e 268{
39236c6e
A
269 int error = 0;
270
813fb2f6 271 VERIFY(dst != NULL);
39236c6e
A
272 VERIFY(pcid != NULL);
273
5ba3f43e 274 error = mptcp_subflow_add(mpte, src, dst, ifscope, pcid);
39236c6e 275
0a7de745 276 return error;
39236c6e
A
277}
278
279/*
280 * User-protocol pru_connectx callback.
281 */
282static int
813fb2f6
A
283mptcp_usr_connectx(struct socket *mp_so, struct sockaddr *src,
284 struct sockaddr *dst, struct proc *p, uint32_t ifscope,
3e170ce0 285 sae_associd_t aid, sae_connid_t *pcid, uint32_t flags, void *arg,
490019cf 286 uint32_t arglen, struct uio *auio, user_ssize_t *bytes_written)
39236c6e 287{
5ba3f43e
A
288#pragma unused(p, aid, flags, arg, arglen)
289 struct mppcb *mpp = mpsotomppcb(mp_so);
3e170ce0
A
290 struct mptses *mpte = NULL;
291 struct mptcb *mp_tp = NULL;
0a7de745 292 user_ssize_t datalen;
39236c6e
A
293 int error = 0;
294
295 if (mpp == NULL || mpp->mpp_state == MPPCB_STATE_DEAD) {
cb323159
A
296 os_log_error(mptcp_log_handle, "%s - %lx: state %d\n",
297 __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte),
298 mpp ? mpp->mpp_state : -1);
39236c6e
A
299 error = EINVAL;
300 goto out;
301 }
302 mpte = mptompte(mpp);
3e170ce0 303 mp_tp = mpte->mpte_mptcb;
3e170ce0
A
304
305 if (mp_tp->mpt_flags & MPTCPF_FALLBACK_TO_TCP) {
cb323159
A
306 os_log_error(mptcp_log_handle, "%s - %lx: fell back to TCP\n",
307 __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte));
3e170ce0
A
308 error = EINVAL;
309 goto out;
310 }
311
9d749ea3
A
312 if (dst->sa_family != AF_INET && dst->sa_family != AF_INET6) {
313 error = EAFNOSUPPORT;
314 goto out;
315 }
316
5ba3f43e
A
317 if (dst->sa_family == AF_INET &&
318 dst->sa_len != sizeof(mpte->__mpte_dst_v4)) {
cb323159
A
319 os_log_error(mptcp_log_handle, "%s - %lx: IPv4 dst len %u\n",
320 __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte), dst->sa_len);
5ba3f43e
A
321 error = EINVAL;
322 goto out;
323 }
324
325 if (dst->sa_family == AF_INET6 &&
326 dst->sa_len != sizeof(mpte->__mpte_dst_v6)) {
cb323159
A
327 os_log_error(mptcp_log_handle, "%s - %lx: IPv6 dst len %u\n",
328 __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte), dst->sa_len);
5ba3f43e
A
329 error = EINVAL;
330 goto out;
331 }
332
333 if (!(mpte->mpte_flags & MPTE_SVCTYPE_CHECKED)) {
bca245ac 334 if (mptcp_entitlement_check(mp_so, mpte->mpte_svctype) < 0) {
5ba3f43e
A
335 error = EPERM;
336 goto out;
337 }
338
339 mpte->mpte_flags |= MPTE_SVCTYPE_CHECKED;
340 }
341
0a7de745 342 if ((mp_so->so_state & (SS_ISCONNECTED | SS_ISCONNECTING)) == 0) {
cb323159 343 memcpy(&mpte->mpte_u_dst, dst, dst->sa_len);
5ba3f43e
A
344 }
345
346 if (src) {
9d749ea3
A
347 if (src->sa_family != AF_INET && src->sa_family != AF_INET6) {
348 error = EAFNOSUPPORT;
349 goto out;
350 }
351
5ba3f43e
A
352 if (src->sa_family == AF_INET &&
353 src->sa_len != sizeof(mpte->__mpte_src_v4)) {
cb323159
A
354 os_log_error(mptcp_log_handle, "%s - %lx: IPv4 src len %u\n",
355 __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte), src->sa_len);
5ba3f43e
A
356 error = EINVAL;
357 goto out;
358 }
359
360 if (src->sa_family == AF_INET6 &&
361 src->sa_len != sizeof(mpte->__mpte_src_v6)) {
cb323159
A
362 os_log_error(mptcp_log_handle, "%s - %lx: IPv6 src len %u\n",
363 __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte), src->sa_len);
5ba3f43e
A
364 error = EINVAL;
365 goto out;
366 }
367
0a7de745 368 if ((mp_so->so_state & (SS_ISCONNECTED | SS_ISCONNECTING)) == 0) {
cb323159 369 memcpy(&mpte->mpte_u_src, src, src->sa_len);
5ba3f43e
A
370 }
371 }
372
373 error = mptcp_connectx(mpte, src, dst, ifscope, pcid);
490019cf
A
374
375 /* If there is data, copy it */
376 if (auio != NULL) {
377 datalen = uio_resid(auio);
378 socket_unlock(mp_so, 0);
379 error = mp_so->so_proto->pr_usrreqs->pru_sosend(mp_so, NULL,
380 (uio_t) auio, NULL, NULL, 0);
5ba3f43e 381
0a7de745 382 if (error == 0 || error == EWOULDBLOCK) {
490019cf 383 *bytes_written = datalen - uio_resid(auio);
0a7de745 384 }
490019cf 385
0a7de745 386 if (error == EWOULDBLOCK) {
490019cf 387 error = EINPROGRESS;
0a7de745 388 }
490019cf
A
389
390 socket_lock(mp_so, 0);
490019cf
A
391 }
392
39236c6e 393out:
0a7de745 394 return error;
39236c6e
A
395}
396
397/*
398 * Handle SIOCGASSOCIDS ioctl for PF_MULTIPATH domain.
399 */
400static int
401mptcp_getassocids(struct mptses *mpte, uint32_t *cnt, user_addr_t aidp)
402{
39236c6e 403 /* MPTCP has at most 1 association */
3e170ce0 404 *cnt = (mpte->mpte_associd != SAE_ASSOCID_ANY) ? 1 : 0;
39236c6e
A
405
406 /* just asking how many there are? */
0a7de745
A
407 if (aidp == USER_ADDR_NULL) {
408 return 0;
409 }
39236c6e 410
0a7de745
A
411 return copyout(&mpte->mpte_associd, aidp,
412 sizeof(mpte->mpte_associd));
39236c6e
A
413}
414
415/*
416 * Handle SIOCGCONNIDS ioctl for PF_MULTIPATH domain.
417 */
418static int
3e170ce0 419mptcp_getconnids(struct mptses *mpte, sae_associd_t aid, uint32_t *cnt,
39236c6e
A
420 user_addr_t cidp)
421{
422 struct mptsub *mpts;
423 int error = 0;
424
3e170ce0 425 if (aid != SAE_ASSOCID_ANY && aid != SAE_ASSOCID_ALL &&
0a7de745
A
426 aid != mpte->mpte_associd) {
427 return EINVAL;
428 }
39236c6e
A
429
430 *cnt = mpte->mpte_numflows;
431
432 /* just asking how many there are? */
0a7de745
A
433 if (cidp == USER_ADDR_NULL) {
434 return 0;
435 }
39236c6e
A
436
437 TAILQ_FOREACH(mpts, &mpte->mpte_subflows, mpts_entry) {
438 if ((error = copyout(&mpts->mpts_connid, cidp,
0a7de745 439 sizeof(mpts->mpts_connid))) != 0) {
39236c6e 440 break;
0a7de745 441 }
39236c6e 442
0a7de745 443 cidp += sizeof(mpts->mpts_connid);
39236c6e
A
444 }
445
0a7de745 446 return error;
39236c6e
A
447}
448
449/*
450 * Handle SIOCGCONNINFO ioctl for PF_MULTIPATH domain.
451 */
452static int
3e170ce0 453mptcp_getconninfo(struct mptses *mpte, sae_connid_t *cid, uint32_t *flags,
39236c6e
A
454 uint32_t *ifindex, int32_t *soerror, user_addr_t src, socklen_t *src_len,
455 user_addr_t dst, socklen_t *dst_len, uint32_t *aux_type,
456 user_addr_t aux_data, uint32_t *aux_len)
457{
39236c6e 458 *flags = 0;
5ba3f43e
A
459 *aux_type = 0;
460 *ifindex = 0;
461 *soerror = 0;
462
cb323159 463 /* MPTCP-level global stats */
5ba3f43e
A
464 if (*cid == SAE_CONNID_ALL) {
465 struct socket *mp_so = mptetoso(mpte);
466 struct mptcb *mp_tp = mpte->mpte_mptcb;
467 struct conninfo_multipathtcp mptcp_ci;
cb323159 468 int error = 0;
5ba3f43e 469
0a7de745
A
470 if (*aux_len != 0 && *aux_len != sizeof(mptcp_ci)) {
471 return EINVAL;
472 }
5ba3f43e 473
0a7de745 474 if (mp_so->so_state & SS_ISCONNECTING) {
5ba3f43e 475 *flags |= CIF_CONNECTING;
0a7de745
A
476 }
477 if (mp_so->so_state & SS_ISCONNECTED) {
5ba3f43e 478 *flags |= CIF_CONNECTED;
0a7de745
A
479 }
480 if (mp_so->so_state & SS_ISDISCONNECTING) {
5ba3f43e 481 *flags |= CIF_DISCONNECTING;
0a7de745
A
482 }
483 if (mp_so->so_state & SS_ISDISCONNECTED) {
5ba3f43e 484 *flags |= CIF_DISCONNECTED;
0a7de745
A
485 }
486 if (!(mp_tp->mpt_flags & MPTCPF_FALLBACK_TO_TCP)) {
5ba3f43e 487 *flags |= CIF_MP_CAPABLE;
0a7de745
A
488 }
489 if (mp_tp->mpt_flags & MPTCPF_FALLBACK_TO_TCP) {
5ba3f43e 490 *flags |= CIF_MP_DEGRADED;
0a7de745 491 }
5ba3f43e
A
492
493 *src_len = 0;
494 *dst_len = 0;
495
496 *aux_type = CIAUX_MPTCP;
497 *aux_len = sizeof(mptcp_ci);
39236c6e 498
5ba3f43e 499 if (aux_data != USER_ADDR_NULL) {
cb323159 500 const struct mptsub *mpts;
5ba3f43e 501 int initial_info_set = 0;
cb323159 502 unsigned long i = 0;
39236c6e 503
0a7de745 504 bzero(&mptcp_ci, sizeof(mptcp_ci));
5ba3f43e
A
505 mptcp_ci.mptcpci_subflow_count = mpte->mpte_numflows;
506 mptcp_ci.mptcpci_switch_count = mpte->mpte_subflow_switches;
39236c6e 507
5ba3f43e
A
508 VERIFY(sizeof(mptcp_ci.mptcpci_itfstats) == sizeof(mpte->mpte_itfstats));
509 memcpy(mptcp_ci.mptcpci_itfstats, mpte->mpte_itfstats, sizeof(mptcp_ci.mptcpci_itfstats));
813fb2f6 510
5ba3f43e 511 TAILQ_FOREACH(mpts, &mpte->mpte_subflows, mpts_entry) {
0a7de745 512 if (i >= sizeof(mptcp_ci.mptcpci_subflow_connids) / sizeof(sae_connid_t)) {
5ba3f43e 513 break;
0a7de745 514 }
5ba3f43e 515 mptcp_ci.mptcpci_subflow_connids[i] = mpts->mpts_connid;
813fb2f6 516
5ba3f43e 517 if (mpts->mpts_flags & MPTSF_INITIAL_SUB) {
cb323159
A
518 const struct inpcb *inp;
519
5ba3f43e 520 inp = sotoinpcb(mpts->mpts_socket);
3e170ce0 521
5ba3f43e
A
522 mptcp_ci.mptcpci_init_rxbytes = inp->inp_stat->rxbytes;
523 mptcp_ci.mptcpci_init_txbytes = inp->inp_stat->txbytes;
524 initial_info_set = 1;
525 }
39236c6e 526
5ba3f43e 527 mptcpstats_update(mptcp_ci.mptcpci_itfstats, mpts);
39236c6e 528
5ba3f43e
A
529 i++;
530 }
39236c6e 531
5ba3f43e
A
532 if (initial_info_set == 0) {
533 mptcp_ci.mptcpci_init_rxbytes = mpte->mpte_init_rxbytes;
534 mptcp_ci.mptcpci_init_txbytes = mpte->mpte_init_txbytes;
535 }
39236c6e 536
0a7de745 537 if (mpte->mpte_flags & MPTE_FIRSTPARTY) {
5ba3f43e 538 mptcp_ci.mptcpci_flags |= MPTCPCI_FIRSTPARTY;
0a7de745 539 }
39236c6e 540
5ba3f43e
A
541 error = copyout(&mptcp_ci, aux_data, sizeof(mptcp_ci));
542 if (error != 0) {
cb323159
A
543 os_log_error(mptcp_log_handle, "%s - %lx: copyout failed: %d\n",
544 __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte), error);
0a7de745 545 return error;
39236c6e 546 }
39236c6e
A
547 }
548
0a7de745 549 return 0;
39236c6e
A
550 }
551
cb323159
A
552 /* Any stats of any subflow */
553 if (*cid == SAE_CONNID_ANY) {
554 const struct mptsub *mpts;
555 struct socket *so;
556 const struct inpcb *inp;
557 int error = 0;
558
559 mpts = TAILQ_FIRST(&mpte->mpte_subflows);
560 if (mpts == NULL) {
561 return ENXIO;
0a7de745 562 }
39236c6e 563
cb323159
A
564 so = mpts->mpts_socket;
565 inp = sotoinpcb(so);
566
567 if (inp->inp_vflag & INP_IPV4) {
568 error = in_getconninfo(so, SAE_CONNID_ANY, flags, ifindex,
569 soerror, src, src_len, dst, dst_len,
570 aux_type, aux_data, aux_len);
571 } else {
572 error = in6_getconninfo(so, SAE_CONNID_ANY, flags, ifindex,
573 soerror, src, src_len, dst, dst_len,
574 aux_type, aux_data, aux_len);
575 }
576
577 if (error != 0) {
578 os_log_error(mptcp_log_handle, "%s - %lx:error from in_getconninfo %d\n",
579 __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte), error);
580 return error;
581 }
582
583 if (mpts->mpts_flags & MPTSF_MP_CAPABLE) {
584 *flags |= CIF_MP_CAPABLE;
585 }
586 if (mpts->mpts_flags & MPTSF_MP_DEGRADED) {
587 *flags |= CIF_MP_DEGRADED;
588 }
589 if (mpts->mpts_flags & MPTSF_MP_READY) {
590 *flags |= CIF_MP_READY;
591 }
592 if (mpts->mpts_flags & MPTSF_ACTIVE) {
593 *flags |= CIF_MP_ACTIVE;
594 }
39037602 595
cb323159 596 return 0;
0a7de745 597 } else {
cb323159 598 /* Per-interface stats */
f427ee49 599 const struct mptsub *mpts, *orig_mpts = NULL;
cb323159
A
600 struct conninfo_tcp tcp_ci;
601 const struct inpcb *inp;
602 struct socket *so;
603 int error = 0;
604 int index;
39236c6e 605
f427ee49
A
606 /* cid is thus an ifindex - range-check first! */
607 if (*cid > USHRT_MAX) {
608 return EINVAL;
609 }
610
cb323159 611 bzero(&tcp_ci, sizeof(tcp_ci));
39236c6e 612
cb323159
A
613 /* First, get a subflow to fill in the "regular" info. */
614 TAILQ_FOREACH(mpts, &mpte->mpte_subflows, mpts_entry) {
615 const struct ifnet *ifp = sotoinpcb(mpts->mpts_socket)->inp_last_outifp;
39236c6e 616
cb323159
A
617 if (ifp && ifp->if_index == *cid) {
618 break;
619 }
620 }
621
622 if (mpts == NULL) {
623 /* No subflow there - well, let's just get the basic itf-info */
624 goto interface_info;
625 }
626
627 so = mpts->mpts_socket;
628 inp = sotoinpcb(so);
629
630 /* Give it USER_ADDR_NULL, because we are doing this on our own */
631 if (inp->inp_vflag & INP_IPV4) {
632 error = in_getconninfo(so, SAE_CONNID_ANY, flags, ifindex,
633 soerror, src, src_len, dst, dst_len,
634 aux_type, USER_ADDR_NULL, aux_len);
635 } else {
636 error = in6_getconninfo(so, SAE_CONNID_ANY, flags, ifindex,
637 soerror, src, src_len, dst, dst_len,
638 aux_type, USER_ADDR_NULL, aux_len);
639 }
640
641 if (error != 0) {
642 os_log_error(mptcp_log_handle, "%s - %lx:error from in_getconninfo %d\n",
643 __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte), error);
644 return error;
645 }
646
647 /* ToDo: Nobody is reading these flags on subflows. Why bother ? */
648 if (mpts->mpts_flags & MPTSF_MP_CAPABLE) {
649 *flags |= CIF_MP_CAPABLE;
650 }
651 if (mpts->mpts_flags & MPTSF_MP_DEGRADED) {
652 *flags |= CIF_MP_DEGRADED;
653 }
654 if (mpts->mpts_flags & MPTSF_MP_READY) {
655 *flags |= CIF_MP_READY;
656 }
657 if (mpts->mpts_flags & MPTSF_ACTIVE) {
658 *flags |= CIF_MP_ACTIVE;
659 }
660
661 /*
662 * Now, we gather the metrics (aka., tcp_info) and roll them in
663 * across all subflows of this interface to build an aggregated
664 * view.
665 *
666 * We take the TCP_INFO from the first subflow as the "master",
667 * feeding into those fields that we do not roll.
668 */
669 if (aux_data != USER_ADDR_NULL) {
670 tcp_getconninfo(so, &tcp_ci);
671
672 orig_mpts = mpts;
673 TAILQ_FOREACH(mpts, &mpte->mpte_subflows, mpts_entry) {
674 const struct inpcb *mptsinp = sotoinpcb(mpts->mpts_socket);
675 const struct ifnet *ifp;
676
677 ifp = mptsinp->inp_last_outifp;
678
679 if (ifp == NULL || ifp->if_index != *cid || mpts == orig_mpts) {
680 continue;
681 }
682
683 /* Roll the itf-stats into the tcp_info */
684 tcp_ci.tcpci_tcp_info.tcpi_txbytes +=
685 mptsinp->inp_stat->txbytes;
686 tcp_ci.tcpci_tcp_info.tcpi_rxbytes +=
687 mptsinp->inp_stat->rxbytes;
688
689 tcp_ci.tcpci_tcp_info.tcpi_wifi_txbytes +=
690 mptsinp->inp_wstat->txbytes;
691 tcp_ci.tcpci_tcp_info.tcpi_wifi_rxbytes +=
692 mptsinp->inp_wstat->rxbytes;
693
694 tcp_ci.tcpci_tcp_info.tcpi_wired_txbytes +=
695 mptsinp->inp_Wstat->txbytes;
696 tcp_ci.tcpci_tcp_info.tcpi_wired_rxbytes +=
697 mptsinp->inp_Wstat->rxbytes;
698
699 tcp_ci.tcpci_tcp_info.tcpi_cell_txbytes +=
700 mptsinp->inp_cstat->txbytes;
701 tcp_ci.tcpci_tcp_info.tcpi_cell_rxbytes +=
702 mptsinp->inp_cstat->rxbytes;
703 }
704 }
705
706interface_info:
707 *aux_type = CIAUX_TCP;
708 if (*aux_len == 0) {
709 *aux_len = sizeof(tcp_ci);
710 } else if (aux_data != USER_ADDR_NULL) {
711 boolean_t create;
712
713 /*
714 * Finally, old subflows might have been closed - we
715 * want this data as well, so grab it from the interface
716 * stats.
717 */
718 create = orig_mpts != NULL;
719
720 /*
721 * When we found a subflow, we are willing to create a stats-index
722 * because we have some data to return. If there isn't a subflow,
723 * nor anything in the stats, return EINVAL. Because the
724 * ifindex belongs to something that doesn't exist.
725 */
f427ee49 726 index = mptcpstats_get_index_by_ifindex(mpte->mpte_itfstats, (u_short)(*cid), false);
cb323159
A
727 if (index == -1) {
728 os_log_error(mptcp_log_handle,
729 "%s - %lx: Asking for too many ifindex: %u subcount %u, mpts? %s\n",
730 __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte),
731 *cid, mpte->mpte_numflows,
732 orig_mpts ? "yes" : "no");
733
734 if (orig_mpts == NULL) {
735 return EINVAL;
736 }
737 } else {
738 struct mptcp_itf_stats *stats;
739
740 stats = &mpte->mpte_itfstats[index];
741
742 /* Roll the itf-stats into the tcp_info */
743 tcp_ci.tcpci_tcp_info.tcpi_last_outif = *cid;
744 tcp_ci.tcpci_tcp_info.tcpi_txbytes +=
745 stats->mpis_txbytes;
746 tcp_ci.tcpci_tcp_info.tcpi_rxbytes +=
747 stats->mpis_rxbytes;
748
749 tcp_ci.tcpci_tcp_info.tcpi_wifi_txbytes +=
750 stats->mpis_wifi_txbytes;
751 tcp_ci.tcpci_tcp_info.tcpi_wifi_rxbytes +=
752 stats->mpis_wifi_rxbytes;
753
754 tcp_ci.tcpci_tcp_info.tcpi_wired_txbytes +=
755 stats->mpis_wired_txbytes;
756 tcp_ci.tcpci_tcp_info.tcpi_wired_rxbytes +=
757 stats->mpis_wired_rxbytes;
758
759 tcp_ci.tcpci_tcp_info.tcpi_cell_txbytes +=
760 stats->mpis_cell_txbytes;
761 tcp_ci.tcpci_tcp_info.tcpi_cell_rxbytes +=
762 stats->mpis_cell_rxbytes;
763 }
764
765 *aux_len = min(*aux_len, sizeof(tcp_ci));
766 error = copyout(&tcp_ci, aux_data, *aux_len);
767 if (error != 0) {
768 return error;
769 }
770 }
771 }
5ba3f43e 772
0a7de745 773 return 0;
39236c6e
A
774}
775
776/*
777 * User-protocol pru_control callback.
778 */
779static int
780mptcp_usr_control(struct socket *mp_so, u_long cmd, caddr_t data,
781 struct ifnet *ifp, struct proc *p)
782{
783#pragma unused(ifp, p)
5ba3f43e 784 struct mppcb *mpp = mpsotomppcb(mp_so);
39236c6e
A
785 struct mptses *mpte;
786 int error = 0;
787
788 if (mpp == NULL || mpp->mpp_state == MPPCB_STATE_DEAD) {
789 error = EINVAL;
790 goto out;
791 }
792 mpte = mptompte(mpp);
39236c6e
A
793
794 switch (cmd) {
0a7de745 795 case SIOCGASSOCIDS32: { /* struct so_aidreq32 */
39236c6e 796 struct so_aidreq32 aidr;
0a7de745 797 bcopy(data, &aidr, sizeof(aidr));
39236c6e
A
798 error = mptcp_getassocids(mpte, &aidr.sar_cnt,
799 aidr.sar_aidp);
0a7de745
A
800 if (error == 0) {
801 bcopy(&aidr, data, sizeof(aidr));
802 }
39236c6e
A
803 break;
804 }
805
0a7de745 806 case SIOCGASSOCIDS64: { /* struct so_aidreq64 */
39236c6e 807 struct so_aidreq64 aidr;
0a7de745 808 bcopy(data, &aidr, sizeof(aidr));
39236c6e 809 error = mptcp_getassocids(mpte, &aidr.sar_cnt,
f427ee49 810 (user_addr_t)aidr.sar_aidp);
0a7de745
A
811 if (error == 0) {
812 bcopy(&aidr, data, sizeof(aidr));
813 }
39236c6e
A
814 break;
815 }
816
0a7de745 817 case SIOCGCONNIDS32: { /* struct so_cidreq32 */
39236c6e 818 struct so_cidreq32 cidr;
0a7de745 819 bcopy(data, &cidr, sizeof(cidr));
39236c6e
A
820 error = mptcp_getconnids(mpte, cidr.scr_aid, &cidr.scr_cnt,
821 cidr.scr_cidp);
0a7de745
A
822 if (error == 0) {
823 bcopy(&cidr, data, sizeof(cidr));
824 }
39236c6e
A
825 break;
826 }
827
0a7de745 828 case SIOCGCONNIDS64: { /* struct so_cidreq64 */
39236c6e 829 struct so_cidreq64 cidr;
0a7de745 830 bcopy(data, &cidr, sizeof(cidr));
39236c6e 831 error = mptcp_getconnids(mpte, cidr.scr_aid, &cidr.scr_cnt,
f427ee49 832 (user_addr_t)cidr.scr_cidp);
0a7de745
A
833 if (error == 0) {
834 bcopy(&cidr, data, sizeof(cidr));
835 }
39236c6e
A
836 break;
837 }
838
0a7de745 839 case SIOCGCONNINFO32: { /* struct so_cinforeq32 */
39236c6e 840 struct so_cinforeq32 cifr;
0a7de745 841 bcopy(data, &cifr, sizeof(cifr));
39236c6e
A
842 error = mptcp_getconninfo(mpte, &cifr.scir_cid,
843 &cifr.scir_flags, &cifr.scir_ifindex, &cifr.scir_error,
844 cifr.scir_src, &cifr.scir_src_len, cifr.scir_dst,
845 &cifr.scir_dst_len, &cifr.scir_aux_type, cifr.scir_aux_data,
846 &cifr.scir_aux_len);
0a7de745
A
847 if (error == 0) {
848 bcopy(&cifr, data, sizeof(cifr));
849 }
39236c6e
A
850 break;
851 }
852
0a7de745 853 case SIOCGCONNINFO64: { /* struct so_cinforeq64 */
39236c6e 854 struct so_cinforeq64 cifr;
0a7de745 855 bcopy(data, &cifr, sizeof(cifr));
39236c6e
A
856 error = mptcp_getconninfo(mpte, &cifr.scir_cid,
857 &cifr.scir_flags, &cifr.scir_ifindex, &cifr.scir_error,
f427ee49
A
858 (user_addr_t)cifr.scir_src, &cifr.scir_src_len,
859 (user_addr_t)cifr.scir_dst, &cifr.scir_dst_len,
860 &cifr.scir_aux_type, (user_addr_t)cifr.scir_aux_data,
39236c6e 861 &cifr.scir_aux_len);
0a7de745
A
862 if (error == 0) {
863 bcopy(&cifr, data, sizeof(cifr));
864 }
39236c6e
A
865 break;
866 }
867
39236c6e
A
868 default:
869 error = EOPNOTSUPP;
870 break;
871 }
872out:
0a7de745 873 return error;
39236c6e
A
874}
875
39236c6e 876static int
5ba3f43e 877mptcp_disconnect(struct mptses *mpte)
39236c6e 878{
39236c6e
A
879 struct socket *mp_so;
880 struct mptcb *mp_tp;
881 int error = 0;
882
5ba3f43e 883 mp_so = mptetoso(mpte);
39236c6e
A
884 mp_tp = mpte->mpte_mptcb;
885
5ba3f43e
A
886 DTRACE_MPTCP3(disconnectx, struct mptses *, mpte,
887 struct socket *, mp_so, struct mptcb *, mp_tp);
3e170ce0 888
5ba3f43e
A
889 /* if we're not detached, go thru socket state checks */
890 if (!(mp_so->so_flags & SOF_PCBCLEARING)) {
0a7de745 891 if (!(mp_so->so_state & (SS_ISCONNECTED |
5ba3f43e
A
892 SS_ISCONNECTING))) {
893 error = ENOTCONN;
39236c6e
A
894 goto out;
895 }
5ba3f43e
A
896 if (mp_so->so_state & SS_ISDISCONNECTING) {
897 error = EALREADY;
898 goto out;
3e170ce0 899 }
39236c6e
A
900 }
901
5ba3f43e
A
902 mptcp_cancel_all_timers(mp_tp);
903 if (mp_tp->mpt_state < MPTCPS_ESTABLISHED) {
904 mptcp_close(mpte, mp_tp);
905 } else if ((mp_so->so_options & SO_LINGER) &&
906 mp_so->so_linger == 0) {
907 mptcp_drop(mpte, mp_tp, 0);
908 } else {
909 soisdisconnecting(mp_so);
910 sbflush(&mp_so->so_rcv);
0a7de745 911 if (mptcp_usrclosed(mpte) != NULL) {
5ba3f43e 912 mptcp_output(mpte);
0a7de745 913 }
39236c6e
A
914 }
915
0a7de745 916 if (error == 0) {
5ba3f43e 917 mptcp_subflow_workloop(mpte);
0a7de745 918 }
5ba3f43e 919
39236c6e 920out:
0a7de745 921 return error;
39236c6e
A
922}
923
fe8ab488 924/*
5ba3f43e 925 * Wrapper function to support disconnect on socket
fe8ab488
A
926 */
927static int
928mptcp_usr_disconnect(struct socket *mp_so)
929{
0a7de745 930 return mptcp_disconnect(mpsotompte(mp_so));
fe8ab488
A
931}
932
39236c6e
A
933/*
934 * User-protocol pru_disconnectx callback.
935 */
936static int
3e170ce0 937mptcp_usr_disconnectx(struct socket *mp_so, sae_associd_t aid, sae_connid_t cid)
39236c6e 938{
0a7de745
A
939 if (aid != SAE_ASSOCID_ANY && aid != SAE_ASSOCID_ALL) {
940 return EINVAL;
941 }
39236c6e 942
0a7de745
A
943 if (cid != SAE_CONNID_ANY && cid != SAE_CONNID_ALL) {
944 return EINVAL;
945 }
39236c6e 946
0a7de745 947 return mptcp_usr_disconnect(mp_so);
39236c6e
A
948}
949
a39ff7e2
A
950void
951mptcp_finish_usrclosed(struct mptses *mpte)
39236c6e 952{
a39ff7e2
A
953 struct mptcb *mp_tp = mpte->mpte_mptcb;
954 struct socket *mp_so = mptetoso(mpte);
39236c6e 955
fe8ab488 956 if (mp_tp->mpt_state == MPTCPS_CLOSED) {
39236c6e 957 mpte = mptcp_close(mpte, mp_tp);
39236c6e 958 } else if (mp_tp->mpt_state >= MPTCPS_FIN_WAIT_2) {
39236c6e
A
959 soisdisconnected(mp_so);
960 } else {
a39ff7e2
A
961 struct mptsub *mpts;
962
39236c6e 963 TAILQ_FOREACH(mpts, &mpte->mpte_subflows, mpts_entry) {
0a7de745
A
964 if ((mp_so->so_state & (SS_CANTRCVMORE | SS_CANTSENDMORE)) ==
965 (SS_CANTRCVMORE | SS_CANTSENDMORE)) {
5ba3f43e 966 mptcp_subflow_disconnect(mpte, mpts);
0a7de745 967 } else {
5ba3f43e 968 mptcp_subflow_shutdown(mpte, mpts);
0a7de745 969 }
39236c6e
A
970 }
971 }
a39ff7e2
A
972}
973
974/*
975 * User issued close, and wish to trail thru shutdown states.
976 */
977static struct mptses *
978mptcp_usrclosed(struct mptses *mpte)
979{
980 struct mptcb *mp_tp = mpte->mpte_mptcb;
981
982 mptcp_close_fsm(mp_tp, MPCE_CLOSE);
983
984 /* Not everything has been acknowledged - don't close the subflows! */
0a7de745
A
985 if (mp_tp->mpt_sndnxt + 1 != mp_tp->mpt_sndmax) {
986 return mpte;
987 }
a39ff7e2
A
988
989 mptcp_finish_usrclosed(mpte);
39236c6e 990
0a7de745 991 return mpte;
39236c6e
A
992}
993
39236c6e
A
994/*
995 * After a receive, possible send some update to peer.
996 */
997static int
998mptcp_usr_rcvd(struct socket *mp_so, int flags)
999{
1000#pragma unused(flags)
5ba3f43e 1001 struct mppcb *mpp = mpsotomppcb(mp_so);
39236c6e 1002 struct mptses *mpte;
cb323159 1003 struct mptsub *mpts;
39236c6e
A
1004 int error = 0;
1005
1006 if (mpp == NULL || mpp->mpp_state == MPPCB_STATE_DEAD) {
1007 error = EINVAL;
1008 goto out;
1009 }
cb323159 1010
39236c6e 1011 mpte = mptompte(mpp);
cb323159
A
1012
1013 TAILQ_FOREACH(mpts, &mpte->mpte_subflows, mpts_entry) {
1014 struct socket *so = mpts->mpts_socket;
1015
1016 if (so->so_proto->pr_flags & PR_WANTRCVD && so->so_pcb != NULL) {
1017 (*so->so_proto->pr_usrreqs->pru_rcvd)(so, 0);
1018 }
1019 }
39236c6e
A
1020
1021 error = mptcp_output(mpte);
1022out:
0a7de745 1023 return error;
39236c6e
A
1024}
1025
1026/*
1027 * Do a send by putting data in the output queue.
1028 */
1029static int
1030mptcp_usr_send(struct socket *mp_so, int prus_flags, struct mbuf *m,
1031 struct sockaddr *nam, struct mbuf *control, struct proc *p)
1032{
1033#pragma unused(nam, p)
5ba3f43e 1034 struct mppcb *mpp = mpsotomppcb(mp_so);
39236c6e
A
1035 struct mptses *mpte;
1036 int error = 0;
1037
0a7de745 1038 if (prus_flags & (PRUS_OOB | PRUS_EOF)) {
39236c6e
A
1039 error = EOPNOTSUPP;
1040 goto out;
1041 }
1042
1043 if (nam != NULL) {
1044 error = EOPNOTSUPP;
1045 goto out;
1046 }
1047
1048 if (control != NULL && control->m_len != 0) {
1049 error = EOPNOTSUPP;
1050 goto out;
1051 }
1052
1053 if (mpp == NULL || mpp->mpp_state == MPPCB_STATE_DEAD) {
1054 error = ECONNRESET;
1055 goto out;
1056 }
1057 mpte = mptompte(mpp);
1058 VERIFY(mpte != NULL);
1059
490019cf 1060 if (!(mp_so->so_state & SS_ISCONNECTED) &&
5ba3f43e 1061 !(mp_so->so_flags1 & SOF1_PRECONNECT_DATA)) {
39236c6e
A
1062 error = ENOTCONN;
1063 goto out;
1064 }
1065
1066 mptcp_insert_dsn(mpp, m);
1067 VERIFY(mp_so->so_snd.sb_flags & SB_NOCOMPRESS);
5ba3f43e 1068 sbappendstream(&mp_so->so_snd, m);
39236c6e
A
1069 m = NULL;
1070
490019cf 1071 error = mptcp_output(mpte);
0a7de745 1072 if (error != 0) {
490019cf 1073 goto out;
0a7de745 1074 }
39037602 1075
490019cf 1076 if (mp_so->so_state & SS_ISCONNECTING) {
0a7de745 1077 if (mp_so->so_state & SS_NBIO) {
490019cf 1078 error = EWOULDBLOCK;
0a7de745 1079 } else {
490019cf 1080 error = sbwait(&mp_so->so_snd);
0a7de745 1081 }
39236c6e 1082 }
39037602 1083
39236c6e
A
1084out:
1085 if (error) {
0a7de745 1086 if (m != NULL) {
39236c6e 1087 m_freem(m);
0a7de745
A
1088 }
1089 if (control != NULL) {
39236c6e 1090 m_freem(control);
0a7de745 1091 }
39236c6e 1092 }
0a7de745 1093 return error;
39236c6e
A
1094}
1095
1096/*
1097 * Mark the MPTCP connection as being incapable of further output.
1098 */
1099static int
1100mptcp_usr_shutdown(struct socket *mp_so)
1101{
5ba3f43e 1102 struct mppcb *mpp = mpsotomppcb(mp_so);
39236c6e
A
1103 struct mptses *mpte;
1104 int error = 0;
1105
1106 if (mpp == NULL || mpp->mpp_state == MPPCB_STATE_DEAD) {
1107 error = EINVAL;
1108 goto out;
1109 }
1110 mpte = mptompte(mpp);
1111 VERIFY(mpte != NULL);
1112
1113 socantsendmore(mp_so);
1114
1115 mpte = mptcp_usrclosed(mpte);
0a7de745 1116 if (mpte != NULL) {
39236c6e 1117 error = mptcp_output(mpte);
0a7de745 1118 }
39236c6e 1119out:
0a7de745 1120 return error;
39236c6e
A
1121}
1122
1123/*
1124 * Copy the contents of uio into a properly sized mbuf chain.
1125 */
1126static int
f427ee49 1127mptcp_uiotombuf(struct uio *uio, int how, user_ssize_t space, struct mbuf **top)
39236c6e
A
1128{
1129 struct mbuf *m, *mb, *nm = NULL, *mtail = NULL;
f427ee49
A
1130 int progress, len, error;
1131 user_ssize_t resid, tot;
39236c6e
A
1132
1133 VERIFY(top != NULL && *top == NULL);
1134
1135 /*
1136 * space can be zero or an arbitrary large value bound by
1137 * the total data supplied by the uio.
1138 */
1139 resid = uio_resid(uio);
0a7de745 1140 if (space > 0) {
f427ee49 1141 tot = MIN(resid, space);
0a7de745 1142 } else {
39236c6e 1143 tot = resid;
0a7de745 1144 }
39236c6e 1145
f427ee49 1146 if (tot < 0 || tot > INT_MAX) {
0a7de745
A
1147 return EINVAL;
1148 }
39236c6e 1149
f427ee49
A
1150 len = (int)tot;
1151 if (len == 0) {
39236c6e 1152 len = 1;
0a7de745 1153 }
39236c6e
A
1154
1155 /* Loop and append maximum sized mbufs to the chain tail. */
1156 while (len > 0) {
1157 uint32_t m_needed = 1;
1158
0a7de745 1159 if (njcl > 0 && len > MBIGCLBYTES) {
39236c6e
A
1160 mb = m_getpackets_internal(&m_needed, 1,
1161 how, 1, M16KCLBYTES);
0a7de745 1162 } else if (len > MCLBYTES) {
39236c6e
A
1163 mb = m_getpackets_internal(&m_needed, 1,
1164 how, 1, MBIGCLBYTES);
0a7de745 1165 } else if (len >= (signed)MINCLSIZE) {
39236c6e
A
1166 mb = m_getpackets_internal(&m_needed, 1,
1167 how, 1, MCLBYTES);
0a7de745 1168 } else {
39236c6e 1169 mb = m_gethdr(how, MT_DATA);
0a7de745 1170 }
39236c6e
A
1171
1172 /* Fail the whole operation if one mbuf can't be allocated. */
1173 if (mb == NULL) {
0a7de745 1174 if (nm != NULL) {
39236c6e 1175 m_freem(nm);
0a7de745
A
1176 }
1177 return ENOBUFS;
39236c6e
A
1178 }
1179
1180 /* Book keeping. */
1181 VERIFY(mb->m_flags & M_PKTHDR);
1182 len -= ((mb->m_flags & M_EXT) ? mb->m_ext.ext_size : MHLEN);
0a7de745 1183 if (mtail != NULL) {
39236c6e 1184 mtail->m_next = mb;
0a7de745 1185 } else {
39236c6e 1186 nm = mb;
0a7de745 1187 }
39236c6e
A
1188 mtail = mb;
1189 }
1190
1191 m = nm;
39236c6e
A
1192
1193 progress = 0;
1194 /* Fill all mbufs with uio data and update header information. */
1195 for (mb = m; mb != NULL; mb = mb->m_next) {
f427ee49
A
1196 /* tot >= 0 && tot <= INT_MAX (see above) */
1197 len = MIN((int)M_TRAILINGSPACE(mb), (int)(tot - progress));
39236c6e
A
1198
1199 error = uiomove(mtod(mb, char *), len, uio);
1200 if (error != 0) {
1201 m_freem(m);
0a7de745 1202 return error;
39236c6e
A
1203 }
1204
1205 /* each mbuf is M_PKTHDR chained via m_next */
1206 mb->m_len = len;
1207 mb->m_pkthdr.len = len;
1208
1209 progress += len;
1210 }
1211 VERIFY(progress == tot);
1212 *top = m;
0a7de745 1213 return 0;
39236c6e
A
1214}
1215
1216/*
1217 * MPTCP socket protocol-user socket send routine, derived from sosend().
1218 */
1219static int
1220mptcp_usr_sosend(struct socket *mp_so, struct sockaddr *addr, struct uio *uio,
1221 struct mbuf *top, struct mbuf *control, int flags)
1222{
1223#pragma unused(addr)
f427ee49 1224 user_ssize_t resid, space;
39236c6e
A
1225 int error, sendflags;
1226 struct proc *p = current_proc();
1227 int sblocked = 0;
1228
1229 /* UIO is required for now, due to per-mbuf M_PKTHDR constrains */
1230 if (uio == NULL || top != NULL) {
1231 error = EINVAL;
1232 goto out;
1233 }
1234 resid = uio_resid(uio);
1235
1236 socket_lock(mp_so, 1);
1237 so_update_last_owner_locked(mp_so, p);
1238 so_update_policy(mp_so);
1239
1240 VERIFY(mp_so->so_type == SOCK_STREAM);
1241 VERIFY(!(mp_so->so_flags & SOF_MP_SUBFLOW));
1242
f427ee49 1243 if (flags & (MSG_OOB | MSG_DONTROUTE)) {
39236c6e
A
1244 error = EOPNOTSUPP;
1245 socket_unlock(mp_so, 1);
1246 goto out;
1247 }
1248
1249 /*
1250 * In theory resid should be unsigned. However, space must be
1251 * signed, as it might be less than 0 if we over-committed, and we
1252 * must use a signed comparison of space and resid. On the other
1253 * hand, a negative resid causes us to loop sending 0-length
1254 * segments to the protocol.
1255 */
f427ee49
A
1256 if (resid < 0 || resid > INT_MAX ||
1257 (flags & MSG_EOR) || control != NULL) {
39236c6e
A
1258 error = EINVAL;
1259 socket_unlock(mp_so, 1);
1260 goto out;
1261 }
1262
1263 OSIncrementAtomicLong(&p->p_stats->p_ru.ru_msgsnd);
1264
1265 do {
1266 error = sosendcheck(mp_so, NULL, resid, 0, 0, flags,
f427ee49 1267 &sblocked);
0a7de745 1268 if (error != 0) {
39236c6e 1269 goto release;
0a7de745 1270 }
39236c6e
A
1271
1272 space = sbspace(&mp_so->so_snd);
1273 do {
1274 socket_unlock(mp_so, 0);
1275 /*
1276 * Copy the data from userland into an mbuf chain.
1277 */
f427ee49 1278 error = mptcp_uiotombuf(uio, M_WAITOK, space, &top);
39236c6e
A
1279 if (error != 0) {
1280 socket_lock(mp_so, 0);
1281 goto release;
1282 }
1283 VERIFY(top != NULL);
1284 space -= resid - uio_resid(uio);
1285 resid = uio_resid(uio);
1286 socket_lock(mp_so, 0);
1287
1288 /*
1289 * Compute flags here, for pru_send and NKEs.
1290 */
1291 sendflags = (resid > 0 && space > 0) ?
1292 PRUS_MORETOCOME : 0;
1293
1294 /*
1295 * Socket filter processing
1296 */
1297 VERIFY(control == NULL);
1298 error = sflt_data_out(mp_so, NULL, &top, &control, 0);
1299 if (error != 0) {
1300 if (error == EJUSTRETURN) {
1301 error = 0;
1302 top = NULL;
1303 /* always free control if any */
1304 }
1305 goto release;
1306 }
1307 if (control != NULL) {
1308 m_freem(control);
1309 control = NULL;
1310 }
1311
1312 /*
1313 * Pass data to protocol.
1314 */
1315 error = (*mp_so->so_proto->pr_usrreqs->pru_send)
1316 (mp_so, sendflags, top, NULL, NULL, p);
1317
1318 top = NULL;
0a7de745 1319 if (error != 0) {
39236c6e 1320 goto release;
0a7de745 1321 }
39236c6e
A
1322 } while (resid != 0 && space > 0);
1323 } while (resid != 0);
1324
1325release:
0a7de745 1326 if (sblocked) {
39236c6e 1327 sbunlock(&mp_so->so_snd, FALSE); /* will unlock socket */
0a7de745 1328 } else {
39236c6e 1329 socket_unlock(mp_so, 1);
0a7de745 1330 }
39236c6e 1331out:
0a7de745 1332 if (top != NULL) {
39236c6e 1333 m_freem(top);
0a7de745
A
1334 }
1335 if (control != NULL) {
39236c6e 1336 m_freem(control);
0a7de745 1337 }
39236c6e 1338
5ba3f43e 1339 soclearfastopen(mp_so);
490019cf 1340
0a7de745 1341 return error;
39236c6e
A
1342}
1343
1344/*
1345 * Called to filter SOPT_{SET,GET} for SOL_SOCKET level socket options.
1346 * This routine simply indicates to the caller whether or not to proceed
1347 * further with the given socket option. This is invoked by sosetoptlock()
1348 * and sogetoptlock().
1349 */
1350static int
1351mptcp_usr_socheckopt(struct socket *mp_so, struct sockopt *sopt)
1352{
1353#pragma unused(mp_so)
1354 int error = 0;
1355
1356 VERIFY(sopt->sopt_level == SOL_SOCKET);
1357
1358 /*
1359 * We could check for sopt_dir (set/get) here, but we'll just
1360 * let the caller deal with it as appropriate; therefore the
1361 * following is a superset of the socket options which we
1362 * allow for set/get.
1363 *
1364 * XXX: adi@apple.com
1365 *
1366 * Need to consider the following cases:
1367 *
5ba3f43e 1368 * a. Certain socket options don't have a clear definition
39236c6e
A
1369 * on the expected behavior post connect(2). At the time
1370 * those options are issued on the MP socket, there may
1371 * be existing subflow sockets that are already connected.
1372 */
1373 switch (sopt->sopt_name) {
0a7de745
A
1374 case SO_LINGER: /* MP */
1375 case SO_LINGER_SEC: /* MP */
1376 case SO_TYPE: /* MP */
1377 case SO_NREAD: /* MP */
1378 case SO_NWRITE: /* MP */
1379 case SO_ERROR: /* MP */
1380 case SO_SNDBUF: /* MP */
1381 case SO_RCVBUF: /* MP */
1382 case SO_SNDLOWAT: /* MP */
1383 case SO_RCVLOWAT: /* MP */
1384 case SO_SNDTIMEO: /* MP */
1385 case SO_RCVTIMEO: /* MP */
1386 case SO_NKE: /* MP */
1387 case SO_NOSIGPIPE: /* MP */
1388 case SO_NOADDRERR: /* MP */
1389 case SO_LABEL: /* MP */
1390 case SO_PEERLABEL: /* MP */
94ff46dc 1391 case SO_DEFUNCTIT: /* MP */
0a7de745
A
1392 case SO_DEFUNCTOK: /* MP */
1393 case SO_ISDEFUNCT: /* MP */
1394 case SO_TRAFFIC_CLASS_DBG: /* MP */
1395 case SO_DELEGATED: /* MP */
1396 case SO_DELEGATED_UUID: /* MP */
5ba3f43e
A
1397#if NECP
1398 case SO_NECP_ATTRIBUTES:
1399 case SO_NECP_CLIENTUUID:
1400#endif /* NECP */
cb323159 1401 case SO_MPKL_SEND_INFO:
39236c6e
A
1402 /*
1403 * Tell the caller that these options are to be processed.
1404 */
1405 break;
1406
0a7de745
A
1407 case SO_DEBUG: /* MP + subflow */
1408 case SO_KEEPALIVE: /* MP + subflow */
1409 case SO_USELOOPBACK: /* MP + subflow */
1410 case SO_RANDOMPORT: /* MP + subflow */
1411 case SO_TRAFFIC_CLASS: /* MP + subflow */
1412 case SO_RECV_TRAFFIC_CLASS: /* MP + subflow */
1413 case SO_PRIVILEGED_TRAFFIC_CLASS: /* MP + subflow */
1414 case SO_RECV_ANYIF: /* MP + subflow */
1415 case SO_RESTRICTIONS: /* MP + subflow */
1416 case SO_FLUSH: /* MP + subflow */
fe8ab488 1417 case SO_NOWAKEFROMSLEEP:
39037602 1418 case SO_NOAPNFALLBK:
5ba3f43e 1419 case SO_MARK_CELLFALLBACK:
39236c6e
A
1420 /*
1421 * Tell the caller that these options are to be processed;
1422 * these will also be recorded later by mptcp_setopt().
1423 *
1424 * NOTE: Only support integer option value for now.
1425 */
0a7de745 1426 if (sopt->sopt_valsize != sizeof(int)) {
39236c6e 1427 error = EINVAL;
0a7de745 1428 }
39236c6e
A
1429 break;
1430
1431 default:
1432 /*
1433 * Tell the caller to stop immediately and return an error.
1434 */
1435 error = ENOPROTOOPT;
1436 break;
1437 }
1438
0a7de745 1439 return error;
39236c6e
A
1440}
1441
1442/*
1443 * Issue SOPT_SET for all MPTCP subflows (for integer option values.)
1444 */
1445static int
1446mptcp_setopt_apply(struct mptses *mpte, struct mptopt *mpo)
1447{
1448 struct socket *mp_so;
1449 struct mptsub *mpts;
1450 struct mptopt smpo;
1451 int error = 0;
1452
1453 /* just bail now if this isn't applicable to subflow sockets */
1454 if (!(mpo->mpo_flags & MPOF_SUBFLOW_OK)) {
1455 error = ENOPROTOOPT;
1456 goto out;
1457 }
1458
1459 /*
1460 * Skip those that are handled internally; these options
1461 * should not have been recorded and marked with the
1462 * MPOF_SUBFLOW_OK by mptcp_setopt(), but just in case.
1463 */
1464 if (mpo->mpo_level == SOL_SOCKET &&
1465 (mpo->mpo_name == SO_NOSIGPIPE || mpo->mpo_name == SO_NOADDRERR)) {
1466 error = ENOPROTOOPT;
1467 goto out;
1468 }
1469
5ba3f43e 1470 mp_so = mptetoso(mpte);
39236c6e
A
1471
1472 /*
1473 * Don't bother going further if there's no subflow; mark the option
1474 * with MPOF_INTERIM so that we know whether or not to remove this
1475 * option upon encountering an error while issuing it during subflow
1476 * socket creation.
1477 */
1478 if (mpte->mpte_numflows == 0) {
1479 VERIFY(TAILQ_EMPTY(&mpte->mpte_subflows));
1480 mpo->mpo_flags |= MPOF_INTERIM;
1481 /* return success */
1482 goto out;
1483 }
1484
0a7de745 1485 bzero(&smpo, sizeof(smpo));
39236c6e
A
1486 smpo.mpo_flags |= MPOF_SUBFLOW_OK;
1487 smpo.mpo_level = mpo->mpo_level;
1488 smpo.mpo_name = mpo->mpo_name;
1489
1490 /* grab exisiting values in case we need to rollback */
1491 TAILQ_FOREACH(mpts, &mpte->mpte_subflows, mpts_entry) {
1492 struct socket *so;
1493
0a7de745 1494 mpts->mpts_flags &= ~(MPTSF_SOPT_OLDVAL | MPTSF_SOPT_INPROG);
39236c6e
A
1495 mpts->mpts_oldintval = 0;
1496 smpo.mpo_intval = 0;
1497 VERIFY(mpts->mpts_socket != NULL);
1498 so = mpts->mpts_socket;
39236c6e
A
1499 if (mptcp_subflow_sogetopt(mpte, so, &smpo) == 0) {
1500 mpts->mpts_flags |= MPTSF_SOPT_OLDVAL;
1501 mpts->mpts_oldintval = smpo.mpo_intval;
1502 }
39236c6e
A
1503 }
1504
1505 /* apply socket option */
1506 TAILQ_FOREACH(mpts, &mpte->mpte_subflows, mpts_entry) {
1507 struct socket *so;
1508
39236c6e
A
1509 mpts->mpts_flags |= MPTSF_SOPT_INPROG;
1510 VERIFY(mpts->mpts_socket != NULL);
1511 so = mpts->mpts_socket;
5ba3f43e 1512 error = mptcp_subflow_sosetopt(mpte, mpts, mpo);
0a7de745 1513 if (error != 0) {
39236c6e 1514 break;
0a7de745 1515 }
39236c6e
A
1516 }
1517
1518 /* cleanup, and rollback if needed */
1519 TAILQ_FOREACH(mpts, &mpte->mpte_subflows, mpts_entry) {
1520 struct socket *so;
1521
39236c6e
A
1522 if (!(mpts->mpts_flags & MPTSF_SOPT_INPROG)) {
1523 /* clear in case it's set */
1524 mpts->mpts_flags &= ~MPTSF_SOPT_OLDVAL;
1525 mpts->mpts_oldintval = 0;
39236c6e
A
1526 continue;
1527 }
1528 if (!(mpts->mpts_flags & MPTSF_SOPT_OLDVAL)) {
1529 mpts->mpts_flags &= ~MPTSF_SOPT_INPROG;
1530 VERIFY(mpts->mpts_oldintval == 0);
39236c6e
A
1531 continue;
1532 }
1533 /* error during sosetopt, so roll it back */
1534 if (error != 0) {
1535 VERIFY(mpts->mpts_socket != NULL);
1536 so = mpts->mpts_socket;
39236c6e 1537 smpo.mpo_intval = mpts->mpts_oldintval;
5ba3f43e 1538 mptcp_subflow_sosetopt(mpte, mpts, &smpo);
39236c6e
A
1539 }
1540 mpts->mpts_oldintval = 0;
0a7de745 1541 mpts->mpts_flags &= ~(MPTSF_SOPT_OLDVAL | MPTSF_SOPT_INPROG);
39236c6e
A
1542 }
1543
1544out:
0a7de745 1545 return error;
39236c6e
A
1546}
1547
1548/*
1549 * Handle SOPT_SET for socket options issued on MP socket.
1550 */
1551static int
1552mptcp_setopt(struct mptses *mpte, struct sockopt *sopt)
1553{
5ba3f43e 1554 int error = 0, optval = 0, level, optname, rec = 1;
39236c6e
A
1555 struct mptopt smpo, *mpo = NULL;
1556 struct socket *mp_so;
39236c6e
A
1557
1558 level = sopt->sopt_level;
1559 optname = sopt->sopt_name;
1560
5ba3f43e 1561 mp_so = mptetoso(mpte);
39236c6e
A
1562
1563 /*
1564 * Record socket options which are applicable to subflow sockets so
1565 * that we can replay them for new ones; see mptcp_usr_socheckopt()
1566 * for the list of eligible socket-level options.
1567 */
1568 if (level == SOL_SOCKET) {
1569 switch (optname) {
1570 case SO_DEBUG:
1571 case SO_KEEPALIVE:
1572 case SO_USELOOPBACK:
1573 case SO_RANDOMPORT:
1574 case SO_TRAFFIC_CLASS:
1575 case SO_RECV_TRAFFIC_CLASS:
1576 case SO_PRIVILEGED_TRAFFIC_CLASS:
1577 case SO_RECV_ANYIF:
1578 case SO_RESTRICTIONS:
fe8ab488 1579 case SO_NOWAKEFROMSLEEP:
39037602 1580 case SO_NOAPNFALLBK:
5ba3f43e 1581 case SO_MARK_CELLFALLBACK:
39236c6e
A
1582 /* record it */
1583 break;
1584 case SO_FLUSH:
1585 /* don't record it */
1586 rec = 0;
1587 break;
5ba3f43e 1588
cb323159
A
1589 /* Next ones, record at MPTCP-level */
1590 case SO_DELEGATED:
1591 error = sooptcopyin(sopt, &mpte->mpte_epid,
1592 sizeof(int), sizeof(int));
1593 if (error != 0) {
1594 goto err_out;
1595 }
1596
1597 goto out;
1598 case SO_DELEGATED_UUID:
1599 error = sooptcopyin(sopt, &mpte->mpte_euuid,
1600 sizeof(uuid_t), sizeof(uuid_t));
1601 if (error != 0) {
1602 goto err_out;
1603 }
1604
1605 goto out;
5ba3f43e
A
1606#if NECP
1607 case SO_NECP_CLIENTUUID:
1608 if (!uuid_is_null(mpsotomppcb(mp_so)->necp_client_uuid)) {
1609 error = EINVAL;
cb323159 1610 goto err_out;
5ba3f43e
A
1611 }
1612
1613 error = sooptcopyin(sopt, &mpsotomppcb(mp_so)->necp_client_uuid,
0a7de745 1614 sizeof(uuid_t), sizeof(uuid_t));
5ba3f43e 1615 if (error != 0) {
cb323159 1616 goto err_out;
5ba3f43e
A
1617 }
1618
1619 mpsotomppcb(mp_so)->necp_cb = mptcp_session_necp_cb;
1620 error = necp_client_register_multipath_cb(mp_so->last_pid,
0a7de745
A
1621 mpsotomppcb(mp_so)->necp_client_uuid,
1622 mpsotomppcb(mp_so));
1623 if (error) {
cb323159 1624 goto err_out;
0a7de745 1625 }
5ba3f43e
A
1626
1627 if (uuid_is_null(mpsotomppcb(mp_so)->necp_client_uuid)) {
1628 error = EINVAL;
cb323159 1629 goto err_out;
5ba3f43e
A
1630 }
1631
1632 goto out;
1633 case SO_NECP_ATTRIBUTES:
1634#endif /* NECP */
39236c6e 1635 default:
5ba3f43e 1636 /* nothing to do; just return */
39236c6e
A
1637 goto out;
1638 }
1639 } else {
1640 switch (optname) {
1641 case TCP_NODELAY:
1642 case TCP_RXT_FINDROP:
1643 case TCP_KEEPALIVE:
1644 case TCP_KEEPINTVL:
1645 case TCP_KEEPCNT:
1646 case TCP_CONNECTIONTIMEOUT:
1647 case TCP_RXT_CONNDROPTIME:
1648 case PERSIST_TIMEOUT:
5ba3f43e
A
1649 case TCP_ADAPTIVE_READ_TIMEOUT:
1650 case TCP_ADAPTIVE_WRITE_TIMEOUT:
39236c6e
A
1651 /* eligible; record it */
1652 break;
fe8ab488
A
1653 case TCP_NOTSENT_LOWAT:
1654 /* record at MPTCP level */
1655 error = sooptcopyin(sopt, &optval, sizeof(optval),
1656 sizeof(optval));
0a7de745 1657 if (error) {
cb323159 1658 goto err_out;
0a7de745 1659 }
fe8ab488
A
1660 if (optval < 0) {
1661 error = EINVAL;
cb323159 1662 goto err_out;
fe8ab488
A
1663 } else {
1664 if (optval == 0) {
1665 mp_so->so_flags &= ~SOF_NOTSENT_LOWAT;
0a7de745 1666 error = mptcp_set_notsent_lowat(mpte, 0);
fe8ab488
A
1667 } else {
1668 mp_so->so_flags |= SOF_NOTSENT_LOWAT;
1669 error = mptcp_set_notsent_lowat(mpte,
1670 optval);
1671 }
cb323159
A
1672
1673 if (error) {
1674 goto err_out;
1675 }
fe8ab488 1676 }
5ba3f43e
A
1677 goto out;
1678 case MPTCP_SERVICE_TYPE:
1679 /* record at MPTCP level */
1680 error = sooptcopyin(sopt, &optval, sizeof(optval),
1681 sizeof(optval));
0a7de745 1682 if (error) {
cb323159 1683 goto err_out;
0a7de745 1684 }
5ba3f43e
A
1685 if (optval < 0 || optval >= MPTCP_SVCTYPE_MAX) {
1686 error = EINVAL;
cb323159 1687 goto err_out;
5ba3f43e
A
1688 }
1689
f427ee49 1690 if (mptcp_entitlement_check(mp_so, (uint8_t)optval) < 0) {
5ba3f43e 1691 error = EACCES;
cb323159 1692 goto err_out;
5ba3f43e
A
1693 }
1694
f427ee49 1695 mpte->mpte_svctype = (uint8_t)optval;
5ba3f43e
A
1696 mpte->mpte_flags |= MPTE_SVCTYPE_CHECKED;
1697
a39ff7e2
A
1698 goto out;
1699 case MPTCP_ALTERNATE_PORT:
1700 /* record at MPTCP level */
1701 error = sooptcopyin(sopt, &optval, sizeof(optval),
1702 sizeof(optval));
0a7de745 1703 if (error) {
cb323159 1704 goto err_out;
0a7de745 1705 }
a39ff7e2
A
1706
1707 if (optval < 0 || optval > UINT16_MAX) {
1708 error = EINVAL;
cb323159 1709 goto err_out;
a39ff7e2
A
1710 }
1711
f427ee49 1712 mpte->mpte_alternate_port = (uint16_t)optval;
a39ff7e2 1713
fe8ab488 1714 goto out;
cb323159
A
1715 case MPTCP_FORCE_ENABLE:
1716 /* record at MPTCP level */
1717 error = sooptcopyin(sopt, &optval, sizeof(optval),
1718 sizeof(optval));
1719 if (error) {
1720 goto err_out;
1721 }
1722
1723 if (optval < 0 || optval > 1) {
1724 error = EINVAL;
1725 goto err_out;
1726 }
1727
1728 if (optval) {
1729 mpte->mpte_flags |= MPTE_FORCE_ENABLE;
1730 } else {
1731 mpte->mpte_flags &= ~MPTE_FORCE_ENABLE;
1732 }
1733
1734 goto out;
1735 case MPTCP_EXPECTED_PROGRESS_TARGET:
1736 {
1737 struct mptcb *mp_tp = mpte->mpte_mptcb;
1738 uint64_t mach_time_target;
1739 uint64_t nanoseconds;
1740
1741 if (mpte->mpte_svctype != MPTCP_SVCTYPE_TARGET_BASED) {
1742 os_log(mptcp_log_handle, "%s - %lx: Can't set urgent activity when svctype is %u\n",
1743 __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte), mpte->mpte_svctype);
1744 error = EINVAL;
1745 goto err_out;
1746 }
1747
1748 error = sooptcopyin(sopt, &mach_time_target, sizeof(mach_time_target), sizeof(mach_time_target));
1749 if (error) {
1750 goto err_out;
1751 }
1752
1753 if (!mptcp_ok_to_create_subflows(mp_tp)) {
1754 os_log(mptcp_log_handle, "%s - %lx: Not ok to create subflows, state %u flags %#x\n",
1755 __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte), mp_tp->mpt_state, mp_tp->mpt_flags);
1756 error = EINVAL;
1757 goto err_out;
1758 }
1759
1760 if (mach_time_target) {
1761 uint64_t time_now = 0;
1762 uint64_t time_now_nanoseconds;
1763
1764 absolutetime_to_nanoseconds(mach_time_target, &nanoseconds);
1765 nanoseconds = nanoseconds - (mptcp_expected_progress_headstart * NSEC_PER_MSEC);
1766
1767 time_now = mach_continuous_time();
1768 absolutetime_to_nanoseconds(time_now, &time_now_nanoseconds);
1769
1770 nanoseconds_to_absolutetime(nanoseconds, &mach_time_target);
1771 /* If the timer is already running and it would
1772 * fire in less than mptcp_expected_progress_headstart
1773 * seconds, then it's not worth canceling it.
1774 */
1775 if (mpte->mpte_time_target &&
1776 mpte->mpte_time_target < time_now &&
1777 time_now_nanoseconds > nanoseconds - (mptcp_expected_progress_headstart * NSEC_PER_MSEC)) {
1778 os_log(mptcp_log_handle, "%s - %lx: Not rescheduling timer %llu now %llu target %llu\n",
1779 __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte),
1780 mpte->mpte_time_target,
1781 time_now,
1782 mach_time_target);
1783 goto out;
1784 }
1785 }
1786
1787 mpte->mpte_time_target = mach_time_target;
1788 mptcp_set_urgency_timer(mpte);
1789
1790 goto out;
1791 }
39236c6e
A
1792 default:
1793 /* not eligible */
1794 error = ENOPROTOOPT;
cb323159 1795 goto err_out;
39236c6e
A
1796 }
1797 }
1798
0a7de745
A
1799 if ((error = sooptcopyin(sopt, &optval, sizeof(optval),
1800 sizeof(optval))) != 0) {
cb323159 1801 goto err_out;
0a7de745 1802 }
39236c6e
A
1803
1804 if (rec) {
1805 /* search for an existing one; if not found, allocate */
0a7de745 1806 if ((mpo = mptcp_sopt_find(mpte, sopt)) == NULL) {
f427ee49 1807 mpo = mptcp_sopt_alloc(Z_WAITOK);
0a7de745 1808 }
39236c6e
A
1809
1810 if (mpo == NULL) {
1811 error = ENOBUFS;
cb323159 1812 goto err_out;
39236c6e 1813 } else {
39236c6e
A
1814 /* initialize or update, as needed */
1815 mpo->mpo_intval = optval;
1816 if (!(mpo->mpo_flags & MPOF_ATTACHED)) {
1817 mpo->mpo_level = level;
1818 mpo->mpo_name = optname;
1819 mptcp_sopt_insert(mpte, mpo);
1820 }
39236c6e
A
1821 /* this can be issued on the subflow socket */
1822 mpo->mpo_flags |= MPOF_SUBFLOW_OK;
1823 }
1824 } else {
0a7de745 1825 bzero(&smpo, sizeof(smpo));
39236c6e
A
1826 mpo = &smpo;
1827 mpo->mpo_flags |= MPOF_SUBFLOW_OK;
1828 mpo->mpo_level = level;
1829 mpo->mpo_name = optname;
1830 mpo->mpo_intval = optval;
1831 }
39236c6e
A
1832
1833 /* issue this socket option on existing subflows */
cb323159
A
1834 error = mptcp_setopt_apply(mpte, mpo);
1835 if (error != 0 && (mpo->mpo_flags & MPOF_ATTACHED)) {
1836 VERIFY(mpo != &smpo);
1837 mptcp_sopt_remove(mpte, mpo);
1838 mptcp_sopt_free(mpo);
39236c6e 1839 }
cb323159
A
1840 if (mpo == &smpo) {
1841 mpo->mpo_flags &= ~MPOF_INTERIM;
39236c6e 1842 }
cb323159
A
1843
1844 if (error) {
1845 goto err_out;
1846 }
1847
1848out:
1849
1850 return 0;
1851
1852err_out:
1853 os_log_error(mptcp_log_handle, "%s - %lx: sopt %s (%d, %d) val %d can't be issued error %d\n",
1854 __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte),
1855 mptcp_sopt2str(level, optname), level, optname, optval, error);
0a7de745 1856 return error;
39236c6e
A
1857}
1858
cb323159
A
1859static void
1860mptcp_fill_info_bytestats(struct tcp_info *ti, struct mptses *mpte)
1861{
1862 struct mptsub *mpts;
1863 int i;
1864
1865 TAILQ_FOREACH(mpts, &mpte->mpte_subflows, mpts_entry) {
1866 const struct inpcb *inp = sotoinpcb(mpts->mpts_socket);
1867
1868 if (inp == NULL) {
1869 continue;
1870 }
1871
1872 ti->tcpi_txbytes += inp->inp_stat->txbytes;
1873 ti->tcpi_rxbytes += inp->inp_stat->rxbytes;
1874 ti->tcpi_cell_txbytes += inp->inp_cstat->txbytes;
1875 ti->tcpi_cell_rxbytes += inp->inp_cstat->rxbytes;
1876 ti->tcpi_wifi_txbytes += inp->inp_wstat->txbytes;
1877 ti->tcpi_wifi_rxbytes += inp->inp_wstat->rxbytes;
1878 ti->tcpi_wired_txbytes += inp->inp_Wstat->txbytes;
1879 ti->tcpi_wired_rxbytes += inp->inp_Wstat->rxbytes;
1880 }
1881
1882 for (i = 0; i < MPTCP_ITFSTATS_SIZE; i++) {
1883 struct mptcp_itf_stats *stats = &mpte->mpte_itfstats[i];
1884
1885 ti->tcpi_txbytes += stats->mpis_txbytes;
1886 ti->tcpi_rxbytes += stats->mpis_rxbytes;
1887
1888 ti->tcpi_wifi_txbytes += stats->mpis_wifi_txbytes;
1889 ti->tcpi_wifi_rxbytes += stats->mpis_wifi_rxbytes;
1890
1891 ti->tcpi_wired_txbytes += stats->mpis_wired_txbytes;
1892 ti->tcpi_wired_rxbytes += stats->mpis_wired_rxbytes;
1893
1894 ti->tcpi_cell_txbytes += stats->mpis_cell_txbytes;
1895 ti->tcpi_cell_rxbytes += stats->mpis_cell_rxbytes;
1896 }
1897}
1898
1899static void
1900mptcp_fill_info(struct mptses *mpte, struct tcp_info *ti)
1901{
1902 struct mptsub *actsub = mpte->mpte_active_sub;
1903 struct mptcb *mp_tp = mpte->mpte_mptcb;
1904 struct tcpcb *acttp = NULL;
1905
1906 if (actsub) {
1907 acttp = sototcpcb(actsub->mpts_socket);
1908 }
1909
1910 bzero(ti, sizeof(*ti));
1911
f427ee49 1912 ti->tcpi_state = (uint8_t)mp_tp->mpt_state;
cb323159
A
1913 /* tcpi_options */
1914 /* tcpi_snd_wscale */
1915 /* tcpi_rcv_wscale */
1916 /* tcpi_flags */
1917 if (acttp) {
1918 ti->tcpi_rto = acttp->t_timer[TCPT_REXMT] ? acttp->t_rxtcur : 0;
1919 }
1920
1921 /* tcpi_snd_mss */
1922 /* tcpi_rcv_mss */
1923 if (acttp) {
1924 ti->tcpi_rttcur = acttp->t_rttcur;
1925 ti->tcpi_srtt = acttp->t_srtt >> TCP_RTT_SHIFT;
1926 ti->tcpi_rttvar = acttp->t_rttvar >> TCP_RTTVAR_SHIFT;
1927 ti->tcpi_rttbest = acttp->t_rttbest >> TCP_RTT_SHIFT;
1928 }
1929 /* tcpi_snd_ssthresh */
1930 /* tcpi_snd_cwnd */
1931 /* tcpi_rcv_space */
1932 ti->tcpi_snd_wnd = mp_tp->mpt_sndwnd;
f427ee49
A
1933 ti->tcpi_snd_nxt = (uint32_t)mp_tp->mpt_sndnxt;
1934 ti->tcpi_rcv_nxt = (uint32_t)mp_tp->mpt_rcvnxt;
cb323159
A
1935 if (acttp) {
1936 ti->tcpi_last_outif = (acttp->t_inpcb->inp_last_outifp == NULL) ? 0 :
1937 acttp->t_inpcb->inp_last_outifp->if_index;
1938 }
1939
1940 mptcp_fill_info_bytestats(ti, mpte);
1941 /* tcpi_txpackets */
1942
1943 /* tcpi_txretransmitbytes */
1944 /* tcpi_txunacked */
1945 /* tcpi_rxpackets */
1946
1947 /* tcpi_rxduplicatebytes */
1948 /* tcpi_rxoutoforderbytes */
1949 /* tcpi_snd_bw */
1950 /* tcpi_synrexmits */
1951 /* tcpi_unused1 */
1952 /* tcpi_unused2 */
1953 /* tcpi_cell_rxpackets */
1954
1955 /* tcpi_cell_txpackets */
1956
1957 /* tcpi_wifi_rxpackets */
1958
1959 /* tcpi_wifi_txpackets */
1960
1961 /* tcpi_wired_rxpackets */
1962 /* tcpi_wired_txpackets */
1963 /* tcpi_connstatus */
1964 /* TFO-stuff */
1965 /* ECN stuff */
1966 /* tcpi_ecn_recv_ce */
1967 /* tcpi_ecn_recv_cwr */
1968 if (acttp) {
1969 ti->tcpi_rcvoopack = acttp->t_rcvoopack;
1970 }
1971 /* tcpi_pawsdrop */
1972 /* tcpi_sack_recovery_episode */
1973 /* tcpi_reordered_pkts */
1974 /* tcpi_dsack_sent */
1975 /* tcpi_dsack_recvd */
1976 /* tcpi_flowhash */
1977 if (acttp) {
1978 ti->tcpi_txretransmitpackets = acttp->t_stat.rxmitpkts;
1979 }
1980}
1981
39236c6e
A
1982/*
1983 * Handle SOPT_GET for socket options issued on MP socket.
1984 */
1985static int
1986mptcp_getopt(struct mptses *mpte, struct sockopt *sopt)
1987{
527f9951 1988 int error = 0, optval = 0;
39236c6e 1989
39236c6e
A
1990 /*
1991 * We only handle SOPT_GET for TCP level socket options; we should
1992 * not get here for socket level options since they are already
1993 * handled at the socket layer.
1994 */
1995 if (sopt->sopt_level != IPPROTO_TCP) {
1996 error = ENOPROTOOPT;
1997 goto out;
1998 }
1999
2000 switch (sopt->sopt_name) {
cb323159
A
2001 case PERSIST_TIMEOUT:
2002 /* Only case for which we have a non-zero default */
2003 optval = tcp_max_persist_timeout;
f427ee49 2004 OS_FALLTHROUGH;
39236c6e
A
2005 case TCP_NODELAY:
2006 case TCP_RXT_FINDROP:
2007 case TCP_KEEPALIVE:
2008 case TCP_KEEPINTVL:
2009 case TCP_KEEPCNT:
2010 case TCP_CONNECTIONTIMEOUT:
2011 case TCP_RXT_CONNDROPTIME:
5ba3f43e
A
2012 case TCP_ADAPTIVE_READ_TIMEOUT:
2013 case TCP_ADAPTIVE_WRITE_TIMEOUT:
cb323159
A
2014 {
2015 struct mptopt *mpo = mptcp_sopt_find(mpte, sopt);
2016
2017 if (mpo != NULL) {
2018 optval = mpo->mpo_intval;
2019 }
39236c6e
A
2020 break;
2021 }
2022
cb323159 2023 /* The next ones are stored at the MPTCP-level */
fe8ab488 2024 case TCP_NOTSENT_LOWAT:
0a7de745 2025 if (mptetoso(mpte)->so_flags & SOF_NOTSENT_LOWAT) {
fe8ab488 2026 optval = mptcp_get_notsent_lowat(mpte);
0a7de745 2027 } else {
fe8ab488 2028 optval = 0;
0a7de745 2029 }
cb323159
A
2030 break;
2031 case TCP_INFO:
2032 {
2033 struct tcp_info ti;
fe8ab488 2034
cb323159
A
2035 mptcp_fill_info(mpte, &ti);
2036 error = sooptcopyout(sopt, &ti, sizeof(struct tcp_info));
39236c6e 2037
cb323159 2038 goto out;
39236c6e 2039 }
5ba3f43e 2040 case MPTCP_SERVICE_TYPE:
cb323159 2041 optval = mpte->mpte_svctype;
39236c6e 2042 break;
cb323159
A
2043 case MPTCP_ALTERNATE_PORT:
2044 optval = mpte->mpte_alternate_port;
39236c6e 2045 break;
cb323159
A
2046 case MPTCP_FORCE_ENABLE:
2047 optval = !!(mpte->mpte_flags & MPTE_FORCE_ENABLE);
39236c6e 2048 break;
cb323159
A
2049 case MPTCP_EXPECTED_PROGRESS_TARGET:
2050 error = sooptcopyout(sopt, &mpte->mpte_time_target, sizeof(mpte->mpte_time_target));
39236c6e 2051
cb323159 2052 goto out;
39236c6e 2053 default:
cb323159 2054 /* not eligible */
39236c6e
A
2055 error = ENOPROTOOPT;
2056 break;
2057 }
cb323159
A
2058
2059 if (error == 0) {
2060 error = sooptcopyout(sopt, &optval, sizeof(int));
2061 }
2062
2063out:
0a7de745 2064 return error;
39236c6e
A
2065}
2066
2067/*
2068 * MPTCP SOPT_{SET,GET} socket option handler, for options issued on the MP
2069 * socket, at SOL_SOCKET and IPPROTO_TCP levels. The former is restricted
2070 * to those that are allowed by mptcp_usr_socheckopt().
2071 */
2072int
2073mptcp_ctloutput(struct socket *mp_so, struct sockopt *sopt)
2074{
5ba3f43e 2075 struct mppcb *mpp = mpsotomppcb(mp_so);
39236c6e
A
2076 struct mptses *mpte;
2077 int error = 0;
2078
2079 if (mpp == NULL || mpp->mpp_state == MPPCB_STATE_DEAD) {
2080 error = EINVAL;
2081 goto out;
2082 }
2083 mpte = mptompte(mpp);
cb323159 2084 socket_lock_assert_owned(mp_so);
39236c6e
A
2085
2086 /* we only handle socket and TCP-level socket options for MPTCP */
2087 if (sopt->sopt_level != SOL_SOCKET && sopt->sopt_level != IPPROTO_TCP) {
39236c6e
A
2088 error = EINVAL;
2089 goto out;
2090 }
2091
2092 switch (sopt->sopt_dir) {
2093 case SOPT_SET:
2094 error = mptcp_setopt(mpte, sopt);
2095 break;
2096
2097 case SOPT_GET:
2098 error = mptcp_getopt(mpte, sopt);
2099 break;
2100 }
2101out:
0a7de745 2102 return error;
39236c6e
A
2103}
2104
39236c6e 2105const char *
5ba3f43e 2106mptcp_sopt2str(int level, int optname)
39236c6e 2107{
39236c6e
A
2108 switch (level) {
2109 case SOL_SOCKET:
39236c6e
A
2110 switch (optname) {
2111 case SO_LINGER:
0a7de745 2112 return "SO_LINGER";
39236c6e 2113 case SO_LINGER_SEC:
0a7de745 2114 return "SO_LINGER_SEC";
39236c6e 2115 case SO_DEBUG:
0a7de745 2116 return "SO_DEBUG";
39236c6e 2117 case SO_KEEPALIVE:
0a7de745 2118 return "SO_KEEPALIVE";
39236c6e 2119 case SO_USELOOPBACK:
0a7de745 2120 return "SO_USELOOPBACK";
39236c6e 2121 case SO_TYPE:
0a7de745 2122 return "SO_TYPE";
39236c6e 2123 case SO_NREAD:
0a7de745 2124 return "SO_NREAD";
39236c6e 2125 case SO_NWRITE:
0a7de745 2126 return "SO_NWRITE";
39236c6e 2127 case SO_ERROR:
0a7de745 2128 return "SO_ERROR";
39236c6e 2129 case SO_SNDBUF:
0a7de745 2130 return "SO_SNDBUF";
39236c6e 2131 case SO_RCVBUF:
0a7de745 2132 return "SO_RCVBUF";
39236c6e 2133 case SO_SNDLOWAT:
0a7de745 2134 return "SO_SNDLOWAT";
39236c6e 2135 case SO_RCVLOWAT:
0a7de745 2136 return "SO_RCVLOWAT";
39236c6e 2137 case SO_SNDTIMEO:
0a7de745 2138 return "SO_SNDTIMEO";
39236c6e 2139 case SO_RCVTIMEO:
0a7de745 2140 return "SO_RCVTIMEO";
39236c6e 2141 case SO_NKE:
0a7de745 2142 return "SO_NKE";
39236c6e 2143 case SO_NOSIGPIPE:
0a7de745 2144 return "SO_NOSIGPIPE";
39236c6e 2145 case SO_NOADDRERR:
0a7de745 2146 return "SO_NOADDRERR";
39236c6e 2147 case SO_RESTRICTIONS:
0a7de745 2148 return "SO_RESTRICTIONS";
39236c6e 2149 case SO_LABEL:
0a7de745 2150 return "SO_LABEL";
39236c6e 2151 case SO_PEERLABEL:
0a7de745 2152 return "SO_PEERLABEL";
39236c6e 2153 case SO_RANDOMPORT:
0a7de745 2154 return "SO_RANDOMPORT";
39236c6e 2155 case SO_TRAFFIC_CLASS:
0a7de745 2156 return "SO_TRAFFIC_CLASS";
39236c6e 2157 case SO_RECV_TRAFFIC_CLASS:
0a7de745 2158 return "SO_RECV_TRAFFIC_CLASS";
39236c6e 2159 case SO_TRAFFIC_CLASS_DBG:
0a7de745 2160 return "SO_TRAFFIC_CLASS_DBG";
39236c6e 2161 case SO_PRIVILEGED_TRAFFIC_CLASS:
0a7de745 2162 return "SO_PRIVILEGED_TRAFFIC_CLASS";
94ff46dc
A
2163 case SO_DEFUNCTIT:
2164 return "SO_DEFUNCTIT";
39236c6e 2165 case SO_DEFUNCTOK:
0a7de745 2166 return "SO_DEFUNCTOK";
39236c6e 2167 case SO_ISDEFUNCT:
0a7de745 2168 return "SO_ISDEFUNCT";
39236c6e 2169 case SO_OPPORTUNISTIC:
0a7de745 2170 return "SO_OPPORTUNISTIC";
39236c6e 2171 case SO_FLUSH:
0a7de745 2172 return "SO_FLUSH";
39236c6e 2173 case SO_RECV_ANYIF:
0a7de745 2174 return "SO_RECV_ANYIF";
fe8ab488 2175 case SO_NOWAKEFROMSLEEP:
0a7de745 2176 return "SO_NOWAKEFROMSLEEP";
39037602 2177 case SO_NOAPNFALLBK:
0a7de745 2178 return "SO_NOAPNFALLBK";
5ba3f43e 2179 case SO_MARK_CELLFALLBACK:
0a7de745 2180 return "SO_CELLFALLBACK";
5ba3f43e 2181 case SO_DELEGATED:
0a7de745 2182 return "SO_DELEGATED";
5ba3f43e 2183 case SO_DELEGATED_UUID:
0a7de745 2184 return "SO_DELEGATED_UUID";
5ba3f43e
A
2185#if NECP
2186 case SO_NECP_ATTRIBUTES:
0a7de745 2187 return "SO_NECP_ATTRIBUTES";
5ba3f43e 2188 case SO_NECP_CLIENTUUID:
0a7de745 2189 return "SO_NECP_CLIENTUUID";
5ba3f43e 2190#endif /* NECP */
39236c6e 2191 }
5ba3f43e 2192
39236c6e
A
2193 break;
2194 case IPPROTO_TCP:
39236c6e 2195 switch (optname) {
5ba3f43e 2196 case TCP_NODELAY:
0a7de745 2197 return "TCP_NODELAY";
39236c6e 2198 case TCP_KEEPALIVE:
0a7de745 2199 return "TCP_KEEPALIVE";
39236c6e 2200 case TCP_KEEPINTVL:
0a7de745 2201 return "TCP_KEEPINTVL";
39236c6e 2202 case TCP_KEEPCNT:
0a7de745 2203 return "TCP_KEEPCNT";
39236c6e 2204 case TCP_CONNECTIONTIMEOUT:
0a7de745 2205 return "TCP_CONNECTIONTIMEOUT";
39236c6e 2206 case TCP_RXT_CONNDROPTIME:
0a7de745 2207 return "TCP_RXT_CONNDROPTIME";
39236c6e 2208 case PERSIST_TIMEOUT:
0a7de745 2209 return "PERSIST_TIMEOUT";
5ba3f43e 2210 case TCP_NOTSENT_LOWAT:
0a7de745 2211 return "NOTSENT_LOWAT";
5ba3f43e 2212 case TCP_ADAPTIVE_READ_TIMEOUT:
0a7de745 2213 return "ADAPTIVE_READ_TIMEOUT";
5ba3f43e 2214 case TCP_ADAPTIVE_WRITE_TIMEOUT:
0a7de745 2215 return "ADAPTIVE_WRITE_TIMEOUT";
5ba3f43e 2216 case MPTCP_SERVICE_TYPE:
0a7de745 2217 return "MPTCP_SERVICE_TYPE";
a39ff7e2 2218 case MPTCP_ALTERNATE_PORT:
0a7de745 2219 return "MPTCP_ALTERNATE_PORT";
cb323159
A
2220 case MPTCP_FORCE_ENABLE:
2221 return "MPTCP_FORCE_ENABLE";
2222 case MPTCP_EXPECTED_PROGRESS_TARGET:
2223 return "MPTCP_EXPECTED_PROGRESS_TARGET";
39236c6e 2224 }
5ba3f43e 2225
39236c6e
A
2226 break;
2227 }
2228
0a7de745 2229 return "unknown";
39236c6e 2230}
490019cf
A
2231
2232static int
2233mptcp_usr_preconnect(struct socket *mp_so)
2234{
2235 struct mptsub *mpts = NULL;
5ba3f43e 2236 struct mppcb *mpp = mpsotomppcb(mp_so);
490019cf
A
2237 struct mptses *mpte;
2238 struct socket *so;
2239 struct tcpcb *tp = NULL;
5ba3f43e 2240 int error;
490019cf
A
2241
2242 mpte = mptompte(mpp);
490019cf 2243
cb323159 2244 mpts = mptcp_get_subflow(mpte, NULL);
490019cf 2245 if (mpts == NULL) {
cb323159
A
2246 os_log_error(mptcp_log_handle, "%s - %lx: invalid preconnect ",
2247 __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte));
0a7de745 2248 return EINVAL;
490019cf 2249 }
490019cf
A
2250 mpts->mpts_flags &= ~MPTSF_TFO_REQD;
2251 so = mpts->mpts_socket;
490019cf
A
2252 tp = intotcpcb(sotoinpcb(so));
2253 tp->t_mpflags &= ~TMPF_TFO_REQUEST;
5ba3f43e
A
2254 error = tcp_output(sototcpcb(so));
2255
2256 soclearfastopen(mp_so);
2257
0a7de745 2258 return error;
490019cf 2259}