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