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