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