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