xref: /xnu-12377.41.6/bsd/net/iptap.c (revision bbb1b6f9e71b8cdde6e5cd6f4841f207dee3d828)
1*bbb1b6f9SApple OSS Distributions /*
2*bbb1b6f9SApple OSS Distributions  * Copyright (c) 1999-2018 Apple Inc. All rights reserved.
3*bbb1b6f9SApple OSS Distributions  *
4*bbb1b6f9SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*bbb1b6f9SApple OSS Distributions  *
6*bbb1b6f9SApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*bbb1b6f9SApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*bbb1b6f9SApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*bbb1b6f9SApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*bbb1b6f9SApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*bbb1b6f9SApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*bbb1b6f9SApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*bbb1b6f9SApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*bbb1b6f9SApple OSS Distributions  *
15*bbb1b6f9SApple OSS Distributions  * Please obtain a copy of the License at
16*bbb1b6f9SApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*bbb1b6f9SApple OSS Distributions  *
18*bbb1b6f9SApple OSS Distributions  * The Original Code and all software distributed under the License are
19*bbb1b6f9SApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*bbb1b6f9SApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*bbb1b6f9SApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*bbb1b6f9SApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*bbb1b6f9SApple OSS Distributions  * Please see the License for the specific language governing rights and
24*bbb1b6f9SApple OSS Distributions  * limitations under the License.
25*bbb1b6f9SApple OSS Distributions  *
26*bbb1b6f9SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*bbb1b6f9SApple OSS Distributions  */
28*bbb1b6f9SApple OSS Distributions 
29*bbb1b6f9SApple OSS Distributions #include <kern/locks.h>
30*bbb1b6f9SApple OSS Distributions #include <kern/zalloc.h>
31*bbb1b6f9SApple OSS Distributions 
32*bbb1b6f9SApple OSS Distributions #include <sys/types.h>
33*bbb1b6f9SApple OSS Distributions #include <sys/kernel_types.h>
34*bbb1b6f9SApple OSS Distributions #include <sys/kauth.h>
35*bbb1b6f9SApple OSS Distributions #include <sys/socket.h>
36*bbb1b6f9SApple OSS Distributions #include <sys/socketvar.h>
37*bbb1b6f9SApple OSS Distributions #include <sys/sockio.h>
38*bbb1b6f9SApple OSS Distributions #include <sys/sysctl.h>
39*bbb1b6f9SApple OSS Distributions #include <sys/proc.h>
40*bbb1b6f9SApple OSS Distributions 
41*bbb1b6f9SApple OSS Distributions #include <net/if.h>
42*bbb1b6f9SApple OSS Distributions #include <net/if_var.h>
43*bbb1b6f9SApple OSS Distributions #include <net/if_types.h>
44*bbb1b6f9SApple OSS Distributions #include <net/bpf.h>
45*bbb1b6f9SApple OSS Distributions #include <net/net_osdep.h>
46*bbb1b6f9SApple OSS Distributions #include <net/pktap.h>
47*bbb1b6f9SApple OSS Distributions #include <net/iptap.h>
48*bbb1b6f9SApple OSS Distributions 
49*bbb1b6f9SApple OSS Distributions #include <netinet/in_pcb.h>
50*bbb1b6f9SApple OSS Distributions #include <netinet/tcp.h>
51*bbb1b6f9SApple OSS Distributions #include <netinet/tcp_var.h>
52*bbb1b6f9SApple OSS Distributions #define _IP_VHL
53*bbb1b6f9SApple OSS Distributions #include <netinet/ip.h>
54*bbb1b6f9SApple OSS Distributions #include <netinet/ip_var.h>
55*bbb1b6f9SApple OSS Distributions #include <netinet/udp.h>
56*bbb1b6f9SApple OSS Distributions #include <netinet/udp_var.h>
57*bbb1b6f9SApple OSS Distributions 
58*bbb1b6f9SApple OSS Distributions #include <netinet/ip6.h>
59*bbb1b6f9SApple OSS Distributions #include <netinet6/in6_pcb.h>
60*bbb1b6f9SApple OSS Distributions 
61*bbb1b6f9SApple OSS Distributions #include <netinet/kpi_ipfilter.h>
62*bbb1b6f9SApple OSS Distributions 
63*bbb1b6f9SApple OSS Distributions #include <libkern/OSAtomic.h>
64*bbb1b6f9SApple OSS Distributions 
65*bbb1b6f9SApple OSS Distributions #include <kern/debug.h>
66*bbb1b6f9SApple OSS Distributions 
67*bbb1b6f9SApple OSS Distributions #include <sys/mcache.h>
68*bbb1b6f9SApple OSS Distributions 
69*bbb1b6f9SApple OSS Distributions #include <string.h>
70*bbb1b6f9SApple OSS Distributions 
71*bbb1b6f9SApple OSS Distributions struct iptap_softc {
72*bbb1b6f9SApple OSS Distributions 	LIST_ENTRY(iptap_softc)         iptap_link;
73*bbb1b6f9SApple OSS Distributions 	uint32_t                                        iptap_unit;
74*bbb1b6f9SApple OSS Distributions 	uint32_t                                        iptap_dlt_raw_count;
75*bbb1b6f9SApple OSS Distributions 	uint32_t                                        iptap_dlt_pkttap_count;
76*bbb1b6f9SApple OSS Distributions 	struct ifnet                            *iptap_ifp;
77*bbb1b6f9SApple OSS Distributions };
78*bbb1b6f9SApple OSS Distributions 
79*bbb1b6f9SApple OSS Distributions static LIST_HEAD(iptap_list, iptap_softc) iptap_list = LIST_HEAD_INITIALIZER(iptap_list);
80*bbb1b6f9SApple OSS Distributions 
81*bbb1b6f9SApple OSS Distributions static void             iptap_lock_shared(void);
82*bbb1b6f9SApple OSS Distributions static void             iptap_lock_exclusive(void);
83*bbb1b6f9SApple OSS Distributions static void             iptap_lock_done(void);
84*bbb1b6f9SApple OSS Distributions 
85*bbb1b6f9SApple OSS Distributions static LCK_GRP_DECLARE(iptap_grp, "IPTAP_IFNAME");
86*bbb1b6f9SApple OSS Distributions static LCK_RW_DECLARE(iptap_lck_rw, &iptap_grp);
87*bbb1b6f9SApple OSS Distributions 
88*bbb1b6f9SApple OSS Distributions errno_t iptap_if_output(ifnet_t, mbuf_t);
89*bbb1b6f9SApple OSS Distributions errno_t iptap_demux(ifnet_t, mbuf_t, char *, protocol_family_t *);
90*bbb1b6f9SApple OSS Distributions errno_t iptap_add_proto(ifnet_t, protocol_family_t, const struct ifnet_demux_desc *,
91*bbb1b6f9SApple OSS Distributions     u_int32_t);
92*bbb1b6f9SApple OSS Distributions errno_t iptap_del_proto(ifnet_t, protocol_family_t);
93*bbb1b6f9SApple OSS Distributions errno_t iptap_getdrvspec(ifnet_t, struct ifdrv64 *);
94*bbb1b6f9SApple OSS Distributions errno_t iptap_ioctl(ifnet_t, unsigned long cmd, void *__sized_by(IOCPARM_LEN(cmd)));
95*bbb1b6f9SApple OSS Distributions void iptap_detach(ifnet_t);
96*bbb1b6f9SApple OSS Distributions errno_t iptap_tap_callback(ifnet_t, u_int32_t, bpf_tap_mode );
97*bbb1b6f9SApple OSS Distributions int iptap_clone_create(struct if_clone *, u_int32_t, void *);
98*bbb1b6f9SApple OSS Distributions int iptap_clone_destroy(struct ifnet *);
99*bbb1b6f9SApple OSS Distributions 
100*bbb1b6f9SApple OSS Distributions static int iptap_ipf_register(void);
101*bbb1b6f9SApple OSS Distributions static int iptap_ipf_unregister(void);
102*bbb1b6f9SApple OSS Distributions static errno_t iptap_ipf_input(void *, mbuf_t *, int, u_int8_t);
103*bbb1b6f9SApple OSS Distributions static errno_t iptap_ipf_output(void *, mbuf_t *, ipf_pktopts_t);
104*bbb1b6f9SApple OSS Distributions static void iptap_ipf_detach(void *);
105*bbb1b6f9SApple OSS Distributions 
106*bbb1b6f9SApple OSS Distributions static ipfilter_t iptap_ipf4, iptap_ipf6;
107*bbb1b6f9SApple OSS Distributions 
108*bbb1b6f9SApple OSS Distributions void iptap_bpf_tap(struct mbuf *m, u_int32_t proto, int outgoing);
109*bbb1b6f9SApple OSS Distributions 
110*bbb1b6f9SApple OSS Distributions #define IPTAP_MAXUNIT   IF_MAXUNIT
111*bbb1b6f9SApple OSS Distributions #define IPTAP_ZONE_MAX_ELEM     MIN(IFNETS_MAX, IPTAP_MAXUNIT)
112*bbb1b6f9SApple OSS Distributions 
113*bbb1b6f9SApple OSS Distributions static struct if_clone iptap_cloner =
114*bbb1b6f9SApple OSS Distributions     IF_CLONE_INITIALIZER(IPTAP_IFNAME,
115*bbb1b6f9SApple OSS Distributions     iptap_clone_create,
116*bbb1b6f9SApple OSS Distributions     iptap_clone_destroy,
117*bbb1b6f9SApple OSS Distributions     0,
118*bbb1b6f9SApple OSS Distributions     IPTAP_MAXUNIT);
119*bbb1b6f9SApple OSS Distributions 
120*bbb1b6f9SApple OSS Distributions SYSCTL_DECL(_net_link);
121*bbb1b6f9SApple OSS Distributions SYSCTL_NODE(_net_link, OID_AUTO, iptap, CTLFLAG_RW | CTLFLAG_LOCKED, 0,
122*bbb1b6f9SApple OSS Distributions     "iptap virtual interface");
123*bbb1b6f9SApple OSS Distributions 
124*bbb1b6f9SApple OSS Distributions static int iptap_total_tap_count = 0;
125*bbb1b6f9SApple OSS Distributions SYSCTL_INT(_net_link_iptap, OID_AUTO, total_tap_count, CTLFLAG_RD | CTLFLAG_LOCKED,
126*bbb1b6f9SApple OSS Distributions     &iptap_total_tap_count, 0, "");
127*bbb1b6f9SApple OSS Distributions 
128*bbb1b6f9SApple OSS Distributions static int iptap_log = 0;
129*bbb1b6f9SApple OSS Distributions SYSCTL_INT(_net_link_iptap, OID_AUTO, log, CTLFLAG_RW | CTLFLAG_LOCKED,
130*bbb1b6f9SApple OSS Distributions     &iptap_log, 0, "");
131*bbb1b6f9SApple OSS Distributions 
132*bbb1b6f9SApple OSS Distributions #define IPTAP_LOG(fmt, ...) \
133*bbb1b6f9SApple OSS Distributions do { \
134*bbb1b6f9SApple OSS Distributions     if ((iptap_log)) \
135*bbb1b6f9SApple OSS Distributions 	printf("%s:%d " fmt, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
136*bbb1b6f9SApple OSS Distributions } while(false)
137*bbb1b6f9SApple OSS Distributions 
138*bbb1b6f9SApple OSS Distributions __private_extern__ void
iptap_init(void)139*bbb1b6f9SApple OSS Distributions iptap_init(void)
140*bbb1b6f9SApple OSS Distributions {
141*bbb1b6f9SApple OSS Distributions 	errno_t error;
142*bbb1b6f9SApple OSS Distributions 
143*bbb1b6f9SApple OSS Distributions 	error = if_clone_attach(&iptap_cloner);
144*bbb1b6f9SApple OSS Distributions 	if (error != 0) {
145*bbb1b6f9SApple OSS Distributions 		panic("%s: if_clone_attach() failed, error %d", __func__, error);
146*bbb1b6f9SApple OSS Distributions 	}
147*bbb1b6f9SApple OSS Distributions }
148*bbb1b6f9SApple OSS Distributions 
149*bbb1b6f9SApple OSS Distributions static void
iptap_lock_shared(void)150*bbb1b6f9SApple OSS Distributions iptap_lock_shared(void)
151*bbb1b6f9SApple OSS Distributions {
152*bbb1b6f9SApple OSS Distributions 	lck_rw_lock_shared(&iptap_lck_rw);
153*bbb1b6f9SApple OSS Distributions }
154*bbb1b6f9SApple OSS Distributions 
155*bbb1b6f9SApple OSS Distributions static void
iptap_lock_exclusive(void)156*bbb1b6f9SApple OSS Distributions iptap_lock_exclusive(void)
157*bbb1b6f9SApple OSS Distributions {
158*bbb1b6f9SApple OSS Distributions 	lck_rw_lock_exclusive(&iptap_lck_rw);
159*bbb1b6f9SApple OSS Distributions }
160*bbb1b6f9SApple OSS Distributions 
161*bbb1b6f9SApple OSS Distributions static void
iptap_lock_done(void)162*bbb1b6f9SApple OSS Distributions iptap_lock_done(void)
163*bbb1b6f9SApple OSS Distributions {
164*bbb1b6f9SApple OSS Distributions 	lck_rw_done(&iptap_lck_rw);
165*bbb1b6f9SApple OSS Distributions }
166*bbb1b6f9SApple OSS Distributions 
167*bbb1b6f9SApple OSS Distributions __private_extern__ int
iptap_clone_create(struct if_clone * ifc,u_int32_t unit,void * params)168*bbb1b6f9SApple OSS Distributions iptap_clone_create(struct if_clone *ifc, u_int32_t unit, void *params)
169*bbb1b6f9SApple OSS Distributions {
170*bbb1b6f9SApple OSS Distributions #pragma unused(params)
171*bbb1b6f9SApple OSS Distributions 
172*bbb1b6f9SApple OSS Distributions 	int error = 0;
173*bbb1b6f9SApple OSS Distributions 	struct iptap_softc *__single iptap = NULL;
174*bbb1b6f9SApple OSS Distributions 	struct ifnet_init_eparams if_init;
175*bbb1b6f9SApple OSS Distributions 
176*bbb1b6f9SApple OSS Distributions 	iptap = kalloc_type(struct iptap_softc, Z_WAITOK_ZERO_NOFAIL);
177*bbb1b6f9SApple OSS Distributions 	iptap->iptap_unit = unit;
178*bbb1b6f9SApple OSS Distributions 
179*bbb1b6f9SApple OSS Distributions 	/*
180*bbb1b6f9SApple OSS Distributions 	 * We do not use a set_bpf_tap() function as we rather rely on the more
181*bbb1b6f9SApple OSS Distributions 	 * accurate callback passed to bpf_attach()
182*bbb1b6f9SApple OSS Distributions 	 */
183*bbb1b6f9SApple OSS Distributions 	bzero(&if_init, sizeof(if_init));
184*bbb1b6f9SApple OSS Distributions 	if_init.ver = IFNET_INIT_CURRENT_VERSION;
185*bbb1b6f9SApple OSS Distributions 	if_init.len = sizeof(if_init);
186*bbb1b6f9SApple OSS Distributions 	if_init.flags = IFNET_INIT_LEGACY;
187*bbb1b6f9SApple OSS Distributions 	if_init.name = __unsafe_null_terminated_from_indexable(ifc->ifc_name);
188*bbb1b6f9SApple OSS Distributions 	if_init.unit = unit;
189*bbb1b6f9SApple OSS Distributions 	if_init.type = IFT_OTHER;
190*bbb1b6f9SApple OSS Distributions 	if_init.family = IFNET_FAMILY_LOOPBACK;
191*bbb1b6f9SApple OSS Distributions 	if_init.output = iptap_if_output;
192*bbb1b6f9SApple OSS Distributions 	if_init.demux = iptap_demux;
193*bbb1b6f9SApple OSS Distributions 	if_init.add_proto = iptap_add_proto;
194*bbb1b6f9SApple OSS Distributions 	if_init.del_proto = iptap_del_proto;
195*bbb1b6f9SApple OSS Distributions 	if_init.softc = iptap;
196*bbb1b6f9SApple OSS Distributions 	if_init.ioctl = iptap_ioctl;
197*bbb1b6f9SApple OSS Distributions 	if_init.detach = iptap_detach;
198*bbb1b6f9SApple OSS Distributions 
199*bbb1b6f9SApple OSS Distributions 	error = ifnet_allocate_extended(&if_init, &iptap->iptap_ifp);
200*bbb1b6f9SApple OSS Distributions 	if (error != 0) {
201*bbb1b6f9SApple OSS Distributions 		printf("%s: ifnet_allocate failed, error %d\n", __func__, error);
202*bbb1b6f9SApple OSS Distributions 		goto done;
203*bbb1b6f9SApple OSS Distributions 	}
204*bbb1b6f9SApple OSS Distributions 
205*bbb1b6f9SApple OSS Distributions 	ifnet_set_flags(iptap->iptap_ifp, IFF_UP, IFF_UP);
206*bbb1b6f9SApple OSS Distributions 
207*bbb1b6f9SApple OSS Distributions 	error = ifnet_attach(iptap->iptap_ifp, NULL);
208*bbb1b6f9SApple OSS Distributions 	if (error != 0) {
209*bbb1b6f9SApple OSS Distributions 		printf("%s: ifnet_attach failed - error %d\n", __func__, error);
210*bbb1b6f9SApple OSS Distributions 		ifnet_release(iptap->iptap_ifp);
211*bbb1b6f9SApple OSS Distributions 		goto done;
212*bbb1b6f9SApple OSS Distributions 	}
213*bbb1b6f9SApple OSS Distributions 
214*bbb1b6f9SApple OSS Distributions 	/*
215*bbb1b6f9SApple OSS Distributions 	 * Attach by default as DLT_PKTAP for packet metadata
216*bbb1b6f9SApple OSS Distributions 	 * Provide DLT_RAW for legacy
217*bbb1b6f9SApple OSS Distributions 	 */
218*bbb1b6f9SApple OSS Distributions 	bpf_attach(iptap->iptap_ifp, DLT_PKTAP, sizeof(struct pktap_header), NULL,
219*bbb1b6f9SApple OSS Distributions 	    iptap_tap_callback);
220*bbb1b6f9SApple OSS Distributions 	bpf_attach(iptap->iptap_ifp, DLT_RAW, 0, NULL,
221*bbb1b6f9SApple OSS Distributions 	    iptap_tap_callback);
222*bbb1b6f9SApple OSS Distributions 
223*bbb1b6f9SApple OSS Distributions 	/* Take a reference and add to the global list */
224*bbb1b6f9SApple OSS Distributions 	ifnet_reference(iptap->iptap_ifp);
225*bbb1b6f9SApple OSS Distributions 
226*bbb1b6f9SApple OSS Distributions 	iptap_lock_exclusive();
227*bbb1b6f9SApple OSS Distributions 
228*bbb1b6f9SApple OSS Distributions 	if (LIST_EMPTY(&iptap_list)) {
229*bbb1b6f9SApple OSS Distributions 		iptap_ipf_register();
230*bbb1b6f9SApple OSS Distributions 	}
231*bbb1b6f9SApple OSS Distributions 	LIST_INSERT_HEAD(&iptap_list, iptap, iptap_link);
232*bbb1b6f9SApple OSS Distributions 	iptap_lock_done();
233*bbb1b6f9SApple OSS Distributions done:
234*bbb1b6f9SApple OSS Distributions 	if (error != 0 && iptap != NULL) {
235*bbb1b6f9SApple OSS Distributions 		kfree_type(struct iptap_softc, iptap);
236*bbb1b6f9SApple OSS Distributions 	}
237*bbb1b6f9SApple OSS Distributions 	return error;
238*bbb1b6f9SApple OSS Distributions }
239*bbb1b6f9SApple OSS Distributions 
240*bbb1b6f9SApple OSS Distributions __private_extern__ int
iptap_clone_destroy(struct ifnet * ifp)241*bbb1b6f9SApple OSS Distributions iptap_clone_destroy(struct ifnet *ifp)
242*bbb1b6f9SApple OSS Distributions {
243*bbb1b6f9SApple OSS Distributions 	int error = 0;
244*bbb1b6f9SApple OSS Distributions 
245*bbb1b6f9SApple OSS Distributions 	(void) ifnet_detach(ifp);
246*bbb1b6f9SApple OSS Distributions 
247*bbb1b6f9SApple OSS Distributions 	return error;
248*bbb1b6f9SApple OSS Distributions }
249*bbb1b6f9SApple OSS Distributions 
250*bbb1b6f9SApple OSS Distributions /*
251*bbb1b6f9SApple OSS Distributions  * This function is called whenever a DLT is set on the interface:
252*bbb1b6f9SApple OSS Distributions  * - When interface is attached to a BPF device via BIOCSETIF for the default DLT
253*bbb1b6f9SApple OSS Distributions  * - Whenever a new DLT is selected via BIOCSDLT
254*bbb1b6f9SApple OSS Distributions  * - When the interface is detached from a BPF device (direction is zero)
255*bbb1b6f9SApple OSS Distributions  */
256*bbb1b6f9SApple OSS Distributions __private_extern__ errno_t
iptap_tap_callback(ifnet_t ifp,u_int32_t dlt,bpf_tap_mode direction)257*bbb1b6f9SApple OSS Distributions iptap_tap_callback(ifnet_t ifp, u_int32_t dlt, bpf_tap_mode direction)
258*bbb1b6f9SApple OSS Distributions {
259*bbb1b6f9SApple OSS Distributions 	struct iptap_softc *__single iptap;
260*bbb1b6f9SApple OSS Distributions 
261*bbb1b6f9SApple OSS Distributions 	iptap = ifp->if_softc;
262*bbb1b6f9SApple OSS Distributions 	if (iptap == NULL) {
263*bbb1b6f9SApple OSS Distributions 		printf("%s: if_softc is NULL for ifp %s\n", __func__,
264*bbb1b6f9SApple OSS Distributions 		    ifp->if_xname);
265*bbb1b6f9SApple OSS Distributions 		goto done;
266*bbb1b6f9SApple OSS Distributions 	}
267*bbb1b6f9SApple OSS Distributions 	switch (dlt) {
268*bbb1b6f9SApple OSS Distributions 	case DLT_RAW:
269*bbb1b6f9SApple OSS Distributions 		if (direction == 0) {
270*bbb1b6f9SApple OSS Distributions 			if (iptap->iptap_dlt_raw_count > 0) {
271*bbb1b6f9SApple OSS Distributions 				iptap->iptap_dlt_raw_count--;
272*bbb1b6f9SApple OSS Distributions 				OSAddAtomic(-1, &iptap_total_tap_count);
273*bbb1b6f9SApple OSS Distributions 			}
274*bbb1b6f9SApple OSS Distributions 		} else {
275*bbb1b6f9SApple OSS Distributions 			iptap->iptap_dlt_raw_count++;
276*bbb1b6f9SApple OSS Distributions 			OSAddAtomic(1, &iptap_total_tap_count);
277*bbb1b6f9SApple OSS Distributions 		}
278*bbb1b6f9SApple OSS Distributions 		break;
279*bbb1b6f9SApple OSS Distributions 	case DLT_PKTAP:
280*bbb1b6f9SApple OSS Distributions 		if (direction == 0) {
281*bbb1b6f9SApple OSS Distributions 			if (iptap->iptap_dlt_pkttap_count > 0) {
282*bbb1b6f9SApple OSS Distributions 				iptap->iptap_dlt_pkttap_count--;
283*bbb1b6f9SApple OSS Distributions 				OSAddAtomic(-1, &iptap_total_tap_count);
284*bbb1b6f9SApple OSS Distributions 			}
285*bbb1b6f9SApple OSS Distributions 		} else {
286*bbb1b6f9SApple OSS Distributions 			iptap->iptap_dlt_pkttap_count++;
287*bbb1b6f9SApple OSS Distributions 			OSAddAtomic(1, &iptap_total_tap_count);
288*bbb1b6f9SApple OSS Distributions 		}
289*bbb1b6f9SApple OSS Distributions 		break;
290*bbb1b6f9SApple OSS Distributions 	}
291*bbb1b6f9SApple OSS Distributions done:
292*bbb1b6f9SApple OSS Distributions 	/*
293*bbb1b6f9SApple OSS Distributions 	 * Attachements count must be positive and we're in trouble
294*bbb1b6f9SApple OSS Distributions 	 * if we have more that 2**31 attachements
295*bbb1b6f9SApple OSS Distributions 	 */
296*bbb1b6f9SApple OSS Distributions 	VERIFY(iptap_total_tap_count >= 0);
297*bbb1b6f9SApple OSS Distributions 
298*bbb1b6f9SApple OSS Distributions 	return 0;
299*bbb1b6f9SApple OSS Distributions }
300*bbb1b6f9SApple OSS Distributions 
301*bbb1b6f9SApple OSS Distributions __private_extern__ errno_t
iptap_if_output(ifnet_t ifp,mbuf_t m)302*bbb1b6f9SApple OSS Distributions iptap_if_output(ifnet_t ifp, mbuf_t m)
303*bbb1b6f9SApple OSS Distributions {
304*bbb1b6f9SApple OSS Distributions #pragma unused(ifp)
305*bbb1b6f9SApple OSS Distributions 
306*bbb1b6f9SApple OSS Distributions 	mbuf_freem(m);
307*bbb1b6f9SApple OSS Distributions 	return ENOTSUP;
308*bbb1b6f9SApple OSS Distributions }
309*bbb1b6f9SApple OSS Distributions 
310*bbb1b6f9SApple OSS Distributions __private_extern__ errno_t
iptap_demux(ifnet_t ifp,mbuf_t m,char * header,protocol_family_t * ppf)311*bbb1b6f9SApple OSS Distributions iptap_demux(ifnet_t ifp, mbuf_t m, char *header,
312*bbb1b6f9SApple OSS Distributions     protocol_family_t *ppf)
313*bbb1b6f9SApple OSS Distributions {
314*bbb1b6f9SApple OSS Distributions #pragma unused(ifp)
315*bbb1b6f9SApple OSS Distributions #pragma unused(m)
316*bbb1b6f9SApple OSS Distributions #pragma unused(header)
317*bbb1b6f9SApple OSS Distributions #pragma unused(ppf)
318*bbb1b6f9SApple OSS Distributions 
319*bbb1b6f9SApple OSS Distributions 	return ENOTSUP;
320*bbb1b6f9SApple OSS Distributions }
321*bbb1b6f9SApple OSS Distributions 
322*bbb1b6f9SApple OSS Distributions __private_extern__ errno_t
iptap_add_proto(ifnet_t ifp,protocol_family_t pf,const struct ifnet_demux_desc * dmx,u_int32_t cnt)323*bbb1b6f9SApple OSS Distributions iptap_add_proto(ifnet_t ifp, protocol_family_t pf,
324*bbb1b6f9SApple OSS Distributions     const struct ifnet_demux_desc *dmx, u_int32_t cnt)
325*bbb1b6f9SApple OSS Distributions {
326*bbb1b6f9SApple OSS Distributions #pragma unused(ifp)
327*bbb1b6f9SApple OSS Distributions #pragma unused(pf)
328*bbb1b6f9SApple OSS Distributions #pragma unused(dmx)
329*bbb1b6f9SApple OSS Distributions #pragma unused(cnt)
330*bbb1b6f9SApple OSS Distributions 
331*bbb1b6f9SApple OSS Distributions 	return 0;
332*bbb1b6f9SApple OSS Distributions }
333*bbb1b6f9SApple OSS Distributions 
334*bbb1b6f9SApple OSS Distributions __private_extern__ errno_t
iptap_del_proto(ifnet_t ifp,protocol_family_t pf)335*bbb1b6f9SApple OSS Distributions iptap_del_proto(ifnet_t ifp, protocol_family_t pf)
336*bbb1b6f9SApple OSS Distributions {
337*bbb1b6f9SApple OSS Distributions #pragma unused(ifp)
338*bbb1b6f9SApple OSS Distributions #pragma unused(pf)
339*bbb1b6f9SApple OSS Distributions 
340*bbb1b6f9SApple OSS Distributions 	return 0;
341*bbb1b6f9SApple OSS Distributions }
342*bbb1b6f9SApple OSS Distributions 
343*bbb1b6f9SApple OSS Distributions __private_extern__ errno_t
iptap_getdrvspec(ifnet_t ifp,struct ifdrv64 * ifd)344*bbb1b6f9SApple OSS Distributions iptap_getdrvspec(ifnet_t ifp, struct ifdrv64 *ifd)
345*bbb1b6f9SApple OSS Distributions {
346*bbb1b6f9SApple OSS Distributions 	errno_t error = 0;
347*bbb1b6f9SApple OSS Distributions 	struct iptap_softc *__single iptap;
348*bbb1b6f9SApple OSS Distributions 
349*bbb1b6f9SApple OSS Distributions 	iptap = ifp->if_softc;
350*bbb1b6f9SApple OSS Distributions 	if (iptap == NULL) {
351*bbb1b6f9SApple OSS Distributions 		error = ENOENT;
352*bbb1b6f9SApple OSS Distributions 		printf("%s: iptap NULL - error %d\n", __func__, error);
353*bbb1b6f9SApple OSS Distributions 		goto done;
354*bbb1b6f9SApple OSS Distributions 	}
355*bbb1b6f9SApple OSS Distributions 
356*bbb1b6f9SApple OSS Distributions 	switch (ifd->ifd_cmd) {
357*bbb1b6f9SApple OSS Distributions 	case PKTP_CMD_TAP_COUNT: {
358*bbb1b6f9SApple OSS Distributions 		uint32_t tap_count = iptap->iptap_dlt_raw_count + iptap->iptap_dlt_pkttap_count;
359*bbb1b6f9SApple OSS Distributions 
360*bbb1b6f9SApple OSS Distributions 		if (ifd->ifd_len < sizeof(tap_count)) {
361*bbb1b6f9SApple OSS Distributions 			printf("%s: PKTP_CMD_TAP_COUNT ifd_len %llu too small - error %d\n",
362*bbb1b6f9SApple OSS Distributions 			    __func__, ifd->ifd_len, error);
363*bbb1b6f9SApple OSS Distributions 			error = EINVAL;
364*bbb1b6f9SApple OSS Distributions 			break;
365*bbb1b6f9SApple OSS Distributions 		}
366*bbb1b6f9SApple OSS Distributions 		error = copyout(&tap_count, ifd->ifd_data, sizeof(tap_count));
367*bbb1b6f9SApple OSS Distributions 		if (error) {
368*bbb1b6f9SApple OSS Distributions 			printf("%s: PKTP_CMD_TAP_COUNT copyout - error %d\n", __func__, error);
369*bbb1b6f9SApple OSS Distributions 			goto done;
370*bbb1b6f9SApple OSS Distributions 		}
371*bbb1b6f9SApple OSS Distributions 		break;
372*bbb1b6f9SApple OSS Distributions 	}
373*bbb1b6f9SApple OSS Distributions 	default:
374*bbb1b6f9SApple OSS Distributions 		error = EINVAL;
375*bbb1b6f9SApple OSS Distributions 		break;
376*bbb1b6f9SApple OSS Distributions 	}
377*bbb1b6f9SApple OSS Distributions 
378*bbb1b6f9SApple OSS Distributions done:
379*bbb1b6f9SApple OSS Distributions 	return error;
380*bbb1b6f9SApple OSS Distributions }
381*bbb1b6f9SApple OSS Distributions 
382*bbb1b6f9SApple OSS Distributions __private_extern__ errno_t
iptap_ioctl(ifnet_t ifp,unsigned long cmd,void * __sized_by (IOCPARM_LEN (cmd))data)383*bbb1b6f9SApple OSS Distributions iptap_ioctl(ifnet_t ifp, unsigned long cmd, void *__sized_by(IOCPARM_LEN(cmd)) data)
384*bbb1b6f9SApple OSS Distributions {
385*bbb1b6f9SApple OSS Distributions 	errno_t error = 0;
386*bbb1b6f9SApple OSS Distributions 
387*bbb1b6f9SApple OSS Distributions 	if ((cmd & IOC_IN)) {
388*bbb1b6f9SApple OSS Distributions 		error = kauth_authorize_generic(kauth_cred_get(), KAUTH_GENERIC_ISSUSER);
389*bbb1b6f9SApple OSS Distributions 		if (error) {
390*bbb1b6f9SApple OSS Distributions 			goto done;
391*bbb1b6f9SApple OSS Distributions 		}
392*bbb1b6f9SApple OSS Distributions 	}
393*bbb1b6f9SApple OSS Distributions 
394*bbb1b6f9SApple OSS Distributions 	switch (cmd) {
395*bbb1b6f9SApple OSS Distributions 	case SIOCGDRVSPEC32: {
396*bbb1b6f9SApple OSS Distributions 		struct ifdrv64 ifd;
397*bbb1b6f9SApple OSS Distributions 		struct ifdrv32 *ifd32 = (struct ifdrv32 *)data;
398*bbb1b6f9SApple OSS Distributions 
399*bbb1b6f9SApple OSS Distributions 		memcpy(ifd.ifd_name, ifd32->ifd_name, sizeof(ifd.ifd_name));
400*bbb1b6f9SApple OSS Distributions 		ifd.ifd_cmd = ifd32->ifd_cmd;
401*bbb1b6f9SApple OSS Distributions 		ifd.ifd_len = ifd32->ifd_len;
402*bbb1b6f9SApple OSS Distributions 		ifd.ifd_data = ifd32->ifd_data;
403*bbb1b6f9SApple OSS Distributions 
404*bbb1b6f9SApple OSS Distributions 		error = iptap_getdrvspec(ifp, &ifd);
405*bbb1b6f9SApple OSS Distributions 
406*bbb1b6f9SApple OSS Distributions 		break;
407*bbb1b6f9SApple OSS Distributions 	}
408*bbb1b6f9SApple OSS Distributions 	case SIOCGDRVSPEC64: {
409*bbb1b6f9SApple OSS Distributions 		struct ifdrv64 *ifd64 = (struct ifdrv64 *)data;
410*bbb1b6f9SApple OSS Distributions 
411*bbb1b6f9SApple OSS Distributions 		error = iptap_getdrvspec(ifp, ifd64);
412*bbb1b6f9SApple OSS Distributions 
413*bbb1b6f9SApple OSS Distributions 		break;
414*bbb1b6f9SApple OSS Distributions 	}
415*bbb1b6f9SApple OSS Distributions 	default:
416*bbb1b6f9SApple OSS Distributions 		error = ENOTSUP;
417*bbb1b6f9SApple OSS Distributions 		break;
418*bbb1b6f9SApple OSS Distributions 	}
419*bbb1b6f9SApple OSS Distributions done:
420*bbb1b6f9SApple OSS Distributions 	return error;
421*bbb1b6f9SApple OSS Distributions }
422*bbb1b6f9SApple OSS Distributions 
423*bbb1b6f9SApple OSS Distributions __private_extern__ void
iptap_detach(ifnet_t ifp)424*bbb1b6f9SApple OSS Distributions iptap_detach(ifnet_t ifp)
425*bbb1b6f9SApple OSS Distributions {
426*bbb1b6f9SApple OSS Distributions 	struct iptap_softc *__single iptap = NULL;
427*bbb1b6f9SApple OSS Distributions 
428*bbb1b6f9SApple OSS Distributions 	iptap_lock_exclusive();
429*bbb1b6f9SApple OSS Distributions 
430*bbb1b6f9SApple OSS Distributions 	iptap = ifp->if_softc;
431*bbb1b6f9SApple OSS Distributions 	ifp->if_softc = NULL;
432*bbb1b6f9SApple OSS Distributions 	LIST_REMOVE(iptap, iptap_link);
433*bbb1b6f9SApple OSS Distributions 
434*bbb1b6f9SApple OSS Distributions 	if (LIST_EMPTY(&iptap_list)) {
435*bbb1b6f9SApple OSS Distributions 		iptap_ipf_unregister();
436*bbb1b6f9SApple OSS Distributions 	}
437*bbb1b6f9SApple OSS Distributions 
438*bbb1b6f9SApple OSS Distributions 	iptap_lock_done();
439*bbb1b6f9SApple OSS Distributions 
440*bbb1b6f9SApple OSS Distributions 	/* Drop reference as it's no more on the global list */
441*bbb1b6f9SApple OSS Distributions 	ifnet_release(ifp);
442*bbb1b6f9SApple OSS Distributions 	kfree_type(struct iptap_softc, iptap);
443*bbb1b6f9SApple OSS Distributions 
444*bbb1b6f9SApple OSS Distributions 	/* This is for the reference taken by ifnet_attach() */
445*bbb1b6f9SApple OSS Distributions 	(void) ifnet_release(ifp);
446*bbb1b6f9SApple OSS Distributions }
447*bbb1b6f9SApple OSS Distributions 
448*bbb1b6f9SApple OSS Distributions static int
iptap_ipf_register(void)449*bbb1b6f9SApple OSS Distributions iptap_ipf_register(void)
450*bbb1b6f9SApple OSS Distributions {
451*bbb1b6f9SApple OSS Distributions 	struct ipf_filter iptap_ipfinit;
452*bbb1b6f9SApple OSS Distributions 	int err = 0;
453*bbb1b6f9SApple OSS Distributions 
454*bbb1b6f9SApple OSS Distributions 	IPTAP_LOG("\n");
455*bbb1b6f9SApple OSS Distributions 
456*bbb1b6f9SApple OSS Distributions 	bzero(&iptap_ipfinit, sizeof(iptap_ipfinit));
457*bbb1b6f9SApple OSS Distributions 	iptap_ipfinit.name = IPTAP_IFNAME;
458*bbb1b6f9SApple OSS Distributions 	iptap_ipfinit.cookie = &iptap_ipf4;
459*bbb1b6f9SApple OSS Distributions 	iptap_ipfinit.ipf_input = iptap_ipf_input;
460*bbb1b6f9SApple OSS Distributions 	iptap_ipfinit.ipf_output = iptap_ipf_output;
461*bbb1b6f9SApple OSS Distributions 	iptap_ipfinit.ipf_detach = iptap_ipf_detach;
462*bbb1b6f9SApple OSS Distributions 
463*bbb1b6f9SApple OSS Distributions 	err = ipf_addv4(&iptap_ipfinit, &iptap_ipf4);
464*bbb1b6f9SApple OSS Distributions 	if (err != 0) {
465*bbb1b6f9SApple OSS Distributions 		printf("%s: ipf_addv4 for %s0 failed - %d\n",
466*bbb1b6f9SApple OSS Distributions 		    __func__, IPTAP_IFNAME, err);
467*bbb1b6f9SApple OSS Distributions 		goto done;
468*bbb1b6f9SApple OSS Distributions 	}
469*bbb1b6f9SApple OSS Distributions 
470*bbb1b6f9SApple OSS Distributions 	iptap_ipfinit.cookie = &iptap_ipf6;
471*bbb1b6f9SApple OSS Distributions 	err = ipf_addv6(&iptap_ipfinit, &iptap_ipf6);
472*bbb1b6f9SApple OSS Distributions 	if (err != 0) {
473*bbb1b6f9SApple OSS Distributions 		printf("%s: ipf_addv6 for %s0 failed - %d\n",
474*bbb1b6f9SApple OSS Distributions 		    __func__, IPTAP_IFNAME, err);
475*bbb1b6f9SApple OSS Distributions 		(void) ipf_remove(iptap_ipf4);
476*bbb1b6f9SApple OSS Distributions 		iptap_ipf4 = NULL;
477*bbb1b6f9SApple OSS Distributions 		goto done;
478*bbb1b6f9SApple OSS Distributions 	}
479*bbb1b6f9SApple OSS Distributions 
480*bbb1b6f9SApple OSS Distributions done:
481*bbb1b6f9SApple OSS Distributions 	return err;
482*bbb1b6f9SApple OSS Distributions }
483*bbb1b6f9SApple OSS Distributions 
484*bbb1b6f9SApple OSS Distributions static int
iptap_ipf_unregister(void)485*bbb1b6f9SApple OSS Distributions iptap_ipf_unregister(void)
486*bbb1b6f9SApple OSS Distributions {
487*bbb1b6f9SApple OSS Distributions 	int err = 0;
488*bbb1b6f9SApple OSS Distributions 
489*bbb1b6f9SApple OSS Distributions 	IPTAP_LOG("\n");
490*bbb1b6f9SApple OSS Distributions 
491*bbb1b6f9SApple OSS Distributions 	if (iptap_ipf4 != NULL) {
492*bbb1b6f9SApple OSS Distributions 		err = ipf_remove(iptap_ipf4);
493*bbb1b6f9SApple OSS Distributions 		if (err != 0) {
494*bbb1b6f9SApple OSS Distributions 			printf("%s: ipf_remove (ipv4) for %s0 failed - %d\n",
495*bbb1b6f9SApple OSS Distributions 			    __func__, IPTAP_IFNAME, err);
496*bbb1b6f9SApple OSS Distributions 			goto done;
497*bbb1b6f9SApple OSS Distributions 		}
498*bbb1b6f9SApple OSS Distributions 		iptap_ipf4 = NULL;
499*bbb1b6f9SApple OSS Distributions 	}
500*bbb1b6f9SApple OSS Distributions 
501*bbb1b6f9SApple OSS Distributions 	if (iptap_ipf6 != NULL) {
502*bbb1b6f9SApple OSS Distributions 		err = ipf_remove(iptap_ipf6);
503*bbb1b6f9SApple OSS Distributions 		if (err != 0) {
504*bbb1b6f9SApple OSS Distributions 			printf("%s: ipf_remove (ipv6) for %s0 failed - %d\n",
505*bbb1b6f9SApple OSS Distributions 			    __func__, IPTAP_IFNAME, err);
506*bbb1b6f9SApple OSS Distributions 			goto done;
507*bbb1b6f9SApple OSS Distributions 		}
508*bbb1b6f9SApple OSS Distributions 		iptap_ipf6 = NULL;
509*bbb1b6f9SApple OSS Distributions 	}
510*bbb1b6f9SApple OSS Distributions done:
511*bbb1b6f9SApple OSS Distributions 	return err;
512*bbb1b6f9SApple OSS Distributions }
513*bbb1b6f9SApple OSS Distributions 
514*bbb1b6f9SApple OSS Distributions static errno_t
iptap_ipf_input(void * arg,mbuf_t * mp,int off,u_int8_t proto)515*bbb1b6f9SApple OSS Distributions iptap_ipf_input(void *arg, mbuf_t *mp, int off, u_int8_t proto)
516*bbb1b6f9SApple OSS Distributions {
517*bbb1b6f9SApple OSS Distributions #pragma unused(off)
518*bbb1b6f9SApple OSS Distributions #pragma unused(proto)
519*bbb1b6f9SApple OSS Distributions 
520*bbb1b6f9SApple OSS Distributions 	if (arg == (void *)&iptap_ipf4) {
521*bbb1b6f9SApple OSS Distributions 		iptap_bpf_tap(*mp, AF_INET, 0);
522*bbb1b6f9SApple OSS Distributions 	} else if (arg == (void *)&iptap_ipf6) {
523*bbb1b6f9SApple OSS Distributions 		iptap_bpf_tap(*mp, AF_INET6, 0);
524*bbb1b6f9SApple OSS Distributions 	} else {
525*bbb1b6f9SApple OSS Distributions 		IPTAP_LOG("%s:%d bad cookie 0x%llx &iptap_ipf4 0x%llx "
526*bbb1b6f9SApple OSS Distributions 		    "&iptap_ipf6 0x%llx\n", __func__, __LINE__,
527*bbb1b6f9SApple OSS Distributions 		    (uint64_t)VM_KERNEL_ADDRPERM(arg),
528*bbb1b6f9SApple OSS Distributions 		    (uint64_t)VM_KERNEL_ADDRPERM(&iptap_ipf4),
529*bbb1b6f9SApple OSS Distributions 		    (uint64_t)VM_KERNEL_ADDRPERM(&iptap_ipf6));
530*bbb1b6f9SApple OSS Distributions 	}
531*bbb1b6f9SApple OSS Distributions 
532*bbb1b6f9SApple OSS Distributions 	return 0;
533*bbb1b6f9SApple OSS Distributions }
534*bbb1b6f9SApple OSS Distributions 
535*bbb1b6f9SApple OSS Distributions static errno_t
iptap_ipf_output(void * arg,mbuf_t * mp,ipf_pktopts_t opt)536*bbb1b6f9SApple OSS Distributions iptap_ipf_output(void *arg, mbuf_t *mp, ipf_pktopts_t opt)
537*bbb1b6f9SApple OSS Distributions {
538*bbb1b6f9SApple OSS Distributions #pragma unused(opt)
539*bbb1b6f9SApple OSS Distributions 
540*bbb1b6f9SApple OSS Distributions 	if (arg == (void *)&iptap_ipf4) {
541*bbb1b6f9SApple OSS Distributions 		iptap_bpf_tap(*mp, AF_INET, 1);
542*bbb1b6f9SApple OSS Distributions 	} else if (arg == (void *)&iptap_ipf6) {
543*bbb1b6f9SApple OSS Distributions 		iptap_bpf_tap(*mp, AF_INET6, 1);
544*bbb1b6f9SApple OSS Distributions 	} else {
545*bbb1b6f9SApple OSS Distributions 		IPTAP_LOG("%s:%d bad cookie 0x%llx &iptap_ipf4 0x%llx "
546*bbb1b6f9SApple OSS Distributions 		    "&iptap_ipf6 0x%llx\n", __func__, __LINE__,
547*bbb1b6f9SApple OSS Distributions 		    (uint64_t)VM_KERNEL_ADDRPERM(arg),
548*bbb1b6f9SApple OSS Distributions 		    (uint64_t)VM_KERNEL_ADDRPERM(&iptap_ipf4),
549*bbb1b6f9SApple OSS Distributions 		    (uint64_t)VM_KERNEL_ADDRPERM(&iptap_ipf6));
550*bbb1b6f9SApple OSS Distributions 	}
551*bbb1b6f9SApple OSS Distributions 
552*bbb1b6f9SApple OSS Distributions 	return 0;
553*bbb1b6f9SApple OSS Distributions }
554*bbb1b6f9SApple OSS Distributions 
555*bbb1b6f9SApple OSS Distributions static void
iptap_ipf_detach(void * arg)556*bbb1b6f9SApple OSS Distributions iptap_ipf_detach(void *arg)
557*bbb1b6f9SApple OSS Distributions {
558*bbb1b6f9SApple OSS Distributions #pragma unused(arg)
559*bbb1b6f9SApple OSS Distributions }
560*bbb1b6f9SApple OSS Distributions 
561*bbb1b6f9SApple OSS Distributions __private_extern__ void
iptap_bpf_tap(struct mbuf * m,u_int32_t proto,int outgoing)562*bbb1b6f9SApple OSS Distributions iptap_bpf_tap(struct mbuf *m, u_int32_t proto, int outgoing)
563*bbb1b6f9SApple OSS Distributions {
564*bbb1b6f9SApple OSS Distributions 	struct iptap_softc *__single iptap;
565*bbb1b6f9SApple OSS Distributions 	void (*bpf_tap_func)(ifnet_t, u_int32_t, mbuf_t, void *, size_t) =
566*bbb1b6f9SApple OSS Distributions 	    outgoing ? bpf_tap_out : bpf_tap_in;
567*bbb1b6f9SApple OSS Distributions 	uint32_t src_scope_id = 0;
568*bbb1b6f9SApple OSS Distributions 	uint32_t dst_scope_id = 0;
569*bbb1b6f9SApple OSS Distributions 
570*bbb1b6f9SApple OSS Distributions 	if (proto == AF_INET6) {
571*bbb1b6f9SApple OSS Distributions 		struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
572*bbb1b6f9SApple OSS Distributions 		/*
573*bbb1b6f9SApple OSS Distributions 		 * Clear the embedded scope ID
574*bbb1b6f9SApple OSS Distributions 		 */
575*bbb1b6f9SApple OSS Distributions 		if (in6_embedded_scope && IN6_IS_SCOPE_EMBED(&ip6->ip6_src)) {
576*bbb1b6f9SApple OSS Distributions 			src_scope_id = ip6->ip6_src.s6_addr16[1];
577*bbb1b6f9SApple OSS Distributions 			ip6->ip6_src.s6_addr16[1] = 0;
578*bbb1b6f9SApple OSS Distributions 		}
579*bbb1b6f9SApple OSS Distributions 		if (in6_embedded_scope && IN6_IS_SCOPE_EMBED(&ip6->ip6_dst)) {
580*bbb1b6f9SApple OSS Distributions 			dst_scope_id = ip6->ip6_dst.s6_addr16[1];
581*bbb1b6f9SApple OSS Distributions 			ip6->ip6_dst.s6_addr16[1] = 0;
582*bbb1b6f9SApple OSS Distributions 		}
583*bbb1b6f9SApple OSS Distributions 	}
584*bbb1b6f9SApple OSS Distributions 
585*bbb1b6f9SApple OSS Distributions 	iptap_lock_shared();
586*bbb1b6f9SApple OSS Distributions 
587*bbb1b6f9SApple OSS Distributions 	LIST_FOREACH(iptap, &iptap_list, iptap_link) {
588*bbb1b6f9SApple OSS Distributions 		if (iptap->iptap_dlt_raw_count > 0) {
589*bbb1b6f9SApple OSS Distributions 			bpf_tap_func(iptap->iptap_ifp, DLT_RAW, m,
590*bbb1b6f9SApple OSS Distributions 			    NULL, 0);
591*bbb1b6f9SApple OSS Distributions 		}
592*bbb1b6f9SApple OSS Distributions 		if (iptap->iptap_dlt_pkttap_count > 0) {
593*bbb1b6f9SApple OSS Distributions 			struct {
594*bbb1b6f9SApple OSS Distributions 				struct pktap_header hdr;
595*bbb1b6f9SApple OSS Distributions 				u_int32_t proto;
596*bbb1b6f9SApple OSS Distributions 			} hdr_buffer;
597*bbb1b6f9SApple OSS Distributions 			struct pktap_header *hdr = &hdr_buffer.hdr;
598*bbb1b6f9SApple OSS Distributions 			size_t hdr_size = sizeof(hdr_buffer);
599*bbb1b6f9SApple OSS Distributions 			struct ifnet *ifp = outgoing ? NULL : m->m_pkthdr.rcvif;
600*bbb1b6f9SApple OSS Distributions 
601*bbb1b6f9SApple OSS Distributions 			/* Verify the structure is packed */
602*bbb1b6f9SApple OSS Distributions 			static_assert(sizeof(hdr_buffer) == sizeof(struct pktap_header) + sizeof(u_int32_t));
603*bbb1b6f9SApple OSS Distributions 
604*bbb1b6f9SApple OSS Distributions 			bzero(&hdr_buffer, sizeof(hdr_buffer));
605*bbb1b6f9SApple OSS Distributions 			hdr->pth_length = sizeof(struct pktap_header);
606*bbb1b6f9SApple OSS Distributions 			hdr->pth_type_next = PTH_TYPE_PACKET;
607*bbb1b6f9SApple OSS Distributions 			hdr->pth_dlt = DLT_NULL;
608*bbb1b6f9SApple OSS Distributions 			if (ifp != NULL) {
609*bbb1b6f9SApple OSS Distributions 				snprintf(hdr->pth_ifname, sizeof(hdr->pth_ifname), "%s",
610*bbb1b6f9SApple OSS Distributions 				    ifp->if_xname);
611*bbb1b6f9SApple OSS Distributions 			}
612*bbb1b6f9SApple OSS Distributions 			hdr_buffer.proto = proto;
613*bbb1b6f9SApple OSS Distributions 			hdr->pth_flags = outgoing ? PTH_FLAG_DIR_OUT : PTH_FLAG_DIR_IN;
614*bbb1b6f9SApple OSS Distributions 			hdr->pth_protocol_family = proto;
615*bbb1b6f9SApple OSS Distributions 			hdr->pth_frame_pre_length = 0;
616*bbb1b6f9SApple OSS Distributions 			hdr->pth_frame_post_length = 0;
617*bbb1b6f9SApple OSS Distributions 			hdr->pth_iftype = ifp != NULL ? ifp->if_type : 0;
618*bbb1b6f9SApple OSS Distributions 			hdr->pth_ifunit = ifp != NULL ? ifp->if_unit : 0;
619*bbb1b6f9SApple OSS Distributions 
620*bbb1b6f9SApple OSS Distributions 			pktap_fill_proc_info(hdr, proto, m, 0, outgoing, ifp);
621*bbb1b6f9SApple OSS Distributions 
622*bbb1b6f9SApple OSS Distributions 			hdr->pth_svc = so_svc2tc(m->m_pkthdr.pkt_svc);
623*bbb1b6f9SApple OSS Distributions 
624*bbb1b6f9SApple OSS Distributions 			bpf_tap_func(iptap->iptap_ifp, DLT_PKTAP, m, &hdr_buffer,
625*bbb1b6f9SApple OSS Distributions 			    hdr_size);
626*bbb1b6f9SApple OSS Distributions 		}
627*bbb1b6f9SApple OSS Distributions 	}
628*bbb1b6f9SApple OSS Distributions 
629*bbb1b6f9SApple OSS Distributions 	iptap_lock_done();
630*bbb1b6f9SApple OSS Distributions 
631*bbb1b6f9SApple OSS Distributions 	if (proto == AF_INET6) {
632*bbb1b6f9SApple OSS Distributions 		struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
633*bbb1b6f9SApple OSS Distributions 
634*bbb1b6f9SApple OSS Distributions 		/*
635*bbb1b6f9SApple OSS Distributions 		 * Restore the embedded scope ID
636*bbb1b6f9SApple OSS Distributions 		 */
637*bbb1b6f9SApple OSS Distributions 		if (in6_embedded_scope && IN6_IS_SCOPE_EMBED(&ip6->ip6_src)) {
638*bbb1b6f9SApple OSS Distributions 			ip6->ip6_src.s6_addr16[1] = (uint16_t)src_scope_id;
639*bbb1b6f9SApple OSS Distributions 		}
640*bbb1b6f9SApple OSS Distributions 		if (in6_embedded_scope && IN6_IS_SCOPE_EMBED(&ip6->ip6_dst)) {
641*bbb1b6f9SApple OSS Distributions 			ip6->ip6_dst.s6_addr16[1] = (uint16_t)dst_scope_id;
642*bbb1b6f9SApple OSS Distributions 		}
643*bbb1b6f9SApple OSS Distributions 	}
644*bbb1b6f9SApple OSS Distributions }
645