2 * Copyright (c) 2012-2020 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <kern/locks.h>
30 #include <kern/zalloc.h>
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>
42 #include <net/if_var.h>
43 #include <net/if_types.h>
45 #include <net/net_osdep.h>
46 #include <net/pktap.h>
48 #include <netinet/in_pcb.h>
49 #include <netinet/tcp.h>
50 #include <netinet/tcp_var.h>
52 #include <netinet/ip.h>
53 #include <netinet/ip_var.h>
54 #include <netinet/udp.h>
55 #include <netinet/udp_var.h>
57 #include <netinet/ip6.h>
58 #include <netinet6/in6_pcb.h>
60 #include <libkern/OSAtomic.h>
62 #include <kern/debug.h>
64 #include <sys/mcache.h>
68 extern struct inpcbinfo ripcbinfo
;
71 LIST_ENTRY(pktap_softc
) pktp_link
;
73 uint32_t pktp_dlt_raw_count
;
74 uint32_t pktp_dlt_pkttap_count
;
75 struct ifnet
*pktp_ifp
;
76 struct pktap_filter pktp_filters
[PKTAP_MAX_FILTERS
];
81 #endif /* PKTAP_DEBUG */
83 #define PKTAP_FILTER_OK 0 /* Packet passes filter checks */
84 #define PKTAP_FILTER_SKIP 1 /* Do not tap this packet */
86 static int pktap_inited
= 0;
88 SYSCTL_DECL(_net_link
);
89 SYSCTL_NODE(_net_link
, IFT_PKTAP
, pktap
,
90 CTLFLAG_RW
| CTLFLAG_LOCKED
, 0, "pktap virtual interface");
92 uint32_t pktap_total_tap_count
= 0;
93 SYSCTL_UINT(_net_link_pktap
, OID_AUTO
, total_tap_count
,
94 CTLFLAG_RD
| CTLFLAG_LOCKED
, &pktap_total_tap_count
, 0, "");
96 static u_int64_t pktap_count_unknown_if_type
= 0;
97 SYSCTL_QUAD(_net_link_pktap
, OID_AUTO
, count_unknown_if_type
,
98 CTLFLAG_RD
| CTLFLAG_LOCKED
, &pktap_count_unknown_if_type
, "");
100 static int pktap_log
= 0;
101 SYSCTL_INT(_net_link_pktap
, OID_AUTO
, log
,
102 CTLFLAG_RW
| CTLFLAG_LOCKED
, &pktap_log
, 0, "");
104 #define PKTAP_LOG(mask, fmt, ...) \
106 if ((pktap_log & mask)) \
107 printf("%s:%d " fmt, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
110 #define PKTP_LOG_FUNC 0x01
111 #define PKTP_LOG_FILTER 0x02
112 #define PKTP_LOG_INPUT 0x04
113 #define PKTP_LOG_OUTPUT 0x08
114 #define PKTP_LOG_ERROR 0x10
115 #define PKTP_LOG_NOPCB 0x20
118 * pktap_lck_rw protects the global list of pktap interfaces
120 decl_lck_rw_data(static, pktap_lck_rw_data
);
121 static lck_rw_t
*pktap_lck_rw
= &pktap_lck_rw_data
;
122 static lck_grp_t
*pktap_lck_grp
= NULL
;
123 static lck_attr_t
*pktap_lck_attr
= NULL
;
125 static LIST_HEAD(pktap_list
, pktap_softc
) pktap_list
=
126 LIST_HEAD_INITIALIZER(pktap_list
);
128 int pktap_clone_create(struct if_clone
*, u_int32_t
, void *);
129 int pktap_clone_destroy(struct ifnet
*);
131 #define PKTAP_MAXUNIT IF_MAXUNIT
132 #define PKTAP_ZONE_MAX_ELEM MIN(IFNETS_MAX, PKTAP_MAXUNIT)
134 static struct if_clone pktap_cloner
=
135 IF_CLONE_INITIALIZER(PKTAP_IFNAME
,
141 sizeof(struct pktap_softc
));
143 errno_t
pktap_if_output(ifnet_t
, mbuf_t
);
144 errno_t
pktap_demux(ifnet_t
, mbuf_t
, char *, protocol_family_t
*);
145 errno_t
pktap_add_proto(ifnet_t
, protocol_family_t
,
146 const struct ifnet_demux_desc
*, u_int32_t
);
147 errno_t
pktap_del_proto(ifnet_t
, protocol_family_t
);
148 errno_t
pktap_getdrvspec(ifnet_t
, struct ifdrv64
*);
149 errno_t
pktap_setdrvspec(ifnet_t
, struct ifdrv64
*);
150 errno_t
pktap_ioctl(ifnet_t
, unsigned long, void *);
151 void pktap_detach(ifnet_t
);
152 int pktap_filter_evaluate(struct pktap_softc
*, struct ifnet
*);
153 void pktap_bpf_tap(struct ifnet
*, protocol_family_t
, struct mbuf
*,
154 u_int32_t
, u_int32_t
, int);
155 errno_t
pktap_tap_callback(ifnet_t
, u_int32_t
, bpf_tap_mode
);
158 pktap_hexdump(int mask
, void *addr
, size_t len
)
160 unsigned char *buf
= addr
;
163 if (!(pktap_log
& mask
)) {
167 for (i
= 0; i
< len
; i
++) {
168 unsigned char h
= (buf
[i
] & 0xf0) >> 4;
169 unsigned char l
= buf
[i
] & 0x0f;
174 } else if (i
% 4 == 0) {
179 h
< 10 ? h
+ '0' : h
- 10 + 'a',
180 l
< 10 ? l
+ '0' : l
- 10 + 'a');
187 #define _CASSERT_OFFFSETOF_FIELD(s1, s2, f) \
188 _CASSERT(offsetof(struct s1, f) == offsetof(struct s2, f))
190 __private_extern__
void
194 lck_grp_attr_t
*lck_grp_attr
= NULL
;
196 _CASSERT_OFFFSETOF_FIELD(pktap_header
, pktap_v2_hdr
, pth_flags
);
198 /* Make sure we're called only once */
199 VERIFY(pktap_inited
== 0);
203 lck_grp_attr
= lck_grp_attr_alloc_init();
204 pktap_lck_grp
= lck_grp_alloc_init("pktap", lck_grp_attr
);
205 pktap_lck_attr
= lck_attr_alloc_init();
207 lck_attr_setdebug(pktap_lck_attr
);
208 #endif /* PKTAP_DEBUG */
209 lck_rw_init(pktap_lck_rw
, pktap_lck_grp
, pktap_lck_attr
);
210 lck_grp_attr_free(lck_grp_attr
);
212 LIST_INIT(&pktap_list
);
214 error
= if_clone_attach(&pktap_cloner
);
216 panic("%s: if_clone_attach() failed, error %d\n",
221 __private_extern__
int
222 pktap_clone_create(struct if_clone
*ifc
, u_int32_t unit
, __unused
void *params
)
225 struct pktap_softc
*pktap
= NULL
;
226 struct ifnet_init_eparams if_init
;
228 PKTAP_LOG(PKTP_LOG_FUNC
, "unit %u\n", unit
);
230 pktap
= if_clone_softc_allocate(&pktap_cloner
);
232 printf("%s: _MALLOC failed\n", __func__
);
236 pktap
->pktp_unit
= unit
;
239 * By default accept packet from physical interfaces
241 pktap
->pktp_filters
[0].filter_op
= PKTAP_FILTER_OP_PASS
;
242 pktap
->pktp_filters
[0].filter_param
= PKTAP_FILTER_PARAM_IF_TYPE
;
243 pktap
->pktp_filters
[0].filter_param_if_type
= IFT_ETHER
;
245 #if !XNU_TARGET_OS_OSX
246 pktap
->pktp_filters
[1].filter_op
= PKTAP_FILTER_OP_PASS
;
247 pktap
->pktp_filters
[1].filter_param
= PKTAP_FILTER_PARAM_IF_TYPE
;
248 pktap
->pktp_filters
[1].filter_param_if_type
= IFT_CELLULAR
;
249 #else /* XNU_TARGET_OS_OSX */
250 pktap
->pktp_filters
[1].filter_op
= PKTAP_FILTER_OP_PASS
;
251 pktap
->pktp_filters
[1].filter_param
= PKTAP_FILTER_PARAM_IF_TYPE
;
252 pktap
->pktp_filters
[1].filter_param_if_type
= IFT_IEEE1394
;
253 #endif /* XNU_TARGET_OS_OSX */
255 pktap
->pktp_filters
[2].filter_op
= PKTAP_FILTER_OP_PASS
;
256 pktap
->pktp_filters
[2].filter_param
= PKTAP_FILTER_PARAM_IF_TYPE
;
257 pktap
->pktp_filters
[2].filter_param_if_type
= IFT_OTHER
;
260 * We do not use a set_bpf_tap() function as we rather rely on the more
261 * accurate callback passed to bpf_attach()
263 bzero(&if_init
, sizeof(if_init
));
264 if_init
.ver
= IFNET_INIT_CURRENT_VERSION
;
265 if_init
.len
= sizeof(if_init
);
266 if_init
.flags
= IFNET_INIT_LEGACY
;
267 if_init
.name
= ifc
->ifc_name
;
269 if_init
.type
= IFT_PKTAP
;
270 if_init
.family
= IFNET_FAMILY_LOOPBACK
;
271 if_init
.output
= pktap_if_output
;
272 if_init
.demux
= pktap_demux
;
273 if_init
.add_proto
= pktap_add_proto
;
274 if_init
.del_proto
= pktap_del_proto
;
275 if_init
.softc
= pktap
;
276 if_init
.ioctl
= pktap_ioctl
;
277 if_init
.detach
= pktap_detach
;
279 error
= ifnet_allocate_extended(&if_init
, &pktap
->pktp_ifp
);
281 printf("%s: ifnet_allocate failed, error %d\n",
286 ifnet_set_flags(pktap
->pktp_ifp
, IFF_UP
, IFF_UP
);
288 error
= ifnet_attach(pktap
->pktp_ifp
, NULL
);
290 printf("%s: ifnet_attach failed - error %d\n", __func__
, error
);
291 ifnet_release(pktap
->pktp_ifp
);
295 /* Attach DLT_PKTAP as the default DLT */
296 bpf_attach(pktap
->pktp_ifp
, DLT_PKTAP
, sizeof(struct pktap_header
),
297 NULL
, pktap_tap_callback
);
298 bpf_attach(pktap
->pktp_ifp
, DLT_RAW
, 0, NULL
, pktap_tap_callback
);
300 /* Take a reference and add to the global list */
301 ifnet_reference(pktap
->pktp_ifp
);
302 lck_rw_lock_exclusive(pktap_lck_rw
);
303 LIST_INSERT_HEAD(&pktap_list
, pktap
, pktp_link
);
304 lck_rw_done(pktap_lck_rw
);
306 if (error
!= 0 && pktap
!= NULL
) {
307 if_clone_softc_deallocate(&pktap_cloner
, pktap
);
312 __private_extern__
int
313 pktap_clone_destroy(struct ifnet
*ifp
)
317 PKTAP_LOG(PKTP_LOG_FUNC
, "%s\n", ifp
->if_xname
);
319 (void) ifnet_detach(ifp
);
325 * This function is called whenever a DLT is set on the interface:
326 * - When interface is attached to a BPF device via BIOCSETIF for the
328 * - Whenever a new DLT is selected via BIOCSDLT
329 * - When the interface is detached from a BPF device (direction is zero)
331 __private_extern__ errno_t
332 pktap_tap_callback(ifnet_t ifp
, u_int32_t dlt
, bpf_tap_mode direction
)
334 struct pktap_softc
*pktap
;
336 pktap
= ifp
->if_softc
;
338 printf("%s: if_softc is NULL for ifp %s\n", __func__
,
344 if (direction
== 0) {
345 if (pktap
->pktp_dlt_raw_count
> 0) {
346 pktap
->pktp_dlt_raw_count
--;
347 OSAddAtomic(-1, &pktap_total_tap_count
);
350 pktap
->pktp_dlt_raw_count
++;
351 OSAddAtomic(1, &pktap_total_tap_count
);
355 if (direction
== 0) {
356 if (pktap
->pktp_dlt_pkttap_count
> 0) {
357 pktap
->pktp_dlt_pkttap_count
--;
358 OSAddAtomic(-1, &pktap_total_tap_count
);
361 pktap
->pktp_dlt_pkttap_count
++;
362 OSAddAtomic(1, &pktap_total_tap_count
);
368 * Attachements count must be positive and we're in trouble
369 * if we have more that 2**31 attachements
371 VERIFY(pktap_total_tap_count
>= 0);
376 __private_extern__ errno_t
377 pktap_if_output(ifnet_t ifp
, mbuf_t m
)
379 PKTAP_LOG(PKTP_LOG_FUNC
, "%s\n", ifp
->if_xname
);
384 __private_extern__ errno_t
385 pktap_demux(ifnet_t ifp
, __unused mbuf_t m
, __unused
char *header
,
386 __unused protocol_family_t
*ppf
)
388 PKTAP_LOG(PKTP_LOG_FUNC
, "%s\n", ifp
->if_xname
);
392 __private_extern__ errno_t
393 pktap_add_proto(__unused ifnet_t ifp
, protocol_family_t pf
,
394 __unused
const struct ifnet_demux_desc
*dmx
, __unused u_int32_t cnt
)
396 PKTAP_LOG(PKTP_LOG_FUNC
, "%s pf %u\n", ifp
->if_xname
, pf
);
400 __private_extern__ errno_t
401 pktap_del_proto(__unused ifnet_t ifp
, __unused protocol_family_t pf
)
403 PKTAP_LOG(PKTP_LOG_FUNC
, "%s pf %u\n", ifp
->if_xname
, pf
);
407 __private_extern__ errno_t
408 pktap_getdrvspec(ifnet_t ifp
, struct ifdrv64
*ifd
)
411 struct pktap_softc
*pktap
;
414 PKTAP_LOG(PKTP_LOG_FUNC
, "%s\n", ifp
->if_xname
);
416 pktap
= ifp
->if_softc
;
419 printf("%s: pktap NULL - error %d\n", __func__
, error
);
423 switch (ifd
->ifd_cmd
) {
424 case PKTP_CMD_FILTER_GET
: {
425 struct x_pktap_filter x_filters
[PKTAP_MAX_FILTERS
];
427 bzero(&x_filters
, sizeof(x_filters
));
429 if (ifd
->ifd_len
< PKTAP_MAX_FILTERS
* sizeof(struct x_pktap_filter
)) {
430 printf("%s: PKTP_CMD_FILTER_GET ifd_len %llu too small - error %d\n",
431 __func__
, ifd
->ifd_len
, error
);
435 for (i
= 0; i
< PKTAP_MAX_FILTERS
; i
++) {
436 struct pktap_filter
*pktap_filter
= pktap
->pktp_filters
+ i
;
437 struct x_pktap_filter
*x_filter
= x_filters
+ i
;
439 x_filter
->filter_op
= pktap_filter
->filter_op
;
440 x_filter
->filter_param
= pktap_filter
->filter_param
;
442 if (pktap_filter
->filter_param
== PKTAP_FILTER_PARAM_IF_TYPE
) {
443 x_filter
->filter_param_if_type
= pktap_filter
->filter_param_if_type
;
444 } else if (pktap_filter
->filter_param
== PKTAP_FILTER_PARAM_IF_NAME
) {
445 strlcpy(x_filter
->filter_param_if_name
,
446 pktap_filter
->filter_param_if_name
,
447 sizeof(x_filter
->filter_param_if_name
));
450 error
= copyout(x_filters
, CAST_USER_ADDR_T(ifd
->ifd_data
),
451 PKTAP_MAX_FILTERS
* sizeof(struct x_pktap_filter
));
453 printf("%s: PKTP_CMD_FILTER_GET copyout - error %d\n", __func__
, error
);
458 case PKTP_CMD_TAP_COUNT
: {
459 uint32_t tap_count
= pktap
->pktp_dlt_raw_count
+ pktap
->pktp_dlt_pkttap_count
;
461 if (ifd
->ifd_len
< sizeof(tap_count
)) {
462 printf("%s: PKTP_CMD_TAP_COUNT ifd_len %llu too small - error %d\n",
463 __func__
, ifd
->ifd_len
, error
);
467 error
= copyout(&tap_count
, CAST_USER_ADDR_T(ifd
->ifd_data
), sizeof(tap_count
));
469 printf("%s: PKTP_CMD_TAP_COUNT copyout - error %d\n", __func__
, error
);
483 __private_extern__ errno_t
484 pktap_setdrvspec(ifnet_t ifp
, struct ifdrv64
*ifd
)
487 struct pktap_softc
*pktap
;
489 PKTAP_LOG(PKTP_LOG_FUNC
, "%s\n", ifp
->if_xname
);
491 pktap
= ifp
->if_softc
;
494 printf("%s: pktap NULL - error %d\n", __func__
, error
);
498 switch (ifd
->ifd_cmd
) {
499 case PKTP_CMD_FILTER_SET
: {
500 struct x_pktap_filter user_filters
[PKTAP_MAX_FILTERS
];
504 if (ifd
->ifd_len
!= PKTAP_MAX_FILTERS
* sizeof(struct x_pktap_filter
)) {
505 printf("%s: PKTP_CMD_FILTER_SET bad ifd_len %llu - error %d\n",
506 __func__
, ifd
->ifd_len
, error
);
510 error
= copyin(CAST_USER_ADDR_T(ifd
->ifd_data
), &user_filters
, (size_t)ifd
->ifd_len
);
512 printf("%s: copyin - error %d\n", __func__
, error
);
516 * Validate user provided parameters
518 for (i
= 0; i
< PKTAP_MAX_FILTERS
; i
++) {
519 struct x_pktap_filter
*x_filter
= user_filters
+ i
;
521 switch (x_filter
->filter_op
) {
522 case PKTAP_FILTER_OP_NONE
:
523 /* Following entries must be PKTAP_FILTER_OP_NONE */
526 case PKTAP_FILTER_OP_PASS
:
527 case PKTAP_FILTER_OP_SKIP
:
528 /* Invalid after PKTAP_FILTER_OP_NONE */
542 switch (x_filter
->filter_param
) {
543 case PKTAP_FILTER_OP_NONE
:
544 if (x_filter
->filter_op
!= PKTAP_FILTER_OP_NONE
) {
551 * Do not allow to tap a pktap from a pktap
553 case PKTAP_FILTER_PARAM_IF_TYPE
:
554 if (x_filter
->filter_param_if_type
== IFT_PKTAP
||
555 x_filter
->filter_param_if_type
> 0xff) {
561 case PKTAP_FILTER_PARAM_IF_NAME
:
562 if (strncmp(x_filter
->filter_param_if_name
, PKTAP_IFNAME
,
563 strlen(PKTAP_IFNAME
)) == 0) {
580 for (i
= 0; i
< PKTAP_MAX_FILTERS
; i
++) {
581 struct pktap_filter
*pktap_filter
= pktap
->pktp_filters
+ i
;
582 struct x_pktap_filter
*x_filter
= user_filters
+ i
;
584 pktap_filter
->filter_op
= x_filter
->filter_op
;
585 pktap_filter
->filter_param
= x_filter
->filter_param
;
587 if (pktap_filter
->filter_param
== PKTAP_FILTER_PARAM_IF_TYPE
) {
588 pktap_filter
->filter_param_if_type
= x_filter
->filter_param_if_type
;
589 } else if (pktap_filter
->filter_param
== PKTAP_FILTER_PARAM_IF_NAME
) {
592 strlcpy(pktap_filter
->filter_param_if_name
,
593 x_filter
->filter_param_if_name
,
594 sizeof(pktap_filter
->filter_param_if_name
));
596 * If name does not end with a number then it's a "wildcard" match
597 * where we compare the prefix of the interface name
599 len
= strlen(pktap_filter
->filter_param_if_name
);
600 if (pktap_filter
->filter_param_if_name
[len
] < '0' ||
601 pktap_filter
->filter_param_if_name
[len
] > '9') {
602 pktap_filter
->filter_ifname_prefix_len
= len
;
617 __private_extern__ errno_t
618 pktap_ioctl(ifnet_t ifp
, unsigned long cmd
, void *data
)
622 PKTAP_LOG(PKTP_LOG_FUNC
, "%s\n", ifp
->if_xname
);
624 if ((cmd
& IOC_IN
)) {
625 error
= kauth_authorize_generic(kauth_cred_get(), KAUTH_GENERIC_ISSUSER
);
627 PKTAP_LOG(PKTP_LOG_ERROR
,
628 "%s: kauth_authorize_generic(KAUTH_GENERIC_ISSUSER) - error %d\n",
635 case SIOCGDRVSPEC32
: {
637 struct ifdrv32
*ifd32
= (struct ifdrv32
*)data
;
639 memcpy(ifd
.ifd_name
, ifd32
->ifd_name
, sizeof(ifd
.ifd_name
));
640 ifd
.ifd_cmd
= ifd32
->ifd_cmd
;
641 ifd
.ifd_len
= ifd32
->ifd_len
;
642 ifd
.ifd_data
= ifd32
->ifd_data
;
644 error
= pktap_getdrvspec(ifp
, &ifd
);
648 case SIOCGDRVSPEC64
: {
649 struct ifdrv64
*ifd64
= (struct ifdrv64
*)data
;
651 error
= pktap_getdrvspec(ifp
, ifd64
);
655 case SIOCSDRVSPEC32
: {
657 struct ifdrv32
*ifd32
= (struct ifdrv32
*)data
;
659 memcpy(ifd
.ifd_name
, ifd32
->ifd_name
, sizeof(ifd
.ifd_name
));
660 ifd
.ifd_cmd
= ifd32
->ifd_cmd
;
661 ifd
.ifd_len
= ifd32
->ifd_len
;
662 ifd
.ifd_data
= ifd32
->ifd_data
;
664 error
= pktap_setdrvspec(ifp
, &ifd
);
667 case SIOCSDRVSPEC64
: {
668 struct ifdrv64
*ifd64
= (struct ifdrv64
*)data
;
670 error
= pktap_setdrvspec(ifp
, ifd64
);
682 __private_extern__
void
683 pktap_detach(ifnet_t ifp
)
685 struct pktap_softc
*pktap
;
687 PKTAP_LOG(PKTP_LOG_FUNC
, "%s\n", ifp
->if_xname
);
689 lck_rw_lock_exclusive(pktap_lck_rw
);
691 pktap
= ifp
->if_softc
;
692 ifp
->if_softc
= NULL
;
693 LIST_REMOVE(pktap
, pktp_link
);
695 lck_rw_done(pktap_lck_rw
);
697 /* Drop reference as it's no more on the global list */
700 if_clone_softc_deallocate(&pktap_cloner
, pktap
);
701 /* This is for the reference taken by ifnet_attach() */
702 (void) ifnet_release(ifp
);
705 __private_extern__
int
706 pktap_filter_evaluate(struct pktap_softc
*pktap
, struct ifnet
*ifp
)
709 int result
= PKTAP_FILTER_SKIP
; /* Need positive matching rule to pass */
712 for (i
= 0; i
< PKTAP_MAX_FILTERS
; i
++) {
713 struct pktap_filter
*pktap_filter
= pktap
->pktp_filters
+ i
;
714 size_t len
= pktap_filter
->filter_ifname_prefix_len
!= 0 ?
715 pktap_filter
->filter_ifname_prefix_len
: PKTAP_IFXNAMESIZE
;
717 switch (pktap_filter
->filter_op
) {
718 case PKTAP_FILTER_OP_NONE
:
722 case PKTAP_FILTER_OP_PASS
:
723 if (pktap_filter
->filter_param
== PKTAP_FILTER_PARAM_IF_TYPE
) {
724 if (pktap_filter
->filter_param_if_type
== 0 ||
725 ifp
->if_type
== pktap_filter
->filter_param_if_type
) {
726 result
= PKTAP_FILTER_OK
;
728 PKTAP_LOG(PKTP_LOG_FILTER
, "pass %s match type %u\n",
729 ifp
->if_xname
, pktap_filter
->filter_param_if_type
);
733 if (pktap_filter
->filter_param
== PKTAP_FILTER_PARAM_IF_NAME
) {
734 if (strncmp(ifp
->if_xname
, pktap_filter
->filter_param_if_name
,
736 result
= PKTAP_FILTER_OK
;
738 PKTAP_LOG(PKTP_LOG_FILTER
, "pass %s match name %s\n",
739 ifp
->if_xname
, pktap_filter
->filter_param_if_name
);
745 case PKTAP_FILTER_OP_SKIP
:
746 if (pktap_filter
->filter_param
== PKTAP_FILTER_PARAM_IF_TYPE
) {
747 if (pktap_filter
->filter_param_if_type
== 0 ||
748 ifp
->if_type
== pktap_filter
->filter_param_if_type
) {
749 result
= PKTAP_FILTER_SKIP
;
751 PKTAP_LOG(PKTP_LOG_FILTER
, "skip %s match type %u\n",
752 ifp
->if_xname
, pktap_filter
->filter_param_if_type
);
756 if (pktap_filter
->filter_param
== PKTAP_FILTER_PARAM_IF_NAME
) {
757 if (strncmp(ifp
->if_xname
, pktap_filter
->filter_param_if_name
,
759 result
= PKTAP_FILTER_SKIP
;
761 PKTAP_LOG(PKTP_LOG_FILTER
, "skip %s match name %s\n",
762 ifp
->if_xname
, pktap_filter
->filter_param_if_name
);
774 PKTAP_LOG(PKTP_LOG_FILTER
, "%s no match\n",
781 pktap_set_procinfo(struct pktap_header
*hdr
, struct so_procinfo
*soprocinfo
)
783 hdr
->pth_pid
= soprocinfo
->spi_pid
;
784 if (hdr
->pth_comm
[0] == 0) {
785 proc_name(soprocinfo
->spi_pid
, hdr
->pth_comm
, MAXCOMLEN
);
787 strlcpy(&hdr
->pth_comm
[0], &soprocinfo
->spi_proc_name
[0], sizeof(hdr
->pth_comm
));
789 if (soprocinfo
->spi_pid
!= 0) {
790 uuid_copy(hdr
->pth_uuid
, soprocinfo
->spi_uuid
);
793 if (soprocinfo
->spi_delegated
!= 0) {
794 hdr
->pth_flags
|= PTH_FLAG_PROC_DELEGATED
;
795 hdr
->pth_epid
= soprocinfo
->spi_epid
;
796 strlcpy(&hdr
->pth_ecomm
[0], &soprocinfo
->spi_e_proc_name
[0], sizeof(hdr
->pth_ecomm
));
797 uuid_copy(hdr
->pth_euuid
, soprocinfo
->spi_euuid
);
801 __private_extern__
void
802 pktap_finalize_proc_info(struct pktap_header
*hdr
)
805 struct so_procinfo soprocinfo
;
807 if (!(hdr
->pth_flags
& PTH_FLAG_DELAY_PKTAP
)) {
811 if (hdr
->pth_ipproto
== IPPROTO_TCP
) {
812 found
= inp_findinpcb_procinfo(&tcbinfo
, hdr
->pth_flowid
,
814 } else if (hdr
->pth_ipproto
== IPPROTO_UDP
) {
815 found
= inp_findinpcb_procinfo(&udbinfo
, hdr
->pth_flowid
,
818 found
= inp_findinpcb_procinfo(&ripcbinfo
, hdr
->pth_flowid
,
823 pktap_set_procinfo(hdr
, &soprocinfo
);
828 pktap_v2_set_procinfo(struct pktap_v2_hdr
*pktap_v2_hdr
,
829 struct so_procinfo
*soprocinfo
)
831 pktap_v2_hdr
->pth_pid
= soprocinfo
->spi_pid
;
833 if (soprocinfo
->spi_pid
!= 0 && soprocinfo
->spi_pid
!= -1) {
834 if (pktap_v2_hdr
->pth_comm_offset
!= 0) {
835 char *ptr
= ((char *)pktap_v2_hdr
) +
836 pktap_v2_hdr
->pth_comm_offset
;
838 strlcpy(ptr
, &soprocinfo
->spi_proc_name
[0], PKTAP_MAX_COMM_SIZE
);
840 if (pktap_v2_hdr
->pth_uuid_offset
!= 0) {
841 uuid_t
*ptr
= (uuid_t
*) (((char *)pktap_v2_hdr
) +
842 pktap_v2_hdr
->pth_uuid_offset
);
844 uuid_copy(*ptr
, soprocinfo
->spi_uuid
);
848 if (!(pktap_v2_hdr
->pth_flags
& PTH_FLAG_PROC_DELEGATED
)) {
853 * The effective UUID may be set independently from the effective pid
855 if (soprocinfo
->spi_delegated
!= 0) {
856 pktap_v2_hdr
->pth_flags
|= PTH_FLAG_PROC_DELEGATED
;
857 pktap_v2_hdr
->pth_e_pid
= soprocinfo
->spi_epid
;
859 if (soprocinfo
->spi_pid
!= 0 && soprocinfo
->spi_pid
!= -1 &&
860 pktap_v2_hdr
->pth_e_comm_offset
!= 0) {
861 char *ptr
= ((char *)pktap_v2_hdr
) +
862 pktap_v2_hdr
->pth_e_comm_offset
;
864 strlcpy(ptr
, &soprocinfo
->spi_e_proc_name
[0], PKTAP_MAX_COMM_SIZE
);
866 if (pktap_v2_hdr
->pth_e_uuid_offset
!= 0) {
867 uuid_t
*ptr
= (uuid_t
*) (((char *)pktap_v2_hdr
) +
868 pktap_v2_hdr
->pth_e_uuid_offset
);
870 uuid_copy(*ptr
, soprocinfo
->spi_euuid
);
875 __private_extern__
void
876 pktap_v2_finalize_proc_info(struct pktap_v2_hdr
*pktap_v2_hdr
)
879 struct so_procinfo soprocinfo
;
881 if (!(pktap_v2_hdr
->pth_flags
& PTH_FLAG_DELAY_PKTAP
)) {
885 if (pktap_v2_hdr
->pth_ipproto
== IPPROTO_TCP
) {
886 found
= inp_findinpcb_procinfo(&tcbinfo
,
887 pktap_v2_hdr
->pth_flowid
, &soprocinfo
);
888 } else if (pktap_v2_hdr
->pth_ipproto
== IPPROTO_UDP
) {
889 found
= inp_findinpcb_procinfo(&udbinfo
,
890 pktap_v2_hdr
->pth_flowid
, &soprocinfo
);
892 found
= inp_findinpcb_procinfo(&ripcbinfo
,
893 pktap_v2_hdr
->pth_flowid
, &soprocinfo
);
896 pktap_v2_set_procinfo(pktap_v2_hdr
, &soprocinfo
);
900 __private_extern__
void
901 pktap_fill_proc_info(struct pktap_header
*hdr
, protocol_family_t proto
,
902 struct mbuf
*m
, u_int32_t pre
, int outgoing
, struct ifnet
*ifp
)
905 * Getting the pid and procname is expensive
906 * For outgoing, do the lookup only if there's an
907 * associated socket as indicated by the flowhash
909 if (outgoing
!= 0 && m
->m_pkthdr
.pkt_flowsrc
== FLOWSRC_INPCB
) {
911 * To avoid lock ordering issues we delay the proc UUID lookup
912 * to the BPF read as we cannot
913 * assume the socket lock is unlocked on output
915 hdr
->pth_flags
|= PTH_FLAG_DELAY_PKTAP
;
916 hdr
->pth_flags
|= PTH_FLAG_SOCKET
;
917 hdr
->pth_flowid
= m
->m_pkthdr
.pkt_flowid
;
919 if (m
->m_pkthdr
.pkt_flags
& PKTF_FLOW_RAWSOCK
) {
920 hdr
->pth_ipproto
= IPPROTO_RAW
;
922 hdr
->pth_ipproto
= m
->m_pkthdr
.pkt_proto
;
925 if (hdr
->pth_ipproto
== IPPROTO_TCP
) {
926 hdr
->pth_pid
= m
->m_pkthdr
.tx_tcp_pid
;
927 hdr
->pth_epid
= m
->m_pkthdr
.tx_tcp_e_pid
;
928 } else if (hdr
->pth_ipproto
== IPPROTO_UDP
) {
929 hdr
->pth_pid
= m
->m_pkthdr
.tx_udp_pid
;
930 hdr
->pth_epid
= m
->m_pkthdr
.tx_udp_e_pid
;
931 } else if (hdr
->pth_ipproto
== IPPROTO_RAW
) {
932 hdr
->pth_pid
= m
->m_pkthdr
.tx_rawip_pid
;
933 hdr
->pth_epid
= m
->m_pkthdr
.tx_rawip_e_pid
;
936 if (hdr
->pth_pid
!= 0 && hdr
->pth_pid
!= -1) {
937 proc_name(hdr
->pth_pid
, hdr
->pth_comm
, MAXCOMLEN
);
942 if (hdr
->pth_epid
!= 0 && hdr
->pth_epid
!= -1) {
943 hdr
->pth_flags
|= PTH_FLAG_PROC_DELEGATED
;
944 proc_name(hdr
->pth_epid
, hdr
->pth_ecomm
, MAXCOMLEN
);
949 if (m
->m_pkthdr
.pkt_flags
& PKTF_NEW_FLOW
) {
950 hdr
->pth_flags
|= PTH_FLAG_NEW_FLOW
;
952 } else if (outgoing
== 0) {
954 struct so_procinfo soprocinfo
;
955 struct inpcb
*inp
= NULL
;
957 memset(&soprocinfo
, 0, sizeof(struct so_procinfo
));
959 if (proto
== PF_INET
) {
963 struct in_addr faddr
, laddr
;
964 u_short fport
= 0, lport
= 0;
965 struct inpcbinfo
*pcbinfo
= NULL
;
968 error
= mbuf_copydata(m
, pre
, sizeof(struct ip
), &ip
);
970 PKTAP_LOG(PKTP_LOG_ERROR
,
971 "mbuf_copydata tcp v4 failed for %s\n",
975 hlen
= IP_VHL_HL(ip
.ip_vhl
) << 2;
980 if (ip
.ip_p
== IPPROTO_TCP
) {
983 error
= mbuf_copydata(m
, pre
+ hlen
,
984 sizeof(struct tcphdr
), &th
);
993 } else if (ip
.ip_p
== IPPROTO_UDP
) {
996 error
= mbuf_copydata(m
, pre
+ hlen
,
997 sizeof(struct udphdr
), &uh
);
999 PKTAP_LOG(PKTP_LOG_ERROR
,
1000 "mbuf_copydata udp v4 failed for %s\n",
1004 fport
= uh
.uh_sport
;
1005 lport
= uh
.uh_dport
;
1010 if (pcbinfo
!= NULL
) {
1011 inp
= in_pcblookup_hash(pcbinfo
, faddr
, fport
,
1012 laddr
, lport
, wildcard
, outgoing
? NULL
: ifp
);
1014 if (inp
== NULL
&& hdr
->pth_iftype
!= IFT_LOOP
) {
1015 PKTAP_LOG(PKTP_LOG_NOPCB
,
1016 "in_pcblookup_hash no pcb %s\n",
1020 PKTAP_LOG(PKTP_LOG_NOPCB
,
1021 "unknown ip_p %u on %s\n",
1022 ip
.ip_p
, hdr
->pth_ifname
);
1023 pktap_hexdump(PKTP_LOG_NOPCB
, &ip
, sizeof(struct ip
));
1025 } else if (proto
== PF_INET6
) {
1028 struct in6_addr
*faddr
;
1029 struct in6_addr
*laddr
;
1030 u_short fport
= 0, lport
= 0;
1031 struct inpcbinfo
*pcbinfo
= NULL
;
1034 error
= mbuf_copydata(m
, pre
, sizeof(struct ip6_hdr
), &ip6
);
1039 faddr
= &ip6
.ip6_src
;
1040 laddr
= &ip6
.ip6_dst
;
1042 if (ip6
.ip6_nxt
== IPPROTO_TCP
) {
1045 error
= mbuf_copydata(m
, pre
+ sizeof(struct ip6_hdr
),
1046 sizeof(struct tcphdr
), &th
);
1048 PKTAP_LOG(PKTP_LOG_ERROR
,
1049 "mbuf_copydata tcp v6 failed for %s\n",
1054 fport
= th
.th_sport
;
1055 lport
= th
.th_dport
;
1058 } else if (ip6
.ip6_nxt
== IPPROTO_UDP
) {
1061 error
= mbuf_copydata(m
, pre
+ sizeof(struct ip6_hdr
),
1062 sizeof(struct udphdr
), &uh
);
1064 PKTAP_LOG(PKTP_LOG_ERROR
,
1065 "mbuf_copydata udp v6 failed for %s\n",
1070 fport
= uh
.uh_sport
;
1071 lport
= uh
.uh_dport
;
1076 if (pcbinfo
!= NULL
) {
1077 inp
= in6_pcblookup_hash(pcbinfo
, faddr
, fport
,
1078 laddr
, lport
, wildcard
, outgoing
? NULL
: ifp
);
1080 if (inp
== NULL
&& hdr
->pth_iftype
!= IFT_LOOP
) {
1081 PKTAP_LOG(PKTP_LOG_NOPCB
,
1082 "in6_pcblookup_hash no pcb %s\n",
1086 PKTAP_LOG(PKTP_LOG_NOPCB
,
1087 "unknown ip6.ip6_nxt %u on %s\n",
1088 ip6
.ip6_nxt
, hdr
->pth_ifname
);
1089 pktap_hexdump(PKTP_LOG_NOPCB
, &ip6
, sizeof(struct ip6_hdr
));
1093 hdr
->pth_flags
|= PTH_FLAG_SOCKET
;
1094 if (inp
->inp_state
!= INPCB_STATE_DEAD
&& inp
->inp_socket
!= NULL
) {
1096 inp_get_soprocinfo(inp
, &soprocinfo
);
1098 in_pcb_checkstate(inp
, WNT_RELEASE
, 0);
1102 * -1 means PID not found
1108 pktap_set_procinfo(hdr
, &soprocinfo
);
1113 __private_extern__
void
1114 pktap_bpf_tap(struct ifnet
*ifp
, protocol_family_t proto
, struct mbuf
*m
,
1115 u_int32_t pre
, u_int32_t post
, int outgoing
)
1117 struct pktap_softc
*pktap
;
1118 void (*bpf_tap_func
)(ifnet_t
, u_int32_t
, mbuf_t
, void *, size_t) =
1119 outgoing
? bpf_tap_out
: bpf_tap_in
;
1122 * Skip the coprocessor interface
1124 if (!intcoproc_unrestricted
&& IFNET_IS_INTCOPROC(ifp
)) {
1128 lck_rw_lock_shared(pktap_lck_rw
);
1131 * No need to take the ifnet_lock as the struct ifnet field if_bpf is
1132 * protected by the BPF subsystem
1134 LIST_FOREACH(pktap
, &pktap_list
, pktp_link
) {
1137 filter_result
= pktap_filter_evaluate(pktap
, ifp
);
1138 if (filter_result
== PKTAP_FILTER_SKIP
) {
1142 if (pktap
->pktp_dlt_raw_count
> 0) {
1143 /* We accept only IPv4 and IPv6 packets for the raw DLT */
1144 if ((proto
== AF_INET
|| proto
== AF_INET6
) &&
1145 !(m
->m_pkthdr
.pkt_flags
& PKTF_INET_RESOLVE
)) {
1147 * We can play just with the length of the first mbuf in the
1148 * chain because bpf_tap_imp() disregard the packet length
1149 * of the mbuf packet header.
1151 if (mbuf_setdata(m
, m
->m_data
+ pre
, m
->m_len
- pre
) == 0) {
1152 bpf_tap_func(pktap
->pktp_ifp
, DLT_RAW
, m
, NULL
, 0);
1153 mbuf_setdata(m
, m
->m_data
- pre
, m
->m_len
+ pre
);
1158 if (pktap
->pktp_dlt_pkttap_count
> 0) {
1160 struct pktap_header hdr
;
1163 struct pktap_header
*hdr
= &hdr_buffer
.hdr
;
1164 size_t hdr_size
= sizeof(struct pktap_header
);
1165 int unknown_if_type
= 0;
1166 size_t data_adjust
= 0;
1167 u_int32_t pre_adjust
= 0;
1169 /* Verify the structure is packed */
1170 _CASSERT(sizeof(hdr_buffer
) == sizeof(struct pktap_header
) + sizeof(u_int32_t
));
1172 bzero(&hdr_buffer
, sizeof(hdr_buffer
));
1173 hdr
->pth_length
= sizeof(struct pktap_header
);
1174 hdr
->pth_type_next
= PTH_TYPE_PACKET
;
1177 * Set DLT of packet based on interface type
1179 switch (ifp
->if_type
) {
1185 * Packets from pdp interfaces have no loopback
1186 * header that contain the protocol number.
1187 * As BPF just concatenate the header and the
1188 * packet content in a single buffer,
1189 * stash the protocol after the pktap header
1190 * and adjust the size of the header accordingly
1192 hdr
->pth_dlt
= DLT_NULL
;
1194 hdr_buffer
.proto
= proto
;
1195 hdr_size
= sizeof(hdr_buffer
);
1196 pre_adjust
= sizeof(hdr_buffer
.proto
);
1202 case IFT_IEEE8023ADLAG
:
1203 hdr
->pth_dlt
= DLT_EN10MB
;
1206 hdr
->pth_dlt
= DLT_PPP
;
1209 hdr
->pth_dlt
= DLT_APPLE_IP_OVER_IEEE1394
;
1212 if (ifp
->if_family
== IFNET_FAMILY_IPSEC
||
1213 ifp
->if_family
== IFNET_FAMILY_UTUN
) {
1216 * - incoming packets do not have the prefix set to four
1217 * - some packets are as small as two bytes!
1219 if (m_pktlen(m
) < 4) {
1222 if (proto
!= AF_INET
&& proto
!= AF_INET6
) {
1225 if (proto
== AF_INET
&& (size_t) m_pktlen(m
) - 4 < sizeof(struct ip
)) {
1228 if (proto
== AF_INET6
&& (size_t) m_pktlen(m
) - 4 < sizeof(struct ip6_hdr
)) {
1234 * - The old utun encapsulation with the protocol family in network order
1235 * - A raw IPv4 or IPv6 packet
1237 uint8_t data
= *(uint8_t *)mbuf_data(m
);
1238 if ((data
>> 4) == 4 || (data
>> 4) == 6) {
1242 * Skip the protocol in the mbuf as it's in network order
1248 hdr
->pth_dlt
= DLT_NULL
;
1249 hdr_buffer
.proto
= proto
;
1250 hdr_size
= sizeof(hdr_buffer
);
1254 hdr
->pth_dlt
= DLT_RAW
;
1256 unknown_if_type
= 1;
1260 if (unknown_if_type
) {
1261 PKTAP_LOG(PKTP_LOG_FUNC
,
1262 "unknown if_type %u for %s\n",
1263 ifp
->if_type
, ifp
->if_xname
);
1264 pktap_count_unknown_if_type
+= 1;
1266 strlcpy(hdr
->pth_ifname
, ifp
->if_xname
,
1267 sizeof(hdr
->pth_ifname
));
1268 hdr
->pth_flags
|= outgoing
? PTH_FLAG_DIR_OUT
: PTH_FLAG_DIR_IN
;
1269 hdr
->pth_protocol_family
= proto
;
1270 hdr
->pth_frame_pre_length
= pre
+ pre_adjust
;
1271 hdr
->pth_frame_post_length
= post
;
1272 hdr
->pth_iftype
= ifp
->if_type
;
1273 hdr
->pth_ifunit
= ifp
->if_unit
;
1275 if (m
->m_pkthdr
.pkt_flags
& PKTF_KEEPALIVE
) {
1276 hdr
->pth_flags
|= PTH_FLAG_KEEP_ALIVE
;
1278 if (m
->m_pkthdr
.pkt_flags
& PKTF_TCP_REXMT
) {
1279 hdr
->pth_flags
|= PTH_FLAG_REXMIT
;
1282 pktap_fill_proc_info(hdr
, proto
, m
, pre
, outgoing
, ifp
);
1284 hdr
->pth_svc
= so_svc2tc(m
->m_pkthdr
.pkt_svc
);
1286 if (data_adjust
== 0) {
1287 bpf_tap_func(pktap
->pktp_ifp
, DLT_PKTAP
, m
, hdr
, hdr_size
);
1290 * We can play just with the length of the first mbuf in the
1291 * chain because bpf_tap_imp() disregard the packet length
1292 * of the mbuf packet header.
1294 if (mbuf_setdata(m
, m
->m_data
+ data_adjust
, m
->m_len
- data_adjust
) == 0) {
1295 bpf_tap_func(pktap
->pktp_ifp
, DLT_PKTAP
, m
, hdr
, hdr_size
);
1296 mbuf_setdata(m
, m
->m_data
- data_adjust
, m
->m_len
+ data_adjust
);
1303 lck_rw_done(pktap_lck_rw
);
1306 __private_extern__
void
1307 pktap_input(struct ifnet
*ifp
, protocol_family_t proto
, struct mbuf
*m
,
1314 if (pktap_total_tap_count
== 0 ||
1315 (m
->m_pkthdr
.pkt_flags
& PKTF_SKIP_PKTAP
) != 0) {
1319 hdr
= (char *)mbuf_data(m
);
1320 start
= (char *)mbuf_datastart(m
);
1321 /* Make sure the frame header is fully contained in the mbuf */
1322 if (frame_header
!= NULL
&& frame_header
>= start
&& frame_header
<= hdr
) {
1323 size_t o_len
= m
->m_len
;
1324 u_int32_t pre
= (u_int32_t
)(hdr
- frame_header
);
1326 if (mbuf_setdata(m
, frame_header
, o_len
+ pre
) == 0) {
1327 PKTAP_LOG(PKTP_LOG_INPUT
, "ifp %s proto %u pre %u post %u\n",
1328 ifp
->if_xname
, proto
, pre
, 0);
1330 pktap_bpf_tap(ifp
, proto
, m
, pre
, 0, 0);
1331 mbuf_setdata(m
, hdr
, o_len
);
1334 PKTAP_LOG(PKTP_LOG_INPUT
, "ifp %s proto %u pre %u post %u\n",
1335 ifp
->if_xname
, proto
, 0, 0);
1337 pktap_bpf_tap(ifp
, proto
, m
, 0, 0, 0);
1341 __private_extern__
void
1342 pktap_output(struct ifnet
*ifp
, protocol_family_t proto
, struct mbuf
*m
,
1343 u_int32_t pre
, u_int32_t post
)
1346 if (pktap_total_tap_count
== 0 ||
1347 (m
->m_pkthdr
.pkt_flags
& PKTF_SKIP_PKTAP
) != 0) {
1351 PKTAP_LOG(PKTP_LOG_OUTPUT
, "ifp %s proto %u pre %u post %u\n",
1352 ifp
->if_xname
, proto
, pre
, post
);
1354 pktap_bpf_tap(ifp
, proto
, m
, pre
, post
, 1);
1359 convert_to_pktap_header_to_v2(struct bpf_packet
*bpf_pkt
, bool truncate
)
1361 struct pktap_header
*pktap_header
;
1362 size_t extra_src_size
;
1363 struct pktap_buffer_v2_hdr_extra pktap_buffer_v2_hdr_extra
;
1364 struct pktap_v2_hdr_space
*pktap_v2_hdr_space
;
1365 struct pktap_v2_hdr
*pktap_v2_hdr
;
1368 pktap_header
= (struct pktap_header
*)bpf_pkt
->bpfp_header
;
1370 if (pktap_header
->pth_type_next
!= PTH_TYPE_PACKET
) {
1374 VERIFY(bpf_pkt
->bpfp_header_length
>= sizeof(struct pktap_header
));
1377 * extra_src_size is the length of the optional link layer header
1379 extra_src_size
= bpf_pkt
->bpfp_header_length
-
1380 sizeof(struct pktap_header
);
1382 VERIFY(extra_src_size
<= sizeof(union pktap_header_extra
));
1384 pktap_v2_hdr_space
= &pktap_buffer_v2_hdr_extra
.hdr_space
;
1385 pktap_v2_hdr
= &pktap_v2_hdr_space
->pth_hdr
;
1386 ptr
= (uint8_t *) (pktap_v2_hdr
+ 1);
1388 COPY_PKTAP_COMMON_FIELDS_TO_V2(pktap_v2_hdr
, pktap_header
);
1391 * When truncating don't bother with the process UUIDs
1394 if ((pktap_header
->pth_flags
& PTH_FLAG_DELAY_PKTAP
)) {
1395 pktap_v2_hdr
->pth_uuid_offset
= pktap_v2_hdr
->pth_length
;
1396 pktap_v2_hdr
->pth_length
+= sizeof(uuid_t
);
1397 uuid_clear(*(uuid_t
*)ptr
);
1398 ptr
+= sizeof(uuid_t
);
1399 VERIFY((void *)ptr
< (void *)(pktap_v2_hdr_space
+ 1));
1400 } else if (!uuid_is_null(pktap_header
->pth_uuid
)) {
1401 pktap_v2_hdr
->pth_uuid_offset
= pktap_v2_hdr
->pth_length
;
1402 uuid_copy(*(uuid_t
*)ptr
, pktap_header
->pth_uuid
);
1403 pktap_v2_hdr
->pth_length
+= sizeof(uuid_t
);
1404 ptr
+= sizeof(uuid_t
);
1405 VERIFY((void *)ptr
< (void *)(pktap_v2_hdr_space
+ 1));
1408 if ((pktap_header
->pth_flags
& PTH_FLAG_DELAY_PKTAP
)) {
1409 if (pktap_header
->pth_flags
& PTH_FLAG_PROC_DELEGATED
) {
1410 pktap_v2_hdr
->pth_e_uuid_offset
= pktap_v2_hdr
->pth_length
;
1411 uuid_clear(*(uuid_t
*)ptr
);
1412 pktap_v2_hdr
->pth_length
+= sizeof(uuid_t
);
1413 ptr
+= sizeof(uuid_t
);
1414 VERIFY((void *)ptr
< (void *)(pktap_v2_hdr_space
+ 1));
1416 } else if (!uuid_is_null(pktap_header
->pth_euuid
)) {
1417 pktap_v2_hdr
->pth_e_uuid_offset
= pktap_v2_hdr
->pth_length
;
1418 uuid_copy(*(uuid_t
*)ptr
, pktap_header
->pth_euuid
);
1419 pktap_v2_hdr
->pth_length
+= sizeof(uuid_t
);
1420 ptr
+= sizeof(uuid_t
);
1421 VERIFY((void *)ptr
< (void *)(pktap_v2_hdr_space
+ 1));
1425 if (pktap_header
->pth_ifname
[0] != 0) {
1428 pktap_v2_hdr
->pth_ifname_offset
= pktap_v2_hdr
->pth_length
;
1431 * Note: strlcpy() returns the length of the string so we need
1432 * to add one for the end-of-string
1434 strsize
= 1 + strlcpy((char *)ptr
, pktap_header
->pth_ifname
,
1435 sizeof(pktap_v2_hdr_space
->pth_ifname
));
1436 pktap_v2_hdr
->pth_length
+= strsize
;
1438 VERIFY((void *)ptr
< (void *)(pktap_v2_hdr_space
+ 1));
1442 * Do not waste space with the process name if we do not have a pid
1444 if (pktap_header
->pth_pid
!= 0 && pktap_header
->pth_pid
!= -1) {
1445 if (pktap_header
->pth_comm
[0] != 0) {
1448 pktap_v2_hdr
->pth_comm_offset
= pktap_v2_hdr
->pth_length
;
1450 strsize
= 1 + strlcpy((char *)ptr
, pktap_header
->pth_comm
,
1451 sizeof(pktap_v2_hdr_space
->pth_comm
));
1452 pktap_v2_hdr
->pth_length
+= strsize
;
1454 VERIFY((void *)ptr
< (void *)(pktap_v2_hdr_space
+ 1));
1455 } else if ((pktap_header
->pth_flags
& PTH_FLAG_DELAY_PKTAP
)) {
1456 size_t strsize
= sizeof(pktap_v2_hdr_space
->pth_comm
);
1458 pktap_v2_hdr
->pth_comm_offset
= pktap_v2_hdr
->pth_length
;
1460 *ptr
= 0; /* empty string by default */
1461 pktap_v2_hdr
->pth_length
+= strsize
;
1463 VERIFY((void *)ptr
< (void *)(pktap_v2_hdr_space
+ 1));
1468 * Do not waste space with the effective process name if we do not have
1469 * an effective pid or it's the same as the pid
1471 if (pktap_header
->pth_epid
!= 0 && pktap_header
->pth_epid
!= -1 &&
1472 pktap_header
->pth_epid
!= pktap_header
->pth_pid
) {
1473 if (pktap_header
->pth_ecomm
[0] != 0) {
1476 pktap_v2_hdr
->pth_e_comm_offset
= pktap_v2_hdr
->pth_length
;
1478 strsize
= 1 + strlcpy((char *)ptr
, pktap_header
->pth_ecomm
,
1479 sizeof(pktap_v2_hdr_space
->pth_e_comm
));
1480 pktap_v2_hdr
->pth_length
+= strsize
;
1482 VERIFY((void *)ptr
< (void *)(pktap_v2_hdr_space
+ 1));
1483 } else if ((pktap_header
->pth_flags
& PTH_FLAG_DELAY_PKTAP
)) {
1484 size_t strsize
= sizeof(pktap_v2_hdr_space
->pth_e_comm
);
1486 pktap_v2_hdr
->pth_e_comm_offset
= pktap_v2_hdr
->pth_length
;
1487 *ptr
= 0; /* empty string by default */
1488 pktap_v2_hdr
->pth_length
+= strsize
;
1490 VERIFY((void *)ptr
< (void *)(pktap_v2_hdr_space
+ 1));
1494 if (extra_src_size
> 0) {
1495 char *extra_src_ptr
= (char *)(pktap_header
+ 1);
1496 char *extra_dst_ptr
= ((char *)pktap_v2_hdr
) +
1497 pktap_v2_hdr
->pth_length
;
1499 VERIFY(pktap_v2_hdr
->pth_length
+ extra_src_size
<=
1500 sizeof(struct pktap_buffer_v2_hdr_extra
));
1502 memcpy(extra_dst_ptr
, extra_src_ptr
, extra_src_size
);
1505 VERIFY(pktap_v2_hdr
->pth_length
+ extra_src_size
<=
1506 bpf_pkt
->bpfp_header_length
);
1508 memcpy(bpf_pkt
->bpfp_header
, pktap_v2_hdr
,
1509 pktap_v2_hdr
->pth_length
+ extra_src_size
);
1511 bpf_pkt
->bpfp_total_length
+= pktap_v2_hdr
->pth_length
-
1512 sizeof(struct pktap_header
);
1513 bpf_pkt
->bpfp_header_length
+= pktap_v2_hdr
->pth_length
-
1514 sizeof(struct pktap_header
);