xref: /xnu-11417.140.69/bsd/net/remote_vif.c (revision 43a90889846e00bfb5cf1d255cdc0a701a1e05a4)
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 *__sized_by(*len), size_t *len);
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 *__single 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 *__single 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 *__single 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 *__single 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 * __sized_by (* len)data,size_t * len)341 rvi_ctl_getopt(kern_ctl_ref kctlref, uint32_t unit, void *unitinfo,
342     int opt, void *__sized_by(*len) 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 *__single 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 = scnprintf(data, *len, "%s%u", ifnet_name(client->_ifp),
359 		    ifnet_unit(client->_ifp));
360 
361 		*len = n + 1;
362 		break;
363 
364 	case RVI_COMMAND_VERSION:
365 		if (data == NULL || len == NULL || *len < sizeof(int)) {
366 			err = EINVAL;
367 			break;
368 		}
369 		*(int *)data = RVI_VERSION_CURRENT;
370 		*len = sizeof(int);
371 		break;
372 
373 	default:
374 		err = ENOPROTOOPT;
375 		break;
376 	}
377 
378 	rvi_lock_done_shared(&rvi_mtx);
379 
380 	return err;
381 }
382 
383 static errno_t
rvi_ctl_send(kern_ctl_ref kctlref,uint32_t unit,void * unitinfo,mbuf_t m,int flags)384 rvi_ctl_send(kern_ctl_ref kctlref, uint32_t unit, void *unitinfo, mbuf_t m, int flags)
385 {
386 #pragma unused(kctlref)
387 #pragma unused(unit)
388 #pragma unused(flags)
389 	errno_t err = 0;
390 	struct rvi_client_t *__single client = (struct rvi_client_t *)unitinfo;
391 	struct pktap_header pktap_hdr;
392 	uint32_t hdr_length;
393 
394 	err = mbuf_copydata(m, 0, sizeof(struct pktap_header), (void *)&pktap_hdr);
395 	if (err != 0) {
396 		os_log(OS_LOG_DEFAULT, "%s: mbuf_copydata failed %d", __func__, err);
397 		goto done;
398 	}
399 	hdr_length = pktap_hdr.pth_length;
400 
401 	mbuf_adj(m, hdr_length);
402 
403 	rvi_lock_shared(&rvi_mtx);
404 
405 	err = rvi_bpf_tap(client->_ifp, m,
406 	    pktap_hdr.pth_flags & PTH_FLAG_DIR_OUT ? 1 : 0,
407 	    client, &pktap_hdr);
408 
409 	rvi_lock_done_shared(&rvi_mtx);
410 done:
411 	mbuf_freem(m);
412 	return err;
413 }
414 
415 static errno_t
rvi_output(ifnet_t ifp,mbuf_t m)416 rvi_output(ifnet_t ifp, mbuf_t m)
417 {
418 #pragma unused(ifp)
419 
420 	mbuf_freem(m);
421 	return 0;
422 }
423 
424 static errno_t
rvi_demux(ifnet_t ifp,mbuf_t m,char * header,protocol_family_t * ppf)425 rvi_demux(ifnet_t ifp, mbuf_t m, char *header, protocol_family_t *ppf)
426 {
427 #pragma unused(ifp)
428 #pragma unused(m)
429 #pragma unused(header)
430 #pragma unused(ppf)
431 
432 	return ENOTSUP;
433 }
434 
435 static errno_t
rvi_add_proto(ifnet_t ifp,protocol_family_t pf,const struct ifnet_demux_desc * dmx,uint32_t cnt)436 rvi_add_proto( ifnet_t ifp, protocol_family_t pf,
437     const struct ifnet_demux_desc *dmx, uint32_t cnt)
438 {
439 #pragma unused(ifp)
440 #pragma unused(pf)
441 #pragma unused(dmx)
442 #pragma unused(cnt)
443 
444 	return EINVAL;
445 }
446 
447 static errno_t
rvi_del_proto(ifnet_t ifp,protocol_family_t pf)448 rvi_del_proto(ifnet_t ifp, protocol_family_t pf)
449 {
450 #pragma unused(ifp)
451 #pragma unused(pf)
452 
453 	return EINVAL;
454 }
455 
456 static errno_t
rvi_ioctl(ifnet_t ifp,unsigned long cmd,void * data)457 rvi_ioctl(ifnet_t ifp, unsigned long cmd, void *data)
458 {
459 #pragma unused(ifp)
460 #pragma unused(cmd)
461 #pragma unused(data)
462 
463 	return ENOTSUP;
464 }
465 
466 static errno_t
rvi_set_bpf_tap(ifnet_t ifp,uint32_t dlt,bpf_tap_mode mode)467 rvi_set_bpf_tap(ifnet_t ifp, uint32_t dlt, bpf_tap_mode mode)
468 {
469 	struct rvi_client_t *__single client;
470 
471 	rvi_lock_shared(&rvi_mtx);
472 
473 	client = ifnet_softc(ifp);
474 	if (client == NULL) {
475 		os_log(OS_LOG_DEFAULT, "%s: ifnet_softc is NULL for ifp %p", __func__, ifp);
476 		goto done;
477 	}
478 	switch (dlt) {
479 	case DLT_RAW:
480 		if (mode == 0) {
481 			if (client->_raw_count > 0) {
482 				client->_raw_count--;
483 			}
484 		} else {
485 			client->_raw_count++;
486 		}
487 		break;
488 	case DLT_PKTAP:
489 		if (mode == 0) {
490 			if (client->_pktap_count > 0) {
491 				client->_pktap_count--;
492 			}
493 		} else {
494 			client->_pktap_count++;
495 		}
496 		break;
497 	}
498 done:
499 	rvi_lock_done_shared(&rvi_mtx);
500 
501 	return 0;
502 }
503 
504 /*
505  * Note: called with the rvi lock taken as shared
506  */
507 static errno_t
rvi_bpf_tap(ifnet_t ifp,mbuf_t m,int outgoing,struct rvi_client_t * client,struct pktap_header * pktap_hdr)508 rvi_bpf_tap(ifnet_t ifp, mbuf_t m, int outgoing, struct rvi_client_t *client,
509     struct pktap_header *pktap_hdr)
510 {
511 #pragma unused(ifp)
512 	errno_t err = 0;
513 	void (*bpf_tap_fn)(ifnet_t, uint32_t, mbuf_t, void *, size_t ) =
514 	    outgoing ? bpf_tap_out : bpf_tap_in;
515 
516 	if (client->_pktap_count > 0) {
517 		bpf_tap_fn(client->_ifp, DLT_PKTAP, m, pktap_hdr,
518 		    sizeof(struct pktap_header));
519 	}
520 
521 	if (client->_raw_count > 0 &&
522 	    (pktap_hdr->pth_protocol_family == AF_INET ||
523 	    pktap_hdr->pth_protocol_family == AF_INET6)) {
524 		/*
525 		 * We can play just with the length of the first mbuf in the
526 		 * chain because bpf_tap_imp() disregard the packet length
527 		 * of the mbuf packet header.
528 		 */
529 		if (pktap_hdr->pth_frame_pre_length > mbuf_len(m)) {
530 			err = mbuf_pullup(&m, pktap_hdr->pth_frame_pre_length);
531 			if (err != 0) {
532 				os_log(OS_LOG_DEFAULT, "%s mbuf_pullup failed", __func__);
533 				return 0;
534 			}
535 		}
536 
537 		if (mbuf_setdata(m, m_mtod_current(m) + pktap_hdr->pth_frame_pre_length,
538 		    m->m_len - pktap_hdr->pth_frame_pre_length) == 0) {
539 			bpf_tap_fn(client->_ifp, DLT_RAW, m, NULL, 0);
540 			mbuf_setdata(m, m_mtod_current(m) - pktap_hdr->pth_frame_pre_length,
541 			    m->m_len + pktap_hdr->pth_frame_pre_length);
542 		}
543 	}
544 
545 	return err;
546 }
547