]> git.saurik.com Git - apple/xnu.git/blame - bsd/netinet/mptcp_usrreq.c
xnu-4570.31.3.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 *);
39236c6e
A
81static int mptcp_setopt(struct mptses *, struct sockopt *);
82static int mptcp_getopt(struct mptses *, struct sockopt *);
83static int mptcp_default_tcp_optval(struct mptses *, struct sockopt *, int *);
490019cf 84static int mptcp_usr_preconnect(struct socket *so);
39236c6e
A
85
86struct pr_usrreqs mptcp_usrreqs = {
87 .pru_attach = mptcp_usr_attach,
88 .pru_connectx = mptcp_usr_connectx,
89 .pru_control = mptcp_usr_control,
90 .pru_detach = mptcp_usr_detach,
fe8ab488 91 .pru_disconnect = mptcp_usr_disconnect,
39236c6e 92 .pru_disconnectx = mptcp_usr_disconnectx,
5ba3f43e 93 .pru_peeraddr = mp_getpeeraddr,
39236c6e
A
94 .pru_rcvd = mptcp_usr_rcvd,
95 .pru_send = mptcp_usr_send,
96 .pru_shutdown = mptcp_usr_shutdown,
5ba3f43e 97 .pru_sockaddr = mp_getsockaddr,
39236c6e
A
98 .pru_sosend = mptcp_usr_sosend,
99 .pru_soreceive = soreceive,
100 .pru_socheckopt = mptcp_usr_socheckopt,
490019cf 101 .pru_preconnect = mptcp_usr_preconnect,
39236c6e
A
102};
103
5ba3f43e
A
104
105#if (DEVELOPMENT || DEBUG)
106static int mptcp_disable_entitlements = 0;
107SYSCTL_INT(_net_inet_mptcp, OID_AUTO, disable_entitlements, CTLFLAG_RW | CTLFLAG_LOCKED,
108 &mptcp_disable_entitlements, 0, "Disable Multipath TCP Entitlement Checking");
109#endif
110
111int mptcp_developer_mode = 0;
112SYSCTL_INT(_net_inet_mptcp, OID_AUTO, allow_aggregate, CTLFLAG_RW | CTLFLAG_LOCKED,
113 &mptcp_developer_mode, 0, "Allow the Multipath aggregation mode");
114
115
39236c6e
A
116/*
117 * Attaches an MPTCP control block to a socket.
118 */
119static int
120mptcp_usr_attach(struct socket *mp_so, int proto, struct proc *p)
121{
122#pragma unused(proto)
123 int error;
124
5ba3f43e 125 VERIFY(mpsotomppcb(mp_so) == NULL);
39236c6e
A
126
127 error = mptcp_attach(mp_so, p);
128 if (error != 0)
129 goto out;
130 /*
131 * XXX: adi@apple.com
132 *
133 * Might want to use a different SO_LINGER timeout than TCP's?
134 */
135 if ((mp_so->so_options & SO_LINGER) && mp_so->so_linger == 0)
136 mp_so->so_linger = TCP_LINGERTIME * hz;
137out:
138 return (error);
139}
140
141/*
142 * Detaches an MPTCP control block from a socket.
143 */
144static int
145mptcp_usr_detach(struct socket *mp_so)
146{
5ba3f43e
A
147 struct mptses *mpte = mpsotompte(mp_so);
148 struct mppcb *mpp = mpsotomppcb(mp_so);
39236c6e 149
5ba3f43e
A
150 if (mpp == NULL || mpp->mpp_state == MPPCB_STATE_DEAD) {
151 mptcplog((LOG_ERR, "%s state: %d\n", __func__,
152 mpp ? mpp->mpp_state : -1),
153 MPTCP_SOCKET_DBG, MPTCP_LOGLVL_ERR);
154 return (EINVAL);
155 }
39236c6e 156
5ba3f43e
A
157 /*
158 * We are done with this MPTCP socket (it has been closed);
159 * trigger all subflows to be disconnected, if not already,
160 * by initiating the PCB detach sequence (SOF_PCBCLEARING
161 * will be set.)
162 */
163 mp_pcbdetach(mp_so);
164
165 mptcp_disconnect(mpte);
166
167 return (0);
39236c6e
A
168}
169
170/*
171 * Attach MPTCP protocol to socket, allocating MP control block,
172 * MPTCP session, control block, buffer space, etc.
173 */
174static int
175mptcp_attach(struct socket *mp_so, struct proc *p)
176{
177#pragma unused(p)
3e170ce0
A
178 struct mptses *mpte = NULL;
179 struct mptcb *mp_tp = NULL;
180 struct mppcb *mpp = NULL;
39236c6e
A
181 int error = 0;
182
183 if (mp_so->so_snd.sb_hiwat == 0 || mp_so->so_rcv.sb_hiwat == 0) {
5ba3f43e 184 error = soreserve(mp_so, tcp_sendspace, tcp_recvspace);
39236c6e
A
185 if (error != 0)
186 goto out;
187 }
188
490019cf 189 if (mp_so->so_snd.sb_preconn_hiwat == 0) {
39037602 190 soreserve_preconnect(mp_so, 2048);
490019cf
A
191 }
192
5ba3f43e
A
193 if ((mp_so->so_rcv.sb_flags & SB_USRSIZE) == 0)
194 mp_so->so_rcv.sb_flags |= SB_AUTOSIZE;
195 if ((mp_so->so_snd.sb_flags & SB_USRSIZE) == 0)
196 mp_so->so_snd.sb_flags |= SB_AUTOSIZE;
197
39236c6e
A
198 /*
199 * MPTCP socket buffers cannot be compressed, due to the
200 * fact that each mbuf chained via m_next is a M_PKTHDR
201 * which carries some MPTCP metadata.
202 */
203 mp_so->so_snd.sb_flags |= SB_NOCOMPRESS;
204 mp_so->so_rcv.sb_flags |= SB_NOCOMPRESS;
205
3e170ce0 206 if ((error = mp_pcballoc(mp_so, &mtcbinfo)) != 0) {
39236c6e 207 goto out;
3e170ce0 208 }
39236c6e 209
5ba3f43e 210 mpp = mpsotomppcb(mp_so);
39236c6e 211 VERIFY(mpp != NULL);
3e170ce0
A
212 mpte = (struct mptses *)mpp->mpp_pcbe;
213 VERIFY(mpte != NULL);
39236c6e
A
214 mp_tp = mpte->mpte_mptcb;
215 VERIFY(mp_tp != NULL);
39236c6e
A
216out:
217 return (error);
218}
219
39236c6e 220static int
5ba3f43e 221mptcp_entitlement_check(struct socket *mp_so)
39236c6e 222{
5ba3f43e 223 struct mptses *mpte = mpsotompte(mp_so);
39236c6e 224
5ba3f43e
A
225 if (soopt_cred_check(mp_so, PRIV_NET_RESTRICTED_MULTIPATH_EXTENDED, TRUE) == 0) {
226 /*
227 * This means the app has the extended entitlement. Thus,
228 * it's a first party app and can run without restrictions.
229 */
230 mpte->mpte_flags |= MPTE_FIRSTPARTY;
231 goto grant;
232 }
39236c6e 233
5ba3f43e
A
234#if (DEVELOPMENT || DEBUG)
235 if (mptcp_disable_entitlements)
236 goto grant;
237#endif
39236c6e 238
5ba3f43e
A
239 if (soopt_cred_check(mp_so, PRIV_NET_PRIVILEGED_MULTIPATH, TRUE)) {
240 mptcplog((LOG_NOTICE, "%s Multipath Capability needed\n", __func__),
241 MPTCP_SOCKET_DBG, MPTCP_LOGLVL_LOG);
242 return (-1);
243 }
39236c6e 244
5ba3f43e
A
245 if (mpte->mpte_svctype > MPTCP_SVCTYPE_INTERACTIVE &&
246 mptcp_developer_mode == 0) {
247 mptcplog((LOG_NOTICE, "%s need to set allow_aggregate sysctl\n",
248 __func__), MPTCP_SOCKET_DBG, MPTCP_LOGLVL_LOG);
249 return (-1);
250 }
39236c6e 251
5ba3f43e
A
252grant:
253 mptcplog((LOG_NOTICE, "%s entitlement granted for %u\n", __func__, mpte->mpte_svctype),
254 MPTCP_SOCKET_DBG, MPTCP_LOGLVL_LOG);
39236c6e
A
255
256 return (0);
257}
258
259/*
260 * Common subroutine to open a MPTCP connection to one of the remote hosts
261 * specified by dst_sl. This includes allocating and establishing a
262 * subflow TCP connection, either initially to establish MPTCP connection,
263 * or to join an existing one. Returns a connection handle upon success.
264 */
265static int
813fb2f6 266mptcp_connectx(struct mptses *mpte, struct sockaddr *src,
5ba3f43e 267 struct sockaddr *dst, uint32_t ifscope, sae_connid_t *pcid)
39236c6e 268{
5ba3f43e 269 struct socket *mp_so = mptetoso(mpte);
39236c6e
A
270 int error = 0;
271
813fb2f6 272 VERIFY(dst != NULL);
39236c6e
A
273 VERIFY(pcid != NULL);
274
5ba3f43e 275 mptcplog((LOG_DEBUG, "%s: mp_so 0x%llx\n", __func__,
3e170ce0
A
276 (u_int64_t)VM_KERNEL_ADDRPERM(mp_so)),
277 MPTCP_SOCKET_DBG, MPTCP_LOGLVL_LOG);
5ba3f43e 278 DTRACE_MPTCP2(connectx, struct mptses *, mpte, struct socket *, mp_so);
fe8ab488 279
5ba3f43e 280 error = mptcp_subflow_add(mpte, src, dst, ifscope, pcid);
39236c6e
A
281
282 return (error);
283}
284
285/*
286 * User-protocol pru_connectx callback.
287 */
288static int
813fb2f6
A
289mptcp_usr_connectx(struct socket *mp_so, struct sockaddr *src,
290 struct sockaddr *dst, struct proc *p, uint32_t ifscope,
3e170ce0 291 sae_associd_t aid, sae_connid_t *pcid, uint32_t flags, void *arg,
490019cf 292 uint32_t arglen, struct uio *auio, user_ssize_t *bytes_written)
39236c6e 293{
5ba3f43e
A
294#pragma unused(p, aid, flags, arg, arglen)
295 struct mppcb *mpp = mpsotomppcb(mp_so);
3e170ce0
A
296 struct mptses *mpte = NULL;
297 struct mptcb *mp_tp = NULL;
490019cf 298 user_ssize_t datalen;
39236c6e
A
299 int error = 0;
300
301 if (mpp == NULL || mpp->mpp_state == MPPCB_STATE_DEAD) {
5ba3f43e
A
302 mptcplog((LOG_ERR, "%s state %d\n", __func__,
303 mpp ? mpp->mpp_state : -1),
304 MPTCP_SOCKET_DBG, MPTCP_LOGLVL_ERR);
39236c6e
A
305 error = EINVAL;
306 goto out;
307 }
308 mpte = mptompte(mpp);
309 VERIFY(mpte != NULL);
5ba3f43e 310 mpte_lock_assert_held(mpte);
39236c6e 311
3e170ce0
A
312 mp_tp = mpte->mpte_mptcb;
313 VERIFY(mp_tp != NULL);
314
315 if (mp_tp->mpt_flags & MPTCPF_FALLBACK_TO_TCP) {
5ba3f43e
A
316 mptcplog((LOG_ERR, "%s fell back to TCP\n", __func__),
317 MPTCP_SOCKET_DBG, MPTCP_LOGLVL_ERR);
3e170ce0
A
318 error = EINVAL;
319 goto out;
320 }
321
5ba3f43e
A
322 if (dst->sa_family == AF_INET &&
323 dst->sa_len != sizeof(mpte->__mpte_dst_v4)) {
324 mptcplog((LOG_ERR, "%s IPv4 dst len %u\n", __func__,
325 dst->sa_len),
326 MPTCP_SOCKET_DBG, MPTCP_LOGLVL_ERR);
327 error = EINVAL;
328 goto out;
329 }
330
331 if (dst->sa_family == AF_INET6 &&
332 dst->sa_len != sizeof(mpte->__mpte_dst_v6)) {
333 mptcplog((LOG_ERR, "%s IPv6 dst len %u\n", __func__,
334 dst->sa_len),
335 MPTCP_SOCKET_DBG, MPTCP_LOGLVL_ERR);
336 error = EINVAL;
337 goto out;
338 }
339
340 if (!(mpte->mpte_flags & MPTE_SVCTYPE_CHECKED)) {
341 if (mptcp_entitlement_check(mp_so) < 0) {
342 error = EPERM;
343 goto out;
344 }
345
346 mpte->mpte_flags |= MPTE_SVCTYPE_CHECKED;
347 }
348
349 if ((mp_so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0) {
350 memcpy(&mpte->mpte_dst, dst, dst->sa_len);
351 }
352
353 if (src) {
354 if (src->sa_family == AF_INET &&
355 src->sa_len != sizeof(mpte->__mpte_src_v4)) {
356 mptcplog((LOG_ERR, "%s IPv4 src len %u\n", __func__,
357 src->sa_len),
358 MPTCP_SOCKET_DBG, MPTCP_LOGLVL_ERR);
359 error = EINVAL;
360 goto out;
361 }
362
363 if (src->sa_family == AF_INET6 &&
364 src->sa_len != sizeof(mpte->__mpte_src_v6)) {
365 mptcplog((LOG_ERR, "%s IPv6 src len %u\n", __func__,
366 src->sa_len),
367 MPTCP_SOCKET_DBG, MPTCP_LOGLVL_ERR);
368 error = EINVAL;
369 goto out;
370 }
371
372 if ((mp_so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0) {
373 memcpy(&mpte->mpte_src, src, src->sa_len);
374 }
375 }
376
377 error = mptcp_connectx(mpte, src, dst, ifscope, pcid);
490019cf
A
378
379 /* If there is data, copy it */
380 if (auio != NULL) {
381 datalen = uio_resid(auio);
382 socket_unlock(mp_so, 0);
383 error = mp_so->so_proto->pr_usrreqs->pru_sosend(mp_so, NULL,
384 (uio_t) auio, NULL, NULL, 0);
5ba3f43e 385
490019cf
A
386 if (error == 0 || error == EWOULDBLOCK)
387 *bytes_written = datalen - uio_resid(auio);
388
389 if (error == EWOULDBLOCK)
390 error = EINPROGRESS;
391
392 socket_lock(mp_so, 0);
490019cf
A
393 }
394
39236c6e
A
395out:
396 return (error);
397}
398
399/*
400 * Handle SIOCGASSOCIDS ioctl for PF_MULTIPATH domain.
401 */
402static int
403mptcp_getassocids(struct mptses *mpte, uint32_t *cnt, user_addr_t aidp)
404{
5ba3f43e 405 mpte_lock_assert_held(mpte); /* same as MP socket lock */
39236c6e
A
406
407 /* MPTCP has at most 1 association */
3e170ce0 408 *cnt = (mpte->mpte_associd != SAE_ASSOCID_ANY) ? 1 : 0;
39236c6e
A
409
410 /* just asking how many there are? */
411 if (aidp == USER_ADDR_NULL)
412 return (0);
413
414 return (copyout(&mpte->mpte_associd, aidp,
415 sizeof (mpte->mpte_associd)));
416}
417
418/*
419 * Handle SIOCGCONNIDS ioctl for PF_MULTIPATH domain.
420 */
421static int
3e170ce0 422mptcp_getconnids(struct mptses *mpte, sae_associd_t aid, uint32_t *cnt,
39236c6e
A
423 user_addr_t cidp)
424{
425 struct mptsub *mpts;
426 int error = 0;
427
5ba3f43e 428 mpte_lock_assert_held(mpte); /* same as MP socket lock */
39236c6e 429
3e170ce0 430 if (aid != SAE_ASSOCID_ANY && aid != SAE_ASSOCID_ALL &&
39236c6e
A
431 aid != mpte->mpte_associd)
432 return (EINVAL);
433
434 *cnt = mpte->mpte_numflows;
435
436 /* just asking how many there are? */
437 if (cidp == USER_ADDR_NULL)
438 return (0);
439
440 TAILQ_FOREACH(mpts, &mpte->mpte_subflows, mpts_entry) {
441 if ((error = copyout(&mpts->mpts_connid, cidp,
442 sizeof (mpts->mpts_connid))) != 0)
443 break;
444
445 cidp += sizeof (mpts->mpts_connid);
446 }
447
448 return (error);
449}
450
451/*
452 * Handle SIOCGCONNINFO ioctl for PF_MULTIPATH domain.
453 */
454static int
3e170ce0 455mptcp_getconninfo(struct mptses *mpte, sae_connid_t *cid, uint32_t *flags,
39236c6e
A
456 uint32_t *ifindex, int32_t *soerror, user_addr_t src, socklen_t *src_len,
457 user_addr_t dst, socklen_t *dst_len, uint32_t *aux_type,
458 user_addr_t aux_data, uint32_t *aux_len)
459{
5ba3f43e
A
460 struct socket *so;
461 struct inpcb *inp;
39236c6e
A
462 struct mptsub *mpts;
463 int error = 0;
464
39236c6e 465 *flags = 0;
5ba3f43e
A
466 *aux_type = 0;
467 *ifindex = 0;
468 *soerror = 0;
469
470 if (*cid == SAE_CONNID_ALL) {
471 struct socket *mp_so = mptetoso(mpte);
472 struct mptcb *mp_tp = mpte->mpte_mptcb;
473 struct conninfo_multipathtcp mptcp_ci;
474
475 if (*aux_len != 0 && *aux_len != sizeof(mptcp_ci))
476 return (EINVAL);
477
478 if (mp_so->so_state & SS_ISCONNECTING)
479 *flags |= CIF_CONNECTING;
480 if (mp_so->so_state & SS_ISCONNECTED)
481 *flags |= CIF_CONNECTED;
482 if (mp_so->so_state & SS_ISDISCONNECTING)
483 *flags |= CIF_DISCONNECTING;
484 if (mp_so->so_state & SS_ISDISCONNECTED)
485 *flags |= CIF_DISCONNECTED;
486 if (!(mp_tp->mpt_flags & MPTCPF_FALLBACK_TO_TCP))
487 *flags |= CIF_MP_CAPABLE;
488 if (mp_tp->mpt_flags & MPTCPF_FALLBACK_TO_TCP)
489 *flags |= CIF_MP_DEGRADED;
490
491 *src_len = 0;
492 *dst_len = 0;
493
494 *aux_type = CIAUX_MPTCP;
495 *aux_len = sizeof(mptcp_ci);
39236c6e 496
5ba3f43e
A
497 if (aux_data != USER_ADDR_NULL) {
498 unsigned long i = 0;
499 int initial_info_set = 0;
39236c6e 500
5ba3f43e
A
501 bzero(&mptcp_ci, sizeof (mptcp_ci));
502 mptcp_ci.mptcpci_subflow_count = mpte->mpte_numflows;
503 mptcp_ci.mptcpci_switch_count = mpte->mpte_subflow_switches;
39236c6e 504
5ba3f43e
A
505 VERIFY(sizeof(mptcp_ci.mptcpci_itfstats) == sizeof(mpte->mpte_itfstats));
506 memcpy(mptcp_ci.mptcpci_itfstats, mpte->mpte_itfstats, sizeof(mptcp_ci.mptcpci_itfstats));
813fb2f6 507
5ba3f43e
A
508 TAILQ_FOREACH(mpts, &mpte->mpte_subflows, mpts_entry) {
509 if (i >= sizeof(mptcp_ci.mptcpci_subflow_connids) / sizeof(sae_connid_t))
510 break;
511 mptcp_ci.mptcpci_subflow_connids[i] = mpts->mpts_connid;
813fb2f6 512
5ba3f43e
A
513 if (mpts->mpts_flags & MPTSF_INITIAL_SUB) {
514 inp = sotoinpcb(mpts->mpts_socket);
3e170ce0 515
5ba3f43e
A
516 mptcp_ci.mptcpci_init_rxbytes = inp->inp_stat->rxbytes;
517 mptcp_ci.mptcpci_init_txbytes = inp->inp_stat->txbytes;
518 initial_info_set = 1;
519 }
39236c6e 520
5ba3f43e 521 mptcpstats_update(mptcp_ci.mptcpci_itfstats, mpts);
39236c6e 522
5ba3f43e
A
523 i++;
524 }
39236c6e 525
5ba3f43e
A
526 if (initial_info_set == 0) {
527 mptcp_ci.mptcpci_init_rxbytes = mpte->mpte_init_rxbytes;
528 mptcp_ci.mptcpci_init_txbytes = mpte->mpte_init_txbytes;
529 }
39236c6e 530
5ba3f43e
A
531 if (mpte->mpte_flags & MPTE_FIRSTPARTY)
532 mptcp_ci.mptcpci_flags |= MPTCPCI_FIRSTPARTY;
39236c6e 533
5ba3f43e
A
534 error = copyout(&mptcp_ci, aux_data, sizeof(mptcp_ci));
535 if (error != 0) {
536 mptcplog((LOG_ERR, "%s copyout failed: %d\n",
537 __func__, error),
538 MPTCP_SOCKET_DBG, MPTCP_LOGLVL_ERR);
539 return (error);
39236c6e 540 }
39236c6e
A
541 }
542
5ba3f43e 543 return (0);
39236c6e
A
544 }
545
5ba3f43e
A
546 TAILQ_FOREACH(mpts, &mpte->mpte_subflows, mpts_entry) {
547 if (mpts->mpts_connid == *cid || *cid == SAE_CONNID_ANY)
548 break;
39236c6e 549 }
5ba3f43e
A
550 if (mpts == NULL)
551 return ((*cid == SAE_CONNID_ANY) ? ENXIO : EINVAL);
39236c6e 552
5ba3f43e
A
553 so = mpts->mpts_socket;
554 inp = sotoinpcb(so);
39037602 555
5ba3f43e
A
556 if (inp->inp_vflag & INP_IPV4)
557 error = in_getconninfo(so, SAE_CONNID_ANY, flags, ifindex,
558 soerror, src, src_len, dst, dst_len,
559 aux_type, aux_data, aux_len);
39236c6e 560 else
5ba3f43e
A
561 error = in6_getconninfo(so, SAE_CONNID_ANY, flags, ifindex,
562 soerror, src, src_len, dst, dst_len,
563 aux_type, aux_data, aux_len);
39236c6e 564
5ba3f43e
A
565 if (error != 0) {
566 mptcplog((LOG_ERR, "%s error from in_getconninfo %d\n",
567 __func__, error),
568 MPTCP_SOCKET_DBG, MPTCP_LOGLVL_ERR);
569 return (error);
39236c6e
A
570 }
571
5ba3f43e
A
572 if (mpts->mpts_flags & MPTSF_MP_CAPABLE)
573 *flags |= CIF_MP_CAPABLE;
574 if (mpts->mpts_flags & MPTSF_MP_DEGRADED)
575 *flags |= CIF_MP_DEGRADED;
576 if (mpts->mpts_flags & MPTSF_MP_READY)
577 *flags |= CIF_MP_READY;
578 if (mpts->mpts_flags & MPTSF_ACTIVE)
579 *flags |= CIF_MP_ACTIVE;
39236c6e 580
5ba3f43e
A
581 mptcplog((LOG_DEBUG, "%s: cid %d flags %x \n", __func__,
582 mpts->mpts_connid, mpts->mpts_flags),
583 MPTCP_SOCKET_DBG, MPTCP_LOGLVL_VERBOSE);
584
585 return (0);
39236c6e
A
586}
587
588/*
589 * User-protocol pru_control callback.
590 */
591static int
592mptcp_usr_control(struct socket *mp_so, u_long cmd, caddr_t data,
593 struct ifnet *ifp, struct proc *p)
594{
595#pragma unused(ifp, p)
5ba3f43e 596 struct mppcb *mpp = mpsotomppcb(mp_so);
39236c6e
A
597 struct mptses *mpte;
598 int error = 0;
599
600 if (mpp == NULL || mpp->mpp_state == MPPCB_STATE_DEAD) {
601 error = EINVAL;
602 goto out;
603 }
604 mpte = mptompte(mpp);
605 VERIFY(mpte != NULL);
606
5ba3f43e 607 mpte_lock_assert_held(mpte); /* same as MP socket lock */
39236c6e
A
608
609 switch (cmd) {
610 case SIOCGASSOCIDS32: { /* struct so_aidreq32 */
611 struct so_aidreq32 aidr;
612 bcopy(data, &aidr, sizeof (aidr));
613 error = mptcp_getassocids(mpte, &aidr.sar_cnt,
614 aidr.sar_aidp);
615 if (error == 0)
616 bcopy(&aidr, data, sizeof (aidr));
617 break;
618 }
619
620 case SIOCGASSOCIDS64: { /* struct so_aidreq64 */
621 struct so_aidreq64 aidr;
622 bcopy(data, &aidr, sizeof (aidr));
623 error = mptcp_getassocids(mpte, &aidr.sar_cnt,
624 aidr.sar_aidp);
625 if (error == 0)
626 bcopy(&aidr, data, sizeof (aidr));
627 break;
628 }
629
630 case SIOCGCONNIDS32: { /* struct so_cidreq32 */
631 struct so_cidreq32 cidr;
632 bcopy(data, &cidr, sizeof (cidr));
633 error = mptcp_getconnids(mpte, cidr.scr_aid, &cidr.scr_cnt,
634 cidr.scr_cidp);
635 if (error == 0)
636 bcopy(&cidr, data, sizeof (cidr));
637 break;
638 }
639
640 case SIOCGCONNIDS64: { /* struct so_cidreq64 */
641 struct so_cidreq64 cidr;
642 bcopy(data, &cidr, sizeof (cidr));
643 error = mptcp_getconnids(mpte, cidr.scr_aid, &cidr.scr_cnt,
644 cidr.scr_cidp);
645 if (error == 0)
646 bcopy(&cidr, data, sizeof (cidr));
647 break;
648 }
649
650 case SIOCGCONNINFO32: { /* struct so_cinforeq32 */
651 struct so_cinforeq32 cifr;
652 bcopy(data, &cifr, sizeof (cifr));
653 error = mptcp_getconninfo(mpte, &cifr.scir_cid,
654 &cifr.scir_flags, &cifr.scir_ifindex, &cifr.scir_error,
655 cifr.scir_src, &cifr.scir_src_len, cifr.scir_dst,
656 &cifr.scir_dst_len, &cifr.scir_aux_type, cifr.scir_aux_data,
657 &cifr.scir_aux_len);
658 if (error == 0)
659 bcopy(&cifr, data, sizeof (cifr));
660 break;
661 }
662
663 case SIOCGCONNINFO64: { /* struct so_cinforeq64 */
664 struct so_cinforeq64 cifr;
665 bcopy(data, &cifr, sizeof (cifr));
666 error = mptcp_getconninfo(mpte, &cifr.scir_cid,
667 &cifr.scir_flags, &cifr.scir_ifindex, &cifr.scir_error,
668 cifr.scir_src, &cifr.scir_src_len, cifr.scir_dst,
669 &cifr.scir_dst_len, &cifr.scir_aux_type, cifr.scir_aux_data,
670 &cifr.scir_aux_len);
671 if (error == 0)
672 bcopy(&cifr, data, sizeof (cifr));
673 break;
674 }
675
39236c6e
A
676 default:
677 error = EOPNOTSUPP;
678 break;
679 }
680out:
681 return (error);
682}
683
39236c6e 684static int
5ba3f43e 685mptcp_disconnect(struct mptses *mpte)
39236c6e 686{
39236c6e
A
687 struct socket *mp_so;
688 struct mptcb *mp_tp;
689 int error = 0;
690
5ba3f43e 691 mpte_lock_assert_held(mpte); /* same as MP socket lock */
39236c6e 692
5ba3f43e 693 mp_so = mptetoso(mpte);
39236c6e
A
694 mp_tp = mpte->mpte_mptcb;
695
3e170ce0 696 mptcplog((LOG_DEBUG, "MPTCP Socket: "
5ba3f43e
A
697 "%s: mp_so 0x%llx %d\n", __func__,
698 (u_int64_t)VM_KERNEL_ADDRPERM(mp_so), mp_so->so_error),
3e170ce0 699 MPTCP_SOCKET_DBG, MPTCP_LOGLVL_LOG);
39236c6e 700
5ba3f43e
A
701 DTRACE_MPTCP3(disconnectx, struct mptses *, mpte,
702 struct socket *, mp_so, struct mptcb *, mp_tp);
3e170ce0 703
5ba3f43e
A
704 /* if we're not detached, go thru socket state checks */
705 if (!(mp_so->so_flags & SOF_PCBCLEARING)) {
706 if (!(mp_so->so_state & (SS_ISCONNECTED|
707 SS_ISCONNECTING))) {
708 error = ENOTCONN;
39236c6e
A
709 goto out;
710 }
5ba3f43e
A
711 if (mp_so->so_state & SS_ISDISCONNECTING) {
712 error = EALREADY;
713 goto out;
3e170ce0 714 }
39236c6e
A
715 }
716
5ba3f43e
A
717 mptcp_cancel_all_timers(mp_tp);
718 if (mp_tp->mpt_state < MPTCPS_ESTABLISHED) {
719 mptcp_close(mpte, mp_tp);
720 } else if ((mp_so->so_options & SO_LINGER) &&
721 mp_so->so_linger == 0) {
722 mptcp_drop(mpte, mp_tp, 0);
723 } else {
724 soisdisconnecting(mp_so);
725 sbflush(&mp_so->so_rcv);
726 if (mptcp_usrclosed(mpte) != NULL)
727 mptcp_output(mpte);
39236c6e
A
728 }
729
5ba3f43e
A
730 if (error == 0)
731 mptcp_subflow_workloop(mpte);
732
39236c6e
A
733out:
734 return (error);
735}
736
fe8ab488 737/*
5ba3f43e 738 * Wrapper function to support disconnect on socket
fe8ab488
A
739 */
740static int
741mptcp_usr_disconnect(struct socket *mp_so)
742{
5ba3f43e 743 return (mptcp_disconnect(mpsotompte(mp_so)));
fe8ab488
A
744}
745
39236c6e
A
746/*
747 * User-protocol pru_disconnectx callback.
748 */
749static int
3e170ce0 750mptcp_usr_disconnectx(struct socket *mp_so, sae_associd_t aid, sae_connid_t cid)
39236c6e 751{
5ba3f43e
A
752 if (aid != SAE_ASSOCID_ANY && aid != SAE_ASSOCID_ALL)
753 return (EINVAL);
39236c6e 754
5ba3f43e
A
755 if (cid != SAE_CONNID_ANY && cid != SAE_CONNID_ALL)
756 return (EINVAL);
39236c6e 757
5ba3f43e 758 return (mptcp_usr_disconnect(mp_so));
39236c6e
A
759}
760
761/*
762 * User issued close, and wish to trail thru shutdown states.
763 */
764static struct mptses *
765mptcp_usrclosed(struct mptses *mpte)
766{
767 struct socket *mp_so;
768 struct mptcb *mp_tp;
769 struct mptsub *mpts;
770
5ba3f43e
A
771 mpte_lock_assert_held(mpte); /* same as MP socket lock */
772 mp_so = mptetoso(mpte);
39236c6e
A
773 mp_tp = mpte->mpte_mptcb;
774
39236c6e
A
775 mptcp_close_fsm(mp_tp, MPCE_CLOSE);
776
fe8ab488 777 if (mp_tp->mpt_state == MPTCPS_CLOSED) {
39236c6e 778 mpte = mptcp_close(mpte, mp_tp);
39236c6e 779 } else if (mp_tp->mpt_state >= MPTCPS_FIN_WAIT_2) {
39236c6e
A
780 soisdisconnected(mp_so);
781 } else {
39236c6e 782 TAILQ_FOREACH(mpts, &mpte->mpte_subflows, mpts_entry) {
5ba3f43e
A
783 if ((mp_so->so_state & (SS_CANTRCVMORE|SS_CANTSENDMORE)) ==
784 (SS_CANTRCVMORE | SS_CANTSENDMORE))
785 mptcp_subflow_disconnect(mpte, mpts);
786 else
787 mptcp_subflow_shutdown(mpte, mpts);
39236c6e
A
788 }
789 }
39236c6e
A
790
791 return (mpte);
792}
793
39236c6e
A
794/*
795 * After a receive, possible send some update to peer.
796 */
797static int
798mptcp_usr_rcvd(struct socket *mp_so, int flags)
799{
800#pragma unused(flags)
5ba3f43e 801 struct mppcb *mpp = mpsotomppcb(mp_so);
39236c6e
A
802 struct mptses *mpte;
803 int error = 0;
804
805 if (mpp == NULL || mpp->mpp_state == MPPCB_STATE_DEAD) {
806 error = EINVAL;
807 goto out;
808 }
809 mpte = mptompte(mpp);
810 VERIFY(mpte != NULL);
811
812 error = mptcp_output(mpte);
813out:
814 return (error);
815}
816
817/*
818 * Do a send by putting data in the output queue.
819 */
820static int
821mptcp_usr_send(struct socket *mp_so, int prus_flags, struct mbuf *m,
822 struct sockaddr *nam, struct mbuf *control, struct proc *p)
823{
824#pragma unused(nam, p)
5ba3f43e 825 struct mppcb *mpp = mpsotomppcb(mp_so);
39236c6e
A
826 struct mptses *mpte;
827 int error = 0;
828
829 if (prus_flags & (PRUS_OOB|PRUS_EOF)) {
830 error = EOPNOTSUPP;
831 goto out;
832 }
833
834 if (nam != NULL) {
835 error = EOPNOTSUPP;
836 goto out;
837 }
838
839 if (control != NULL && control->m_len != 0) {
840 error = EOPNOTSUPP;
841 goto out;
842 }
843
844 if (mpp == NULL || mpp->mpp_state == MPPCB_STATE_DEAD) {
845 error = ECONNRESET;
846 goto out;
847 }
848 mpte = mptompte(mpp);
849 VERIFY(mpte != NULL);
850
490019cf 851 if (!(mp_so->so_state & SS_ISCONNECTED) &&
5ba3f43e 852 !(mp_so->so_flags1 & SOF1_PRECONNECT_DATA)) {
39236c6e
A
853 error = ENOTCONN;
854 goto out;
855 }
856
857 mptcp_insert_dsn(mpp, m);
858 VERIFY(mp_so->so_snd.sb_flags & SB_NOCOMPRESS);
5ba3f43e 859 sbappendstream(&mp_so->so_snd, m);
39236c6e
A
860 m = NULL;
861
490019cf
A
862 error = mptcp_output(mpte);
863 if (error != 0)
864 goto out;
39037602 865
490019cf
A
866 if (mp_so->so_state & SS_ISCONNECTING) {
867 if (mp_so->so_state & SS_NBIO)
868 error = EWOULDBLOCK;
869 else
870 error = sbwait(&mp_so->so_snd);
39236c6e 871 }
39037602 872
39236c6e
A
873out:
874 if (error) {
875 if (m != NULL)
876 m_freem(m);
877 if (control != NULL)
878 m_freem(control);
879 }
880 return (error);
881}
882
883/*
884 * Mark the MPTCP connection as being incapable of further output.
885 */
886static int
887mptcp_usr_shutdown(struct socket *mp_so)
888{
5ba3f43e 889 struct mppcb *mpp = mpsotomppcb(mp_so);
39236c6e
A
890 struct mptses *mpte;
891 int error = 0;
892
893 if (mpp == NULL || mpp->mpp_state == MPPCB_STATE_DEAD) {
894 error = EINVAL;
895 goto out;
896 }
897 mpte = mptompte(mpp);
898 VERIFY(mpte != NULL);
899
900 socantsendmore(mp_so);
901
902 mpte = mptcp_usrclosed(mpte);
903 if (mpte != NULL)
904 error = mptcp_output(mpte);
905out:
906 return (error);
907}
908
909/*
910 * Copy the contents of uio into a properly sized mbuf chain.
911 */
912static int
913mptcp_uiotombuf(struct uio *uio, int how, int space, uint32_t align,
914 struct mbuf **top)
915{
916 struct mbuf *m, *mb, *nm = NULL, *mtail = NULL;
917 user_ssize_t resid, tot, len, progress; /* must be user_ssize_t */
918 int error;
919
920 VERIFY(top != NULL && *top == NULL);
921
922 /*
923 * space can be zero or an arbitrary large value bound by
924 * the total data supplied by the uio.
925 */
926 resid = uio_resid(uio);
927 if (space > 0)
928 tot = imin(resid, space);
929 else
930 tot = resid;
931
932 /*
933 * The smallest unit is a single mbuf with pkthdr.
934 * We can't align past it.
935 */
936 if (align >= MHLEN)
937 return (EINVAL);
938
939 /*
940 * Give us the full allocation or nothing.
941 * If space is zero return the smallest empty mbuf.
942 */
943 if ((len = tot + align) == 0)
944 len = 1;
945
946 /* Loop and append maximum sized mbufs to the chain tail. */
947 while (len > 0) {
948 uint32_t m_needed = 1;
949
950 if (njcl > 0 && len > MBIGCLBYTES)
951 mb = m_getpackets_internal(&m_needed, 1,
952 how, 1, M16KCLBYTES);
953 else if (len > MCLBYTES)
954 mb = m_getpackets_internal(&m_needed, 1,
955 how, 1, MBIGCLBYTES);
956 else if (len >= (signed)MINCLSIZE)
957 mb = m_getpackets_internal(&m_needed, 1,
958 how, 1, MCLBYTES);
959 else
960 mb = m_gethdr(how, MT_DATA);
961
962 /* Fail the whole operation if one mbuf can't be allocated. */
963 if (mb == NULL) {
964 if (nm != NULL)
965 m_freem(nm);
966 return (ENOBUFS);
967 }
968
969 /* Book keeping. */
970 VERIFY(mb->m_flags & M_PKTHDR);
971 len -= ((mb->m_flags & M_EXT) ? mb->m_ext.ext_size : MHLEN);
972 if (mtail != NULL)
973 mtail->m_next = mb;
974 else
975 nm = mb;
976 mtail = mb;
977 }
978
979 m = nm;
980 m->m_data += align;
981
982 progress = 0;
983 /* Fill all mbufs with uio data and update header information. */
984 for (mb = m; mb != NULL; mb = mb->m_next) {
985 len = imin(M_TRAILINGSPACE(mb), tot - progress);
986
987 error = uiomove(mtod(mb, char *), len, uio);
988 if (error != 0) {
989 m_freem(m);
990 return (error);
991 }
992
993 /* each mbuf is M_PKTHDR chained via m_next */
994 mb->m_len = len;
995 mb->m_pkthdr.len = len;
996
997 progress += len;
998 }
999 VERIFY(progress == tot);
1000 *top = m;
1001 return (0);
1002}
1003
1004/*
1005 * MPTCP socket protocol-user socket send routine, derived from sosend().
1006 */
1007static int
1008mptcp_usr_sosend(struct socket *mp_so, struct sockaddr *addr, struct uio *uio,
1009 struct mbuf *top, struct mbuf *control, int flags)
1010{
1011#pragma unused(addr)
1012 int32_t space;
1013 user_ssize_t resid;
1014 int error, sendflags;
1015 struct proc *p = current_proc();
1016 int sblocked = 0;
1017
1018 /* UIO is required for now, due to per-mbuf M_PKTHDR constrains */
1019 if (uio == NULL || top != NULL) {
1020 error = EINVAL;
1021 goto out;
1022 }
1023 resid = uio_resid(uio);
1024
1025 socket_lock(mp_so, 1);
1026 so_update_last_owner_locked(mp_so, p);
1027 so_update_policy(mp_so);
1028
1029 VERIFY(mp_so->so_type == SOCK_STREAM);
1030 VERIFY(!(mp_so->so_flags & SOF_MP_SUBFLOW));
1031
1032 if ((flags & (MSG_OOB|MSG_DONTROUTE|MSG_HOLD|MSG_SEND|MSG_FLUSH)) ||
1033 (mp_so->so_flags & SOF_ENABLE_MSGS)) {
1034 error = EOPNOTSUPP;
1035 socket_unlock(mp_so, 1);
1036 goto out;
1037 }
1038
1039 /*
1040 * In theory resid should be unsigned. However, space must be
1041 * signed, as it might be less than 0 if we over-committed, and we
1042 * must use a signed comparison of space and resid. On the other
1043 * hand, a negative resid causes us to loop sending 0-length
1044 * segments to the protocol.
1045 */
1046 if (resid < 0 || (flags & MSG_EOR) || control != NULL) {
1047 error = EINVAL;
1048 socket_unlock(mp_so, 1);
1049 goto out;
1050 }
1051
1052 OSIncrementAtomicLong(&p->p_stats->p_ru.ru_msgsnd);
1053
1054 do {
1055 error = sosendcheck(mp_so, NULL, resid, 0, 0, flags,
1056 &sblocked, NULL);
1057 if (error != 0)
1058 goto release;
1059
1060 space = sbspace(&mp_so->so_snd);
1061 do {
1062 socket_unlock(mp_so, 0);
1063 /*
1064 * Copy the data from userland into an mbuf chain.
1065 */
1066 error = mptcp_uiotombuf(uio, M_WAITOK, space, 0, &top);
1067 if (error != 0) {
1068 socket_lock(mp_so, 0);
1069 goto release;
1070 }
1071 VERIFY(top != NULL);
1072 space -= resid - uio_resid(uio);
1073 resid = uio_resid(uio);
1074 socket_lock(mp_so, 0);
1075
1076 /*
1077 * Compute flags here, for pru_send and NKEs.
1078 */
1079 sendflags = (resid > 0 && space > 0) ?
1080 PRUS_MORETOCOME : 0;
1081
1082 /*
1083 * Socket filter processing
1084 */
1085 VERIFY(control == NULL);
1086 error = sflt_data_out(mp_so, NULL, &top, &control, 0);
1087 if (error != 0) {
1088 if (error == EJUSTRETURN) {
1089 error = 0;
1090 top = NULL;
1091 /* always free control if any */
1092 }
1093 goto release;
1094 }
1095 if (control != NULL) {
1096 m_freem(control);
1097 control = NULL;
1098 }
1099
1100 /*
1101 * Pass data to protocol.
1102 */
1103 error = (*mp_so->so_proto->pr_usrreqs->pru_send)
1104 (mp_so, sendflags, top, NULL, NULL, p);
1105
1106 top = NULL;
1107 if (error != 0)
1108 goto release;
1109 } while (resid != 0 && space > 0);
1110 } while (resid != 0);
1111
1112release:
1113 if (sblocked)
1114 sbunlock(&mp_so->so_snd, FALSE); /* will unlock socket */
1115 else
1116 socket_unlock(mp_so, 1);
1117out:
1118 if (top != NULL)
1119 m_freem(top);
1120 if (control != NULL)
1121 m_freem(control);
1122
5ba3f43e 1123 soclearfastopen(mp_so);
490019cf 1124
39236c6e
A
1125 return (error);
1126}
1127
1128/*
1129 * Called to filter SOPT_{SET,GET} for SOL_SOCKET level socket options.
1130 * This routine simply indicates to the caller whether or not to proceed
1131 * further with the given socket option. This is invoked by sosetoptlock()
1132 * and sogetoptlock().
1133 */
1134static int
1135mptcp_usr_socheckopt(struct socket *mp_so, struct sockopt *sopt)
1136{
1137#pragma unused(mp_so)
1138 int error = 0;
1139
1140 VERIFY(sopt->sopt_level == SOL_SOCKET);
1141
1142 /*
1143 * We could check for sopt_dir (set/get) here, but we'll just
1144 * let the caller deal with it as appropriate; therefore the
1145 * following is a superset of the socket options which we
1146 * allow for set/get.
1147 *
1148 * XXX: adi@apple.com
1149 *
1150 * Need to consider the following cases:
1151 *
5ba3f43e 1152 * a. Certain socket options don't have a clear definition
39236c6e
A
1153 * on the expected behavior post connect(2). At the time
1154 * those options are issued on the MP socket, there may
1155 * be existing subflow sockets that are already connected.
1156 */
1157 switch (sopt->sopt_name) {
1158 case SO_LINGER: /* MP */
1159 case SO_LINGER_SEC: /* MP */
1160 case SO_TYPE: /* MP */
1161 case SO_NREAD: /* MP */
1162 case SO_NWRITE: /* MP */
1163 case SO_ERROR: /* MP */
1164 case SO_SNDBUF: /* MP */
1165 case SO_RCVBUF: /* MP */
1166 case SO_SNDLOWAT: /* MP */
1167 case SO_RCVLOWAT: /* MP */
1168 case SO_SNDTIMEO: /* MP */
1169 case SO_RCVTIMEO: /* MP */
1170 case SO_NKE: /* MP */
1171 case SO_NOSIGPIPE: /* MP */
1172 case SO_NOADDRERR: /* MP */
1173 case SO_LABEL: /* MP */
1174 case SO_PEERLABEL: /* MP */
1175 case SO_DEFUNCTOK: /* MP */
1176 case SO_ISDEFUNCT: /* MP */
1177 case SO_TRAFFIC_CLASS_DBG: /* MP */
5ba3f43e
A
1178 case SO_DELEGATED: /* MP */
1179 case SO_DELEGATED_UUID: /* MP */
1180#if NECP
1181 case SO_NECP_ATTRIBUTES:
1182 case SO_NECP_CLIENTUUID:
1183#endif /* NECP */
39236c6e
A
1184 /*
1185 * Tell the caller that these options are to be processed.
1186 */
1187 break;
1188
1189 case SO_DEBUG: /* MP + subflow */
1190 case SO_KEEPALIVE: /* MP + subflow */
1191 case SO_USELOOPBACK: /* MP + subflow */
1192 case SO_RANDOMPORT: /* MP + subflow */
1193 case SO_TRAFFIC_CLASS: /* MP + subflow */
1194 case SO_RECV_TRAFFIC_CLASS: /* MP + subflow */
1195 case SO_PRIVILEGED_TRAFFIC_CLASS: /* MP + subflow */
1196 case SO_RECV_ANYIF: /* MP + subflow */
1197 case SO_RESTRICTIONS: /* MP + subflow */
1198 case SO_FLUSH: /* MP + subflow */
fe8ab488 1199 case SO_NOWAKEFROMSLEEP:
39037602 1200 case SO_NOAPNFALLBK:
5ba3f43e 1201 case SO_MARK_CELLFALLBACK:
39236c6e
A
1202 /*
1203 * Tell the caller that these options are to be processed;
1204 * these will also be recorded later by mptcp_setopt().
1205 *
1206 * NOTE: Only support integer option value for now.
1207 */
1208 if (sopt->sopt_valsize != sizeof (int))
1209 error = EINVAL;
1210 break;
1211
1212 default:
1213 /*
1214 * Tell the caller to stop immediately and return an error.
1215 */
1216 error = ENOPROTOOPT;
1217 break;
1218 }
1219
1220 return (error);
1221}
1222
1223/*
1224 * Issue SOPT_SET for all MPTCP subflows (for integer option values.)
1225 */
1226static int
1227mptcp_setopt_apply(struct mptses *mpte, struct mptopt *mpo)
1228{
1229 struct socket *mp_so;
1230 struct mptsub *mpts;
1231 struct mptopt smpo;
1232 int error = 0;
1233
1234 /* just bail now if this isn't applicable to subflow sockets */
1235 if (!(mpo->mpo_flags & MPOF_SUBFLOW_OK)) {
1236 error = ENOPROTOOPT;
1237 goto out;
1238 }
1239
1240 /*
1241 * Skip those that are handled internally; these options
1242 * should not have been recorded and marked with the
1243 * MPOF_SUBFLOW_OK by mptcp_setopt(), but just in case.
1244 */
1245 if (mpo->mpo_level == SOL_SOCKET &&
1246 (mpo->mpo_name == SO_NOSIGPIPE || mpo->mpo_name == SO_NOADDRERR)) {
1247 error = ENOPROTOOPT;
1248 goto out;
1249 }
1250
5ba3f43e
A
1251 mpte_lock_assert_held(mpte); /* same as MP socket lock */
1252 mp_so = mptetoso(mpte);
39236c6e
A
1253
1254 /*
1255 * Don't bother going further if there's no subflow; mark the option
1256 * with MPOF_INTERIM so that we know whether or not to remove this
1257 * option upon encountering an error while issuing it during subflow
1258 * socket creation.
1259 */
1260 if (mpte->mpte_numflows == 0) {
1261 VERIFY(TAILQ_EMPTY(&mpte->mpte_subflows));
1262 mpo->mpo_flags |= MPOF_INTERIM;
1263 /* return success */
1264 goto out;
1265 }
1266
1267 bzero(&smpo, sizeof (smpo));
1268 smpo.mpo_flags |= MPOF_SUBFLOW_OK;
1269 smpo.mpo_level = mpo->mpo_level;
1270 smpo.mpo_name = mpo->mpo_name;
1271
1272 /* grab exisiting values in case we need to rollback */
1273 TAILQ_FOREACH(mpts, &mpte->mpte_subflows, mpts_entry) {
1274 struct socket *so;
1275
39236c6e
A
1276 mpts->mpts_flags &= ~(MPTSF_SOPT_OLDVAL|MPTSF_SOPT_INPROG);
1277 mpts->mpts_oldintval = 0;
1278 smpo.mpo_intval = 0;
1279 VERIFY(mpts->mpts_socket != NULL);
1280 so = mpts->mpts_socket;
39236c6e
A
1281 if (mptcp_subflow_sogetopt(mpte, so, &smpo) == 0) {
1282 mpts->mpts_flags |= MPTSF_SOPT_OLDVAL;
1283 mpts->mpts_oldintval = smpo.mpo_intval;
1284 }
39236c6e
A
1285 }
1286
1287 /* apply socket option */
1288 TAILQ_FOREACH(mpts, &mpte->mpte_subflows, mpts_entry) {
1289 struct socket *so;
1290
39236c6e
A
1291 mpts->mpts_flags |= MPTSF_SOPT_INPROG;
1292 VERIFY(mpts->mpts_socket != NULL);
1293 so = mpts->mpts_socket;
5ba3f43e 1294 error = mptcp_subflow_sosetopt(mpte, mpts, mpo);
39236c6e
A
1295 if (error != 0)
1296 break;
1297 }
1298
1299 /* cleanup, and rollback if needed */
1300 TAILQ_FOREACH(mpts, &mpte->mpte_subflows, mpts_entry) {
1301 struct socket *so;
1302
39236c6e
A
1303 if (!(mpts->mpts_flags & MPTSF_SOPT_INPROG)) {
1304 /* clear in case it's set */
1305 mpts->mpts_flags &= ~MPTSF_SOPT_OLDVAL;
1306 mpts->mpts_oldintval = 0;
39236c6e
A
1307 continue;
1308 }
1309 if (!(mpts->mpts_flags & MPTSF_SOPT_OLDVAL)) {
1310 mpts->mpts_flags &= ~MPTSF_SOPT_INPROG;
1311 VERIFY(mpts->mpts_oldintval == 0);
39236c6e
A
1312 continue;
1313 }
1314 /* error during sosetopt, so roll it back */
1315 if (error != 0) {
1316 VERIFY(mpts->mpts_socket != NULL);
1317 so = mpts->mpts_socket;
39236c6e 1318 smpo.mpo_intval = mpts->mpts_oldintval;
5ba3f43e 1319 mptcp_subflow_sosetopt(mpte, mpts, &smpo);
39236c6e
A
1320 }
1321 mpts->mpts_oldintval = 0;
1322 mpts->mpts_flags &= ~(MPTSF_SOPT_OLDVAL|MPTSF_SOPT_INPROG);
39236c6e
A
1323 }
1324
1325out:
1326 return (error);
1327}
1328
1329/*
1330 * Handle SOPT_SET for socket options issued on MP socket.
1331 */
1332static int
1333mptcp_setopt(struct mptses *mpte, struct sockopt *sopt)
1334{
5ba3f43e 1335 int error = 0, optval = 0, level, optname, rec = 1;
39236c6e
A
1336 struct mptopt smpo, *mpo = NULL;
1337 struct socket *mp_so;
39236c6e
A
1338
1339 level = sopt->sopt_level;
1340 optname = sopt->sopt_name;
1341
1342 VERIFY(sopt->sopt_dir == SOPT_SET);
1343 VERIFY(level == SOL_SOCKET || level == IPPROTO_TCP);
5ba3f43e
A
1344 mpte_lock_assert_held(mpte); /* same as MP socket lock */
1345 mp_so = mptetoso(mpte);
39236c6e
A
1346
1347 /*
1348 * Record socket options which are applicable to subflow sockets so
1349 * that we can replay them for new ones; see mptcp_usr_socheckopt()
1350 * for the list of eligible socket-level options.
1351 */
1352 if (level == SOL_SOCKET) {
1353 switch (optname) {
1354 case SO_DEBUG:
1355 case SO_KEEPALIVE:
1356 case SO_USELOOPBACK:
1357 case SO_RANDOMPORT:
1358 case SO_TRAFFIC_CLASS:
1359 case SO_RECV_TRAFFIC_CLASS:
1360 case SO_PRIVILEGED_TRAFFIC_CLASS:
1361 case SO_RECV_ANYIF:
1362 case SO_RESTRICTIONS:
fe8ab488 1363 case SO_NOWAKEFROMSLEEP:
39037602 1364 case SO_NOAPNFALLBK:
5ba3f43e 1365 case SO_MARK_CELLFALLBACK:
39236c6e
A
1366 /* record it */
1367 break;
1368 case SO_FLUSH:
1369 /* don't record it */
1370 rec = 0;
1371 break;
5ba3f43e
A
1372
1373 /* Next ones, record at MPTCP-level */
1374#if NECP
1375 case SO_NECP_CLIENTUUID:
1376 if (!uuid_is_null(mpsotomppcb(mp_so)->necp_client_uuid)) {
1377 error = EINVAL;
1378 goto out;
1379 }
1380
1381 error = sooptcopyin(sopt, &mpsotomppcb(mp_so)->necp_client_uuid,
1382 sizeof(uuid_t), sizeof(uuid_t));
1383 if (error != 0) {
1384 goto out;
1385 }
1386
1387 mpsotomppcb(mp_so)->necp_cb = mptcp_session_necp_cb;
1388 error = necp_client_register_multipath_cb(mp_so->last_pid,
1389 mpsotomppcb(mp_so)->necp_client_uuid,
1390 mpsotomppcb(mp_so));
1391 if (error)
1392 goto out;
1393
1394 if (uuid_is_null(mpsotomppcb(mp_so)->necp_client_uuid)) {
1395 error = EINVAL;
1396 goto out;
1397 }
1398
1399 goto out;
1400 case SO_NECP_ATTRIBUTES:
1401#endif /* NECP */
39236c6e 1402 default:
5ba3f43e 1403 /* nothing to do; just return */
39236c6e
A
1404 goto out;
1405 }
1406 } else {
1407 switch (optname) {
1408 case TCP_NODELAY:
1409 case TCP_RXT_FINDROP:
1410 case TCP_KEEPALIVE:
1411 case TCP_KEEPINTVL:
1412 case TCP_KEEPCNT:
1413 case TCP_CONNECTIONTIMEOUT:
1414 case TCP_RXT_CONNDROPTIME:
1415 case PERSIST_TIMEOUT:
5ba3f43e
A
1416 case TCP_ADAPTIVE_READ_TIMEOUT:
1417 case TCP_ADAPTIVE_WRITE_TIMEOUT:
39236c6e
A
1418 /* eligible; record it */
1419 break;
fe8ab488
A
1420 case TCP_NOTSENT_LOWAT:
1421 /* record at MPTCP level */
1422 error = sooptcopyin(sopt, &optval, sizeof(optval),
1423 sizeof(optval));
1424 if (error)
1425 goto out;
1426 if (optval < 0) {
1427 error = EINVAL;
1428 goto out;
1429 } else {
1430 if (optval == 0) {
1431 mp_so->so_flags &= ~SOF_NOTSENT_LOWAT;
1432 error = mptcp_set_notsent_lowat(mpte,0);
1433 } else {
1434 mp_so->so_flags |= SOF_NOTSENT_LOWAT;
1435 error = mptcp_set_notsent_lowat(mpte,
1436 optval);
1437 }
1438 }
5ba3f43e
A
1439 goto out;
1440 case MPTCP_SERVICE_TYPE:
1441 /* record at MPTCP level */
1442 error = sooptcopyin(sopt, &optval, sizeof(optval),
1443 sizeof(optval));
1444 if (error)
1445 goto out;
1446 if (optval < 0 || optval >= MPTCP_SVCTYPE_MAX) {
1447 error = EINVAL;
1448 goto out;
1449 }
1450
1451 mpte->mpte_svctype = optval;
1452
1453 if (mptcp_entitlement_check(mp_so) < 0) {
1454 error = EACCES;
1455 goto out;
1456 }
1457
1458 mpte->mpte_flags |= MPTE_SVCTYPE_CHECKED;
1459
fe8ab488 1460 goto out;
39236c6e
A
1461 default:
1462 /* not eligible */
1463 error = ENOPROTOOPT;
1464 goto out;
1465 }
1466 }
1467
1468 if ((error = sooptcopyin(sopt, &optval, sizeof (optval),
1469 sizeof (optval))) != 0)
1470 goto out;
1471
1472 if (rec) {
1473 /* search for an existing one; if not found, allocate */
1474 if ((mpo = mptcp_sopt_find(mpte, sopt)) == NULL)
1475 mpo = mptcp_sopt_alloc(M_WAITOK);
1476
1477 if (mpo == NULL) {
1478 error = ENOBUFS;
1479 } else {
5ba3f43e
A
1480 mptcplog((LOG_DEBUG, "%s: mp_so 0x%llx sopt %s val %d %s\n",
1481 __func__, (u_int64_t)VM_KERNEL_ADDRPERM(mp_so),
1482 mptcp_sopt2str(level, optname), optval,
39236c6e 1483 (mpo->mpo_flags & MPOF_ATTACHED) ?
3e170ce0
A
1484 "updated" : "recorded"),
1485 MPTCP_SOCKET_DBG, MPTCP_LOGLVL_LOG);
39236c6e
A
1486
1487 /* initialize or update, as needed */
1488 mpo->mpo_intval = optval;
1489 if (!(mpo->mpo_flags & MPOF_ATTACHED)) {
1490 mpo->mpo_level = level;
1491 mpo->mpo_name = optname;
1492 mptcp_sopt_insert(mpte, mpo);
1493 }
1494 VERIFY(mpo->mpo_flags & MPOF_ATTACHED);
1495 /* this can be issued on the subflow socket */
1496 mpo->mpo_flags |= MPOF_SUBFLOW_OK;
1497 }
1498 } else {
1499 bzero(&smpo, sizeof (smpo));
1500 mpo = &smpo;
1501 mpo->mpo_flags |= MPOF_SUBFLOW_OK;
1502 mpo->mpo_level = level;
1503 mpo->mpo_name = optname;
1504 mpo->mpo_intval = optval;
1505 }
1506 VERIFY(mpo == NULL || error == 0);
1507
1508 /* issue this socket option on existing subflows */
1509 if (error == 0) {
1510 error = mptcp_setopt_apply(mpte, mpo);
1511 if (error != 0 && (mpo->mpo_flags & MPOF_ATTACHED)) {
1512 VERIFY(mpo != &smpo);
1513 mptcp_sopt_remove(mpte, mpo);
1514 mptcp_sopt_free(mpo);
1515 }
1516 if (mpo == &smpo)
1517 mpo->mpo_flags &= ~MPOF_INTERIM;
1518 }
1519out:
1520 if (error == 0 && mpo != NULL) {
5ba3f43e 1521 mptcplog((LOG_INFO, "%s: mp_so 0x%llx sopt %s val %d set %s\n",
39236c6e 1522 __func__, (u_int64_t)VM_KERNEL_ADDRPERM(mp_so),
5ba3f43e
A
1523 mptcp_sopt2str(level, optname), optval,
1524 (mpo->mpo_flags & MPOF_INTERIM) ?
3e170ce0 1525 "pending" : "successful"),
5ba3f43e 1526 MPTCP_SOCKET_DBG, MPTCP_LOGLVL_LOG);
39236c6e 1527 } else if (error != 0) {
5ba3f43e
A
1528 mptcplog((LOG_ERR, "%s: mp_so 0x%llx sopt %s (%d, %d) val %d can't be issued error %d\n",
1529 __func__, (u_int64_t)VM_KERNEL_ADDRPERM(mp_so),
1530 mptcp_sopt2str(level, optname), level, optname, optval, error),
3e170ce0 1531 MPTCP_SOCKET_DBG, MPTCP_LOGLVL_ERR);
39236c6e
A
1532 }
1533 return (error);
1534}
1535
1536/*
1537 * Handle SOPT_GET for socket options issued on MP socket.
1538 */
1539static int
1540mptcp_getopt(struct mptses *mpte, struct sockopt *sopt)
1541{
1542 int error = 0, optval;
1543
1544 VERIFY(sopt->sopt_dir == SOPT_GET);
5ba3f43e 1545 mpte_lock_assert_held(mpte); /* same as MP socket lock */
39236c6e
A
1546
1547 /*
1548 * We only handle SOPT_GET for TCP level socket options; we should
1549 * not get here for socket level options since they are already
1550 * handled at the socket layer.
1551 */
1552 if (sopt->sopt_level != IPPROTO_TCP) {
1553 error = ENOPROTOOPT;
1554 goto out;
1555 }
1556
1557 switch (sopt->sopt_name) {
1558 case TCP_NODELAY:
1559 case TCP_RXT_FINDROP:
1560 case TCP_KEEPALIVE:
1561 case TCP_KEEPINTVL:
1562 case TCP_KEEPCNT:
1563 case TCP_CONNECTIONTIMEOUT:
1564 case TCP_RXT_CONNDROPTIME:
1565 case PERSIST_TIMEOUT:
5ba3f43e
A
1566 case TCP_ADAPTIVE_READ_TIMEOUT:
1567 case TCP_ADAPTIVE_WRITE_TIMEOUT:
fe8ab488 1568 case TCP_NOTSENT_LOWAT:
5ba3f43e 1569 case MPTCP_SERVICE_TYPE:
39236c6e
A
1570 /* eligible; get the default value just in case */
1571 error = mptcp_default_tcp_optval(mpte, sopt, &optval);
1572 break;
1573 default:
1574 /* not eligible */
1575 error = ENOPROTOOPT;
1576 break;
1577 }
1578
fe8ab488
A
1579 switch (sopt->sopt_name) {
1580 case TCP_NOTSENT_LOWAT:
5ba3f43e 1581 if (mptetoso(mpte)->so_flags & SOF_NOTSENT_LOWAT)
fe8ab488
A
1582 optval = mptcp_get_notsent_lowat(mpte);
1583 else
1584 optval = 0;
1585 goto out;
5ba3f43e
A
1586 case MPTCP_SERVICE_TYPE:
1587 optval = mpte->mpte_svctype;
1588 goto out;
fe8ab488
A
1589 }
1590
39236c6e
A
1591 /*
1592 * Search for a previously-issued TCP level socket option and
1593 * return the recorded option value. This assumes that the
1594 * value did not get modified by the lower layer after it was
1595 * issued at setsockopt(2) time. If not found, we'll return
1596 * the default value obtained ealier.
1597 */
1598 if (error == 0) {
1599 struct mptopt *mpo;
1600
1601 if ((mpo = mptcp_sopt_find(mpte, sopt)) != NULL)
1602 optval = mpo->mpo_intval;
1603
1604 error = sooptcopyout(sopt, &optval, sizeof (int));
1605 }
1606out:
1607 return (error);
1608}
1609
1610/*
1611 * Return default values for TCP socket options. Ideally we would query the
1612 * subflow TCP socket, but that requires creating a subflow socket before
1613 * connectx(2) time. To simplify things, just return the default values
1614 * that we know of.
1615 */
1616static int
1617mptcp_default_tcp_optval(struct mptses *mpte, struct sockopt *sopt, int *optval)
1618{
1619 int error = 0;
1620
1621 VERIFY(sopt->sopt_level == IPPROTO_TCP);
1622 VERIFY(sopt->sopt_dir == SOPT_GET);
5ba3f43e 1623 mpte_lock_assert_held(mpte); /* same as MP socket lock */
39236c6e
A
1624
1625 /* try to do what tcp_newtcpcb() does */
1626 switch (sopt->sopt_name) {
1627 case TCP_NODELAY:
1628 case TCP_RXT_FINDROP:
1629 case TCP_KEEPINTVL:
1630 case TCP_KEEPCNT:
1631 case TCP_CONNECTIONTIMEOUT:
1632 case TCP_RXT_CONNDROPTIME:
fe8ab488 1633 case TCP_NOTSENT_LOWAT:
5ba3f43e
A
1634 case TCP_ADAPTIVE_READ_TIMEOUT:
1635 case TCP_ADAPTIVE_WRITE_TIMEOUT:
1636 case MPTCP_SERVICE_TYPE:
39236c6e
A
1637 *optval = 0;
1638 break;
1639
1640 case TCP_KEEPALIVE:
1641 *optval = mptcp_subflow_keeptime;
1642 break;
1643
1644 case PERSIST_TIMEOUT:
1645 *optval = tcp_max_persist_timeout;
1646 break;
1647
1648 default:
1649 error = ENOPROTOOPT;
1650 break;
1651 }
1652 return (error);
1653}
1654
1655/*
1656 * MPTCP SOPT_{SET,GET} socket option handler, for options issued on the MP
1657 * socket, at SOL_SOCKET and IPPROTO_TCP levels. The former is restricted
1658 * to those that are allowed by mptcp_usr_socheckopt().
1659 */
1660int
1661mptcp_ctloutput(struct socket *mp_so, struct sockopt *sopt)
1662{
5ba3f43e 1663 struct mppcb *mpp = mpsotomppcb(mp_so);
39236c6e
A
1664 struct mptses *mpte;
1665 int error = 0;
1666
1667 if (mpp == NULL || mpp->mpp_state == MPPCB_STATE_DEAD) {
1668 error = EINVAL;
1669 goto out;
1670 }
1671 mpte = mptompte(mpp);
5ba3f43e 1672 mpte_lock_assert_held(mpte); /* same as MP socket lock */
39236c6e
A
1673
1674 /* we only handle socket and TCP-level socket options for MPTCP */
1675 if (sopt->sopt_level != SOL_SOCKET && sopt->sopt_level != IPPROTO_TCP) {
3e170ce0
A
1676 mptcplog((LOG_DEBUG, "MPTCP Socket: "
1677 "%s: mp_so 0x%llx sopt %s level not "
39236c6e 1678 "handled\n", __func__, (u_int64_t)VM_KERNEL_ADDRPERM(mp_so),
5ba3f43e 1679 mptcp_sopt2str(sopt->sopt_level, sopt->sopt_name)),
3e170ce0 1680 MPTCP_SOCKET_DBG, MPTCP_LOGLVL_LOG);
39236c6e
A
1681 error = EINVAL;
1682 goto out;
1683 }
1684
1685 switch (sopt->sopt_dir) {
1686 case SOPT_SET:
1687 error = mptcp_setopt(mpte, sopt);
1688 break;
1689
1690 case SOPT_GET:
1691 error = mptcp_getopt(mpte, sopt);
1692 break;
1693 }
1694out:
1695 return (error);
1696}
1697
39236c6e 1698const char *
5ba3f43e 1699mptcp_sopt2str(int level, int optname)
39236c6e 1700{
39236c6e
A
1701 switch (level) {
1702 case SOL_SOCKET:
39236c6e
A
1703 switch (optname) {
1704 case SO_LINGER:
5ba3f43e 1705 return ("SO_LINGER");
39236c6e 1706 case SO_LINGER_SEC:
5ba3f43e 1707 return ("SO_LINGER_SEC");
39236c6e 1708 case SO_DEBUG:
5ba3f43e 1709 return ("SO_DEBUG");
39236c6e 1710 case SO_KEEPALIVE:
5ba3f43e 1711 return ("SO_KEEPALIVE");
39236c6e 1712 case SO_USELOOPBACK:
5ba3f43e 1713 return ("SO_USELOOPBACK");
39236c6e 1714 case SO_TYPE:
5ba3f43e 1715 return ("SO_TYPE");
39236c6e 1716 case SO_NREAD:
5ba3f43e 1717 return ("SO_NREAD");
39236c6e 1718 case SO_NWRITE:
5ba3f43e 1719 return ("SO_NWRITE");
39236c6e 1720 case SO_ERROR:
5ba3f43e 1721 return ("SO_ERROR");
39236c6e 1722 case SO_SNDBUF:
5ba3f43e 1723 return ("SO_SNDBUF");
39236c6e 1724 case SO_RCVBUF:
5ba3f43e 1725 return ("SO_RCVBUF");
39236c6e 1726 case SO_SNDLOWAT:
5ba3f43e 1727 return ("SO_SNDLOWAT");
39236c6e 1728 case SO_RCVLOWAT:
5ba3f43e 1729 return ("SO_RCVLOWAT");
39236c6e 1730 case SO_SNDTIMEO:
5ba3f43e 1731 return ("SO_SNDTIMEO");
39236c6e 1732 case SO_RCVTIMEO:
5ba3f43e 1733 return ("SO_RCVTIMEO");
39236c6e 1734 case SO_NKE:
5ba3f43e 1735 return ("SO_NKE");
39236c6e 1736 case SO_NOSIGPIPE:
5ba3f43e 1737 return ("SO_NOSIGPIPE");
39236c6e 1738 case SO_NOADDRERR:
5ba3f43e 1739 return ("SO_NOADDRERR");
39236c6e 1740 case SO_RESTRICTIONS:
5ba3f43e 1741 return ("SO_RESTRICTIONS");
39236c6e 1742 case SO_LABEL:
5ba3f43e 1743 return ("SO_LABEL");
39236c6e 1744 case SO_PEERLABEL:
5ba3f43e 1745 return ("SO_PEERLABEL");
39236c6e 1746 case SO_RANDOMPORT:
5ba3f43e 1747 return ("SO_RANDOMPORT");
39236c6e 1748 case SO_TRAFFIC_CLASS:
5ba3f43e 1749 return ("SO_TRAFFIC_CLASS");
39236c6e 1750 case SO_RECV_TRAFFIC_CLASS:
5ba3f43e 1751 return ("SO_RECV_TRAFFIC_CLASS");
39236c6e 1752 case SO_TRAFFIC_CLASS_DBG:
5ba3f43e 1753 return ("SO_TRAFFIC_CLASS_DBG");
39236c6e 1754 case SO_PRIVILEGED_TRAFFIC_CLASS:
5ba3f43e 1755 return ("SO_PRIVILEGED_TRAFFIC_CLASS");
39236c6e 1756 case SO_DEFUNCTOK:
5ba3f43e 1757 return ("SO_DEFUNCTOK");
39236c6e 1758 case SO_ISDEFUNCT:
5ba3f43e 1759 return ("SO_ISDEFUNCT");
39236c6e 1760 case SO_OPPORTUNISTIC:
5ba3f43e 1761 return ("SO_OPPORTUNISTIC");
39236c6e 1762 case SO_FLUSH:
5ba3f43e 1763 return ("SO_FLUSH");
39236c6e 1764 case SO_RECV_ANYIF:
5ba3f43e 1765 return ("SO_RECV_ANYIF");
fe8ab488 1766 case SO_NOWAKEFROMSLEEP:
5ba3f43e 1767 return ("SO_NOWAKEFROMSLEEP");
39037602 1768 case SO_NOAPNFALLBK:
5ba3f43e
A
1769 return ("SO_NOAPNFALLBK");
1770 case SO_MARK_CELLFALLBACK:
1771 return ("SO_CELLFALLBACK");
1772 case SO_DELEGATED:
1773 return ("SO_DELEGATED");
1774 case SO_DELEGATED_UUID:
1775 return ("SO_DELEGATED_UUID");
1776#if NECP
1777 case SO_NECP_ATTRIBUTES:
1778 return ("SO_NECP_ATTRIBUTES");
1779 case SO_NECP_CLIENTUUID:
1780 return ("SO_NECP_CLIENTUUID");
1781#endif /* NECP */
39236c6e 1782 }
5ba3f43e 1783
39236c6e
A
1784 break;
1785 case IPPROTO_TCP:
39236c6e 1786 switch (optname) {
5ba3f43e
A
1787 case TCP_NODELAY:
1788 return ("TCP_NODELAY");
39236c6e 1789 case TCP_KEEPALIVE:
5ba3f43e 1790 return ("TCP_KEEPALIVE");
39236c6e 1791 case TCP_KEEPINTVL:
5ba3f43e 1792 return ("TCP_KEEPINTVL");
39236c6e 1793 case TCP_KEEPCNT:
5ba3f43e 1794 return ("TCP_KEEPCNT");
39236c6e 1795 case TCP_CONNECTIONTIMEOUT:
5ba3f43e 1796 return ("TCP_CONNECTIONTIMEOUT");
39236c6e 1797 case TCP_RXT_CONNDROPTIME:
5ba3f43e 1798 return ("TCP_RXT_CONNDROPTIME");
39236c6e 1799 case PERSIST_TIMEOUT:
5ba3f43e
A
1800 return ("PERSIST_TIMEOUT");
1801 case TCP_NOTSENT_LOWAT:
1802 return ("NOTSENT_LOWAT");
1803 case TCP_ADAPTIVE_READ_TIMEOUT:
1804 return ("ADAPTIVE_READ_TIMEOUT");
1805 case TCP_ADAPTIVE_WRITE_TIMEOUT:
1806 return ("ADAPTIVE_WRITE_TIMEOUT");
1807 case MPTCP_SERVICE_TYPE:
1808 return ("MPTCP_SERVICE_TYPE");
39236c6e 1809 }
5ba3f43e 1810
39236c6e
A
1811 break;
1812 }
1813
5ba3f43e 1814 return ("unknown");
39236c6e 1815}
490019cf
A
1816
1817static int
1818mptcp_usr_preconnect(struct socket *mp_so)
1819{
1820 struct mptsub *mpts = NULL;
5ba3f43e 1821 struct mppcb *mpp = mpsotomppcb(mp_so);
490019cf
A
1822 struct mptses *mpte;
1823 struct socket *so;
1824 struct tcpcb *tp = NULL;
5ba3f43e 1825 int error;
490019cf
A
1826
1827 mpte = mptompte(mpp);
1828 VERIFY(mpte != NULL);
5ba3f43e 1829 mpte_lock_assert_held(mpte); /* same as MP socket lock */
490019cf
A
1830
1831 mpts = mptcp_get_subflow(mpte, NULL, NULL);
1832 if (mpts == NULL) {
5ba3f43e
A
1833 mptcplog((LOG_ERR, "%s: mp_so 0x%llx invalid preconnect ",
1834 __func__, (u_int64_t)VM_KERNEL_ADDRPERM(mp_so)),
1835 MPTCP_SOCKET_DBG, MPTCP_LOGLVL_ERR);
490019cf
A
1836 return (EINVAL);
1837 }
490019cf
A
1838 mpts->mpts_flags &= ~MPTSF_TFO_REQD;
1839 so = mpts->mpts_socket;
490019cf
A
1840 tp = intotcpcb(sotoinpcb(so));
1841 tp->t_mpflags &= ~TMPF_TFO_REQUEST;
5ba3f43e
A
1842 error = tcp_output(sototcpcb(so));
1843
1844 soclearfastopen(mp_so);
1845
490019cf
A
1846 return (error);
1847}