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