1 /*
2 * Copyright (c) 2010-2021 Apple Inc. All rights reserved.
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 <string.h>
30 #include <stdint.h>
31 #include <stdbool.h>
32
33 #include <mach/mach_types.h>
34
35 #include <kern/kalloc.h>
36 #include <kern/locks.h>
37 #include <kern/debug.h>
38
39 #include <sys/kernel.h>
40 #include <sys/param.h>
41 #include <sys/sockio.h>
42 #include <sys/socket.h>
43 #include <sys/queue.h>
44 #include <sys/cdefs.h>
45 #include <sys/kern_control.h>
46 #include <sys/mbuf.h>
47 #include <sys/sysctl.h>
48
49 #include <net/if_types.h>
50 #include <net/if.h>
51 #include <net/kpi_interface.h>
52 #include <net/bpf.h>
53 #include <net/remote_vif.h>
54
55 #include <libkern/libkern.h>
56 #include <libkern/OSAtomic.h>
57
58 #include <os/log.h>
59
60 #define RVI_IF_NAME "rvi"
61
62 #define RVI_DIR_IN IFF_LINK0
63 #define RVI_DIR_OUT IFF_LINK1
64 #define RVI_DIR_INOUT (RVI_DIR_IN | RVI_DIR_OUT)
65
66 #define RVI_IF_FAMILY IFNET_FAMILY_LOOPBACK
67 #define RVI_IF_TYPE IFT_OTHER
68 #define RVI_IF_FLAGS (IFF_UP | IFF_DEBUG | RVI_DIR_INOUT)
69
70 struct rvi_client_t {
71 LIST_ENTRY(rvi_client_t) _cle;
72 ifnet_t _ifp;
73 uint32_t _unit;
74 uint32_t _vif;
75 uint32_t _raw_count;
76 uint32_t _pktap_count;
77 };
78
79 static LIST_HEAD(, rvi_client_t) _s_rvi_clients;
80
81 static LCK_GRP_DECLARE(rvi_grp, "remote virtual interface lock");
82 static LCK_RW_DECLARE(rvi_mtx, &rvi_grp);
83
84 static kern_ctl_ref rvi_kernctl = NULL;
85
86 kern_return_t rvi_start(kmod_info_t *, void *);
87 kern_return_t rvi_stop(kmod_info_t *, void *);
88
89 static void rvi_insert_client(struct rvi_client_t *);
90 static errno_t rvi_create_if(struct rvi_client_t *);
91 static errno_t rvi_destroy_if(struct rvi_client_t *);
92
93 static inline void rvi_lock_shared(lck_rw_t *);
94 static inline void rvi_lock_exclusive(lck_rw_t *);
95 static inline void rvi_lock_done_shared(lck_rw_t *);
96 static inline void rvi_lock_done_exclusive(lck_rw_t *);
97
98 static errno_t rvi_output(ifnet_t, mbuf_t);
99 static errno_t rvi_demux(ifnet_t, mbuf_t, char *, protocol_family_t *);
100 static errno_t rvi_ioctl(ifnet_t, unsigned long, void *);
101 static errno_t rvi_add_proto(ifnet_t, protocol_family_t, const struct ifnet_demux_desc *, uint32_t);
102 static errno_t rvi_del_proto(ifnet_t, protocol_family_t);
103 static errno_t rvi_set_bpf_tap(ifnet_t, uint32_t, bpf_tap_mode);
104 static void rvi_detach(ifnet_t);
105
106 static errno_t rvi_bpf_tap(ifnet_t, mbuf_t, int, struct rvi_client_t *, struct pktap_header *);
107
108 static errno_t rvi_register_control(void);
109 static errno_t rvi_ctl_connect(kern_ctl_ref, struct sockaddr_ctl *, void **);
110 static errno_t rvi_ctl_send(kern_ctl_ref, uint32_t, void *, mbuf_t, int);
111 static errno_t rvi_ctl_disconnect(kern_ctl_ref, uint32_t, void *);
112 static errno_t rvi_ctl_getopt(kern_ctl_ref, uint32_t, void *, int, void *, size_t *);
113
114 int
rvi_init()115 rvi_init()
116 {
117 int error = 0;
118
119 if ((error = rvi_register_control()) != 0) {
120 os_log(OS_LOG_DEFAULT, "rvi_start failed: rvi_register_control failure");
121 return error;
122 }
123
124 return 0;
125 }
126
127 static inline void
rvi_lock_shared(lck_rw_t * mtx)128 rvi_lock_shared(lck_rw_t *mtx)
129 {
130 lck_rw_lock_shared(mtx);
131 }
132
133 static inline void
rvi_lock_exclusive(lck_rw_t * mtx)134 rvi_lock_exclusive(lck_rw_t *mtx)
135 {
136 lck_rw_lock_exclusive(mtx);
137 }
138
139 static inline void
rvi_lock_done_shared(lck_rw_t * mtx)140 rvi_lock_done_shared(lck_rw_t *mtx)
141 {
142 lck_rw_unlock_shared(mtx);
143 }
144
145 static inline void
rvi_lock_done_exclusive(lck_rw_t * mtx)146 rvi_lock_done_exclusive(lck_rw_t *mtx)
147 {
148 lck_rw_unlock_exclusive(mtx);
149 }
150
151 static errno_t
rvi_create_if(struct rvi_client_t * client)152 rvi_create_if(struct rvi_client_t *client)
153 {
154 errno_t err = 0;
155 struct ifnet_init_params rvi_ifinit;
156
157 memset(&rvi_ifinit, 0x0, sizeof(rvi_ifinit));
158 rvi_ifinit.name = RVI_IF_NAME;
159 rvi_ifinit.unit = client->_vif;
160 rvi_ifinit.type = RVI_IF_TYPE;
161 rvi_ifinit.family = RVI_IF_FAMILY;
162 rvi_ifinit.output = rvi_output;
163 rvi_ifinit.demux = rvi_demux;
164 rvi_ifinit.add_proto = rvi_add_proto;
165 rvi_ifinit.del_proto = rvi_del_proto;
166 rvi_ifinit.ioctl = rvi_ioctl;
167 rvi_ifinit.detach = rvi_detach;
168 rvi_ifinit.softc = client;
169
170 err = ifnet_allocate(&rvi_ifinit, &client->_ifp);
171 if (err != 0) {
172 os_log(OS_LOG_DEFAULT, "%s: ifnet_allocate for %s%d failed - %d",
173 __func__, RVI_IF_NAME, client->_vif, err);
174 goto done;
175 }
176
177 ifnet_set_flags(client->_ifp, RVI_IF_FLAGS, RVI_IF_FLAGS);
178
179 err = ifnet_attach(client->_ifp, NULL);
180 if (err != 0) {
181 os_log(OS_LOG_DEFAULT, "%s: ifnet_attach for %s%d failed - %d",
182 __func__, RVI_IF_NAME, client->_vif, err);
183 ifnet_release(client->_ifp);
184 goto done;
185 }
186
187 bpf_attach(client->_ifp, DLT_PKTAP, sizeof(struct pktap_header), NULL,
188 rvi_set_bpf_tap);
189 bpf_attach(client->_ifp, DLT_RAW, 0, NULL, rvi_set_bpf_tap);
190 done:
191 return err;
192 }
193
194 static errno_t
rvi_destroy_if(struct rvi_client_t * client)195 rvi_destroy_if(struct rvi_client_t *client)
196 {
197 errno_t err = 0;
198
199 if (client == NULL) {
200 goto done;
201 }
202
203 err = ifnet_detach(client->_ifp);
204 if (err != 0) {
205 os_log(OS_LOG_DEFAULT, "%s: ifnet_detach for %s%d failed - %d",
206 __func__, RVI_IF_NAME, client->_vif, err);
207 }
208 done:
209 return err;
210 }
211
212 static void
rvi_detach(ifnet_t ifp)213 rvi_detach(ifnet_t ifp)
214 {
215 struct rvi_client_t *client;
216
217 rvi_lock_exclusive(&rvi_mtx);
218
219 client = ifnet_softc(ifp);
220 LIST_REMOVE(client, _cle);
221
222 ifnet_release(ifp);
223
224 rvi_lock_done_exclusive(&rvi_mtx);
225
226 kfree_type(struct rvi_client_t, client);
227 }
228
229 static void
rvi_insert_client(struct rvi_client_t * client)230 rvi_insert_client(struct rvi_client_t *client)
231 {
232 struct rvi_client_t *itr = NULL;
233 uint32_t ph = 0;
234
235 rvi_lock_exclusive(&rvi_mtx);
236
237 if (LIST_EMPTY(&_s_rvi_clients)) {
238 LIST_INSERT_HEAD(&_s_rvi_clients, client, _cle);
239 } else {
240 LIST_FOREACH(itr, &_s_rvi_clients, _cle) {
241 if (ph != itr->_vif) {
242 LIST_INSERT_BEFORE(itr, client, _cle);
243 break;
244 }
245
246 ph++;
247
248 if (LIST_NEXT(itr, _cle) == NULL) {
249 LIST_INSERT_AFTER(itr, client, _cle);
250 break;
251 }
252 }
253 }
254
255 rvi_lock_done_exclusive(&rvi_mtx);
256
257 client->_vif = ph;
258 }
259
260 static void
rvi_remove_client(uint32_t unit)261 rvi_remove_client(uint32_t unit)
262 {
263 struct rvi_client_t *client = NULL;
264
265 rvi_lock_shared(&rvi_mtx);
266
267 LIST_FOREACH(client, &_s_rvi_clients, _cle) {
268 if (client->_unit == unit) {
269 break;
270 }
271 }
272
273 rvi_lock_done_shared(&rvi_mtx);
274
275 if (client == NULL) {
276 panic("rvi_ctl_disconnect: received a disconnect notification without a cache entry");
277 }
278
279 (void)rvi_destroy_if(client);
280 }
281
282
283 static errno_t
rvi_register_control(void)284 rvi_register_control(void)
285 {
286 errno_t err = 0;
287 struct kern_ctl_reg kern_ctl;
288
289 bzero(&kern_ctl, sizeof(kern_ctl));
290 strlcpy(kern_ctl.ctl_name, RVI_CONTROL_NAME, sizeof(kern_ctl.ctl_name));
291 kern_ctl.ctl_name[sizeof(kern_ctl.ctl_name) - 1] = 0;
292 kern_ctl.ctl_flags = CTL_FLAG_PRIVILEGED;
293 kern_ctl.ctl_sendsize = RVI_BUFFERSZ;
294 kern_ctl.ctl_recvsize = RVI_BUFFERSZ;
295 kern_ctl.ctl_connect = rvi_ctl_connect;
296 kern_ctl.ctl_disconnect = rvi_ctl_disconnect;
297 kern_ctl.ctl_send = rvi_ctl_send;
298 kern_ctl.ctl_setopt = NULL;
299 kern_ctl.ctl_getopt = rvi_ctl_getopt;
300
301 err = ctl_register(&kern_ctl, &rvi_kernctl);
302
303 return err;
304 }
305
306 static errno_t
rvi_ctl_connect(kern_ctl_ref kctlref,struct sockaddr_ctl * sac,void ** unitinfo)307 rvi_ctl_connect(kern_ctl_ref kctlref, struct sockaddr_ctl *sac, void **unitinfo)
308 {
309 #pragma unused(kctlref)
310 errno_t err = 0;
311 struct rvi_client_t *client = NULL;
312
313 client = kalloc_type(struct rvi_client_t, Z_WAITOK | Z_ZERO | Z_NOFAIL);
314
315 client->_unit = sac->sc_unit;
316 rvi_insert_client(client);
317
318 err = rvi_create_if(client);
319 if (err != 0) {
320 os_log(OS_LOG_DEFAULT, "%s: failure to create virtual interface %d",
321 __func__, err);
322 }
323 *unitinfo = client;
324
325 return err;
326 }
327
328 static errno_t
rvi_ctl_disconnect(kern_ctl_ref kctlref,uint32_t unit,void * unitinfo)329 rvi_ctl_disconnect(kern_ctl_ref kctlref, uint32_t unit, void *unitinfo)
330 {
331 #pragma unused(kctlref)
332 #pragma unused(unitinfo)
333 errno_t err = 0;
334
335 rvi_remove_client(unit);
336
337 return err;
338 }
339
340 static errno_t
rvi_ctl_getopt(kern_ctl_ref kctlref,uint32_t unit,void * unitinfo,int opt,void * data,size_t * len)341 rvi_ctl_getopt(kern_ctl_ref kctlref, uint32_t unit, void *unitinfo,
342 int opt, void *data, size_t *len)
343 {
344 #pragma unused(kctlref)
345 #pragma unused(unit)
346 errno_t err = 0;
347 int n;
348 struct rvi_client_t *client = (struct rvi_client_t *)unitinfo;
349
350 rvi_lock_shared(&rvi_mtx);
351
352 switch (opt) {
353 case RVI_COMMAND_GET_INTERFACE:
354 if (data == NULL || len == NULL) {
355 err = EINVAL;
356 break;
357 }
358 n = snprintf(data, sizeof(*len), "%s%u", ifnet_name(client->_ifp),
359 ifnet_unit(client->_ifp));
360 *len = n + 1;
361 break;
362
363 case RVI_COMMAND_VERSION:
364 if (data == NULL || len == NULL || *len < sizeof(int)) {
365 err = EINVAL;
366 break;
367 }
368 *(int *)data = RVI_VERSION_CURRENT;
369 *len = sizeof(int);
370 break;
371
372 default:
373 err = ENOPROTOOPT;
374 break;
375 }
376
377 rvi_lock_done_shared(&rvi_mtx);
378
379 return err;
380 }
381
382 static errno_t
rvi_ctl_send(kern_ctl_ref kctlref,uint32_t unit,void * unitinfo,mbuf_t m,int flags)383 rvi_ctl_send(kern_ctl_ref kctlref, uint32_t unit, void *unitinfo, mbuf_t m, int flags)
384 {
385 #pragma unused(kctlref)
386 #pragma unused(unit)
387 #pragma unused(flags)
388 errno_t err = 0;
389 struct rvi_client_t *client = (struct rvi_client_t *)unitinfo;
390 struct pktap_header pktap_hdr;
391 uint32_t hdr_length;
392
393 err = mbuf_copydata(m, 0, sizeof(struct pktap_header), (void *)&pktap_hdr);
394 if (err != 0) {
395 os_log(OS_LOG_DEFAULT, "%s: mbuf_copydata failed %d", __func__, err);
396 goto done;
397 }
398 hdr_length = pktap_hdr.pth_length;
399
400 mbuf_adj(m, hdr_length);
401
402 rvi_lock_shared(&rvi_mtx);
403
404 err = rvi_bpf_tap(client->_ifp, m,
405 pktap_hdr.pth_flags & PTH_FLAG_DIR_OUT ? 1 : 0,
406 client, &pktap_hdr);
407
408 rvi_lock_done_shared(&rvi_mtx);
409 done:
410 mbuf_freem(m);
411 return err;
412 }
413
414 static errno_t
rvi_output(ifnet_t ifp,mbuf_t m)415 rvi_output(ifnet_t ifp, mbuf_t m)
416 {
417 #pragma unused(ifp)
418
419 mbuf_freem(m);
420 return 0;
421 }
422
423 static errno_t
rvi_demux(ifnet_t ifp,mbuf_t m,char * header,protocol_family_t * ppf)424 rvi_demux(ifnet_t ifp, mbuf_t m, char *header, protocol_family_t *ppf)
425 {
426 #pragma unused(ifp)
427 #pragma unused(m)
428 #pragma unused(header)
429 #pragma unused(ppf)
430
431 return ENOTSUP;
432 }
433
434 static errno_t
rvi_add_proto(ifnet_t ifp,protocol_family_t pf,const struct ifnet_demux_desc * dmx,uint32_t cnt)435 rvi_add_proto( ifnet_t ifp, protocol_family_t pf,
436 const struct ifnet_demux_desc *dmx, uint32_t cnt)
437 {
438 #pragma unused(ifp)
439 #pragma unused(pf)
440 #pragma unused(dmx)
441 #pragma unused(cnt)
442
443 return EINVAL;
444 }
445
446 static errno_t
rvi_del_proto(ifnet_t ifp,protocol_family_t pf)447 rvi_del_proto(ifnet_t ifp, protocol_family_t pf)
448 {
449 #pragma unused(ifp)
450 #pragma unused(pf)
451
452 return EINVAL;
453 }
454
455 static errno_t
rvi_ioctl(ifnet_t ifp,unsigned long cmd,void * data)456 rvi_ioctl(ifnet_t ifp, unsigned long cmd, void *data)
457 {
458 #pragma unused(ifp)
459 #pragma unused(cmd)
460 #pragma unused(data)
461
462 return ENOTSUP;
463 }
464
465 static errno_t
rvi_set_bpf_tap(ifnet_t ifp,uint32_t dlt,bpf_tap_mode mode)466 rvi_set_bpf_tap(ifnet_t ifp, uint32_t dlt, bpf_tap_mode mode)
467 {
468 struct rvi_client_t *client;
469
470 rvi_lock_shared(&rvi_mtx);
471
472 client = ifnet_softc(ifp);
473 if (client == NULL) {
474 os_log(OS_LOG_DEFAULT, "%s: ifnet_softc is NULL for ifp %p", __func__, ifp);
475 goto done;
476 }
477 switch (dlt) {
478 case DLT_RAW:
479 if (mode == 0) {
480 if (client->_raw_count > 0) {
481 client->_raw_count--;
482 }
483 } else {
484 client->_raw_count++;
485 }
486 break;
487 case DLT_PKTAP:
488 if (mode == 0) {
489 if (client->_pktap_count > 0) {
490 client->_pktap_count--;
491 }
492 } else {
493 client->_pktap_count++;
494 }
495 break;
496 }
497 done:
498 rvi_lock_done_shared(&rvi_mtx);
499
500 return 0;
501 }
502
503 /*
504 * Note: called with the rvi lock taken as shared
505 */
506 static errno_t
rvi_bpf_tap(ifnet_t ifp,mbuf_t m,int outgoing,struct rvi_client_t * client,struct pktap_header * pktap_hdr)507 rvi_bpf_tap(ifnet_t ifp, mbuf_t m, int outgoing, struct rvi_client_t *client,
508 struct pktap_header *pktap_hdr)
509 {
510 #pragma unused(ifp)
511 errno_t err = 0;
512 void (*bpf_tap_fn)(ifnet_t, uint32_t, mbuf_t, void *, size_t ) =
513 outgoing ? bpf_tap_out : bpf_tap_in;
514
515 if (client->_pktap_count > 0) {
516 bpf_tap_fn(client->_ifp, DLT_PKTAP, m, pktap_hdr,
517 sizeof(struct pktap_header));
518 }
519
520 if (client->_raw_count > 0 &&
521 (pktap_hdr->pth_protocol_family == AF_INET ||
522 pktap_hdr->pth_protocol_family == AF_INET6)) {
523 /*
524 * We can play just with the length of the first mbuf in the
525 * chain because bpf_tap_imp() disregard the packet length
526 * of the mbuf packet header.
527 */
528 if (pktap_hdr->pth_frame_pre_length > mbuf_len(m)) {
529 err = mbuf_pullup(&m, pktap_hdr->pth_frame_pre_length);
530 if (err != 0) {
531 os_log(OS_LOG_DEFAULT, "%s mbuf_pullup failed", __func__);
532 return 0;
533 }
534 }
535
536 if (mbuf_setdata(m, m->m_data + pktap_hdr->pth_frame_pre_length,
537 m->m_len - pktap_hdr->pth_frame_pre_length) == 0) {
538 bpf_tap_fn(client->_ifp, DLT_RAW, m, NULL, 0);
539 mbuf_setdata(m, m->m_data - pktap_hdr->pth_frame_pre_length,
540 m->m_len + pktap_hdr->pth_frame_pre_length);
541 }
542 }
543
544 return err;
545 }
546