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