2 * Copyright (c) 2012-2017 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/kernel.h>
33 #include <sys/mcache.h>
34 #include <sys/syslog.h>
35 #include <sys/socket.h>
36 #include <sys/socketvar.h>
37 #include <sys/protosw.h>
38 #include <sys/proc_internal.h>
40 #include <mach/boolean.h>
41 #include <kern/zalloc.h>
42 #include <kern/locks.h>
44 #include <netinet/mp_pcb.h>
45 #include <netinet/mptcp_var.h>
46 #include <netinet6/in6_pcb.h>
48 static lck_grp_t
*mp_lock_grp
;
49 static lck_attr_t
*mp_lock_attr
;
50 static lck_grp_attr_t
*mp_lock_grp_attr
;
51 decl_lck_mtx_data(static, mp_lock
); /* global MULTIPATH lock */
52 decl_lck_mtx_data(static, mp_timeout_lock
);
54 static TAILQ_HEAD(, mppcbinfo
) mppi_head
= TAILQ_HEAD_INITIALIZER(mppi_head
);
56 static boolean_t mp_timeout_run
; /* MP timer is scheduled to run */
57 static boolean_t mp_garbage_collecting
;
58 static boolean_t mp_ticking
;
59 static void mp_sched_timeout(void);
60 static void mp_timeout(void *);
65 static int mp_initialized
= 0;
67 VERIFY(!mp_initialized
);
70 mp_lock_grp_attr
= lck_grp_attr_alloc_init();
71 mp_lock_grp
= lck_grp_alloc_init("multipath", mp_lock_grp_attr
);
72 mp_lock_attr
= lck_attr_alloc_init();
73 lck_mtx_init(&mp_lock
, mp_lock_grp
, mp_lock_attr
);
74 lck_mtx_init(&mp_timeout_lock
, mp_lock_grp
, mp_lock_attr
);
81 struct mppcbinfo
*mppi
;
87 * Update coarse-grained networking timestamp (in sec.); the idea
88 * is to piggy-back on the timeout callout to update the counter
89 * returnable via net_uptime().
93 lck_mtx_lock_spin(&mp_timeout_lock
);
94 gc
= mp_garbage_collecting
;
95 mp_garbage_collecting
= FALSE
;
101 lck_mtx_unlock(&mp_timeout_lock
);
103 lck_mtx_lock(&mp_lock
);
104 TAILQ_FOREACH(mppi
, &mppi_head
, mppi_entry
) {
105 if ((gc
&& mppi
->mppi_gc
!= NULL
) ||
106 (t
&& mppi
->mppi_timer
!= NULL
)) {
107 lck_mtx_lock(&mppi
->mppi_lock
);
108 if (gc
&& mppi
->mppi_gc
!= NULL
)
109 gc_act
+= mppi
->mppi_gc(mppi
);
110 if (t
&& mppi
->mppi_timer
!= NULL
)
111 t_act
+= mppi
->mppi_timer(mppi
);
112 lck_mtx_unlock(&mppi
->mppi_lock
);
115 lck_mtx_unlock(&mp_lock
);
117 lck_mtx_lock_spin(&mp_timeout_lock
);
120 /* lock was dropped above, so check first before overriding */
121 if (!mp_garbage_collecting
)
122 mp_garbage_collecting
= (gc_act
!= 0);
124 mp_ticking
= (t_act
!= 0);
126 /* re-arm the timer if there's work to do */
127 mp_timeout_run
= FALSE
;
129 lck_mtx_unlock(&mp_timeout_lock
);
133 mp_sched_timeout(void)
135 LCK_MTX_ASSERT(&mp_timeout_lock
, LCK_MTX_ASSERT_OWNED
);
137 if (!mp_timeout_run
&& (mp_garbage_collecting
|| mp_ticking
)) {
138 lck_mtx_convert_spin(&mp_timeout_lock
);
139 mp_timeout_run
= TRUE
;
140 timeout(mp_timeout
, NULL
, hz
);
147 lck_mtx_lock_spin(&mp_timeout_lock
);
148 mp_garbage_collecting
= TRUE
;
150 lck_mtx_unlock(&mp_timeout_lock
);
154 mptcp_timer_sched(void)
156 lck_mtx_lock_spin(&mp_timeout_lock
);
159 lck_mtx_unlock(&mp_timeout_lock
);
163 mp_pcbinfo_attach(struct mppcbinfo
*mppi
)
165 struct mppcbinfo
*mppi0
;
167 lck_mtx_lock(&mp_lock
);
168 TAILQ_FOREACH(mppi0
, &mppi_head
, mppi_entry
) {
170 panic("%s: mppi %p already in the list\n",
175 TAILQ_INSERT_TAIL(&mppi_head
, mppi
, mppi_entry
);
176 lck_mtx_unlock(&mp_lock
);
180 mp_pcbinfo_detach(struct mppcbinfo
*mppi
)
182 struct mppcbinfo
*mppi0
;
185 lck_mtx_lock(&mp_lock
);
186 TAILQ_FOREACH(mppi0
, &mppi_head
, mppi_entry
) {
191 TAILQ_REMOVE(&mppi_head
, mppi0
, mppi_entry
);
194 lck_mtx_unlock(&mp_lock
);
200 mp_pcballoc(struct socket
*so
, struct mppcbinfo
*mppi
)
202 struct mppcb
*mpp
= NULL
;
205 VERIFY(mpsotomppcb(so
) == NULL
);
207 mpp
= zalloc(mppi
->mppi_zone
);
212 bzero(mpp
, mppi
->mppi_size
);
213 lck_mtx_init(&mpp
->mpp_lock
, mppi
->mppi_lock_grp
, mppi
->mppi_lock_attr
);
214 mpp
->mpp_pcbinfo
= mppi
;
215 mpp
->mpp_state
= MPPCB_STATE_INUSE
;
216 mpp
->mpp_socket
= so
;
219 error
= mptcp_sescreate(mpp
);
221 lck_mtx_destroy(&mpp
->mpp_lock
, mppi
->mppi_lock_grp
);
222 zfree(mppi
->mppi_zone
, mpp
);
226 lck_mtx_lock(&mppi
->mppi_lock
);
227 mpp
->mpp_flags
|= MPP_ATTACHED
;
228 TAILQ_INSERT_TAIL(&mppi
->mppi_pcbs
, mpp
, mpp_entry
);
230 lck_mtx_unlock(&mppi
->mppi_lock
);
236 mp_pcbdetach(struct socket
*mp_so
)
238 struct mppcb
*mpp
= mpsotomppcb(mp_so
);
240 mpp
->mpp_state
= MPPCB_STATE_DEAD
;
241 if (!(mp_so
->so_flags
& SOF_PCBCLEARING
))
242 mp_so
->so_flags
|= SOF_PCBCLEARING
;
248 mp_pcbdispose(struct mppcb
*mpp
)
250 struct mppcbinfo
*mppi
= mpp
->mpp_pcbinfo
;
252 VERIFY(mppi
!= NULL
);
254 LCK_MTX_ASSERT(&mppi
->mppi_lock
, LCK_MTX_ASSERT_OWNED
);
255 mpp_lock_assert_held(mpp
);
257 VERIFY(mpp
->mpp_state
== MPPCB_STATE_DEAD
);
258 VERIFY(mpp
->mpp_flags
& MPP_ATTACHED
);
260 mpp
->mpp_flags
&= ~MPP_ATTACHED
;
261 TAILQ_REMOVE(&mppi
->mppi_pcbs
, mpp
, mpp_entry
);
262 VERIFY(mppi
->mppi_count
!= 0);
268 necp_mppcb_dispose(mpp
);
271 lck_mtx_destroy(&mpp
->mpp_lock
, mppi
->mppi_lock_grp
);
273 VERIFY(mpp
->mpp_socket
!= NULL
);
274 VERIFY(mpp
->mpp_socket
->so_usecount
== 0);
275 mpp
->mpp_socket
->so_pcb
= NULL
;
276 mpp
->mpp_socket
= NULL
;
278 zfree(mppi
->mppi_zone
, mpp
);
282 mp_getaddr_v4(struct socket
*mp_so
, struct sockaddr
**nam
, boolean_t peer
)
284 struct mptses
*mpte
= mpsotompte(mp_so
);
285 struct sockaddr_in
*sin
;
288 * Do the malloc first in case it blocks.
290 MALLOC(sin
, struct sockaddr_in
*, sizeof (*sin
), M_SONAME
, M_WAITOK
);
293 bzero(sin
, sizeof (*sin
));
294 sin
->sin_family
= AF_INET
;
295 sin
->sin_len
= sizeof (*sin
);
298 sin
->sin_port
= mpte
->__mpte_src_v4
.sin_port
;
299 sin
->sin_addr
= mpte
->__mpte_src_v4
.sin_addr
;
301 sin
->sin_port
= mpte
->__mpte_dst_v4
.sin_port
;
302 sin
->sin_addr
= mpte
->__mpte_dst_v4
.sin_addr
;
305 *nam
= (struct sockaddr
*)sin
;
310 mp_getaddr_v6(struct socket
*mp_so
, struct sockaddr
**nam
, boolean_t peer
)
312 struct mptses
*mpte
= mpsotompte(mp_so
);
313 struct in6_addr addr
;
317 port
= mpte
->__mpte_src_v6
.sin6_port
;
318 addr
= mpte
->__mpte_src_v6
.sin6_addr
;
320 port
= mpte
->__mpte_dst_v6
.sin6_port
;
321 addr
= mpte
->__mpte_dst_v6
.sin6_addr
;
324 *nam
= in6_sockaddr(port
, &addr
);
332 mp_getsockaddr(struct socket
*mp_so
, struct sockaddr
**nam
)
334 struct mptses
*mpte
= mpsotompte(mp_so
);
336 if (mpte
->mpte_src
.sa_family
== AF_INET
|| mpte
->mpte_src
.sa_family
== 0)
337 return mp_getaddr_v4(mp_so
, nam
, false);
338 else if (mpte
->mpte_src
.sa_family
== AF_INET
)
339 return mp_getaddr_v6(mp_so
, nam
, false);
345 mp_getpeeraddr(struct socket
*mp_so
, struct sockaddr
**nam
)
347 struct mptses
*mpte
= mpsotompte(mp_so
);
349 if (mpte
->mpte_src
.sa_family
== AF_INET
|| mpte
->mpte_src
.sa_family
== 0)
350 return mp_getaddr_v4(mp_so
, nam
, true);
351 else if (mpte
->mpte_src
.sa_family
== AF_INET
)
352 return mp_getaddr_v6(mp_so
, nam
, true);