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