xref: /xnu-12377.41.6/bsd/net/remote_vif.c (revision bbb1b6f9e71b8cdde6e5cd6f4841f207dee3d828)
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 	if (err == 0) {
412 		mbuf_freem(m);
413 	}
414 	return err;
415 }
416 
417 static errno_t
rvi_output(ifnet_t ifp,mbuf_t m)418 rvi_output(ifnet_t ifp, mbuf_t m)
419 {
420 #pragma unused(ifp)
421 
422 	mbuf_freem(m);
423 	return 0;
424 }
425 
426 static errno_t
rvi_demux(ifnet_t ifp,mbuf_t m,char * header,protocol_family_t * ppf)427 rvi_demux(ifnet_t ifp, mbuf_t m, char *header, protocol_family_t *ppf)
428 {
429 #pragma unused(ifp)
430 #pragma unused(m)
431 #pragma unused(header)
432 #pragma unused(ppf)
433 
434 	return ENOTSUP;
435 }
436 
437 static errno_t
rvi_add_proto(ifnet_t ifp,protocol_family_t pf,const struct ifnet_demux_desc * dmx,uint32_t cnt)438 rvi_add_proto( ifnet_t ifp, protocol_family_t pf,
439     const struct ifnet_demux_desc *dmx, uint32_t cnt)
440 {
441 #pragma unused(ifp)
442 #pragma unused(pf)
443 #pragma unused(dmx)
444 #pragma unused(cnt)
445 
446 	return EINVAL;
447 }
448 
449 static errno_t
rvi_del_proto(ifnet_t ifp,protocol_family_t pf)450 rvi_del_proto(ifnet_t ifp, protocol_family_t pf)
451 {
452 #pragma unused(ifp)
453 #pragma unused(pf)
454 
455 	return EINVAL;
456 }
457 
458 static errno_t
rvi_ioctl(ifnet_t ifp,unsigned long cmd,void * data)459 rvi_ioctl(ifnet_t ifp, unsigned long cmd, void *data)
460 {
461 #pragma unused(ifp)
462 #pragma unused(cmd)
463 #pragma unused(data)
464 
465 	return ENOTSUP;
466 }
467 
468 static errno_t
rvi_set_bpf_tap(ifnet_t ifp,uint32_t dlt,bpf_tap_mode mode)469 rvi_set_bpf_tap(ifnet_t ifp, uint32_t dlt, bpf_tap_mode mode)
470 {
471 	struct rvi_client_t *__single client;
472 
473 	rvi_lock_shared(&rvi_mtx);
474 
475 	client = ifnet_softc(ifp);
476 	if (client == NULL) {
477 		os_log(OS_LOG_DEFAULT, "%s: ifnet_softc is NULL for ifp %p", __func__, ifp);
478 		goto done;
479 	}
480 	switch (dlt) {
481 	case DLT_RAW:
482 		if (mode == 0) {
483 			if (client->_raw_count > 0) {
484 				client->_raw_count--;
485 			}
486 		} else {
487 			client->_raw_count++;
488 		}
489 		break;
490 	case DLT_PKTAP:
491 		if (mode == 0) {
492 			if (client->_pktap_count > 0) {
493 				client->_pktap_count--;
494 			}
495 		} else {
496 			client->_pktap_count++;
497 		}
498 		break;
499 	}
500 done:
501 	rvi_lock_done_shared(&rvi_mtx);
502 
503 	return 0;
504 }
505 
506 /*
507  * Note: called with the rvi lock taken as shared
508  */
509 static errno_t
rvi_bpf_tap(ifnet_t ifp,mbuf_t m,int outgoing,struct rvi_client_t * client,struct pktap_header * pktap_hdr)510 rvi_bpf_tap(ifnet_t ifp, mbuf_t m, int outgoing, struct rvi_client_t *client,
511     struct pktap_header *pktap_hdr)
512 {
513 #pragma unused(ifp)
514 	errno_t err = 0;
515 	void (*bpf_tap_fn)(ifnet_t, uint32_t, mbuf_t, void *, size_t ) =
516 	    outgoing ? bpf_tap_out : bpf_tap_in;
517 
518 	if (client->_pktap_count > 0) {
519 		bpf_tap_fn(client->_ifp, DLT_PKTAP, m, pktap_hdr,
520 		    sizeof(struct pktap_header));
521 	}
522 
523 	if (client->_raw_count > 0 &&
524 	    (pktap_hdr->pth_protocol_family == AF_INET ||
525 	    pktap_hdr->pth_protocol_family == AF_INET6)) {
526 		/*
527 		 * We can play just with the length of the first mbuf in the
528 		 * chain because bpf_tap_imp() disregard the packet length
529 		 * of the mbuf packet header.
530 		 */
531 		if (pktap_hdr->pth_frame_pre_length > mbuf_len(m)) {
532 			err = mbuf_pullup(&m, pktap_hdr->pth_frame_pre_length);
533 			if (err != 0) {
534 				os_log_error(OS_LOG_DEFAULT, "%s mbuf_pullup failed", __func__);
535 				return err;
536 			}
537 		}
538 
539 		if (mbuf_setdata(m, m_mtod_current(m) + pktap_hdr->pth_frame_pre_length,
540 		    m->m_len - pktap_hdr->pth_frame_pre_length) == 0) {
541 			bpf_tap_fn(client->_ifp, DLT_RAW, m, NULL, 0);
542 			mbuf_setdata(m, m_mtod_current(m) - pktap_hdr->pth_frame_pre_length,
543 			    m->m_len + pktap_hdr->pth_frame_pre_length);
544 		}
545 	}
546 
547 	return err;
548 }
549