2 * Copyright (c) 2012-2017 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>
31 #include <sys/types.h>
32 #include <sys/kernel_types.h>
33 #include <sys/kauth.h>
34 #include <sys/socket.h>
35 #include <sys/socketvar.h>
36 #include <sys/sockio.h>
37 #include <sys/sysctl.h>
41 #include <net/if_var.h>
42 #include <net/if_types.h>
44 #include <net/net_osdep.h>
45 #include <net/pktap.h>
47 #include <netinet/in_pcb.h>
48 #include <netinet/tcp.h>
49 #include <netinet/tcp_var.h>
51 #include <netinet/ip.h>
52 #include <netinet/ip_var.h>
53 #include <netinet/udp.h>
54 #include <netinet/udp_var.h>
56 #include <netinet/ip6.h>
57 #include <netinet6/in6_pcb.h>
59 #include <libkern/OSAtomic.h>
61 #include <kern/debug.h>
63 #include <sys/mcache.h>
67 extern struct inpcbinfo ripcbinfo
;
70 LIST_ENTRY(pktap_softc
) pktp_link
;
72 uint32_t pktp_dlt_raw_count
;
73 uint32_t pktp_dlt_pkttap_count
;
74 struct ifnet
*pktp_ifp
;
75 struct pktap_filter pktp_filters
[PKTAP_MAX_FILTERS
];
80 #endif /* PKTAP_DEBUG */
82 #define PKTAP_FILTER_OK 0 /* Packet passes filter checks */
83 #define PKTAP_FILTER_SKIP 1 /* Do not tap this packet */
85 static int pktap_inited
= 0;
87 SYSCTL_DECL(_net_link
);
88 SYSCTL_NODE(_net_link
, IFT_PKTAP
, pktap
,
89 CTLFLAG_RW
|CTLFLAG_LOCKED
, 0, "pktap virtual interface");
91 uint32_t pktap_total_tap_count
= 0;
92 SYSCTL_UINT(_net_link_pktap
, OID_AUTO
, total_tap_count
,
93 CTLFLAG_RD
| CTLFLAG_LOCKED
, &pktap_total_tap_count
, 0, "");
95 static u_int64_t pktap_count_unknown_if_type
= 0;
96 SYSCTL_QUAD(_net_link_pktap
, OID_AUTO
, count_unknown_if_type
,
97 CTLFLAG_RD
| CTLFLAG_LOCKED
, &pktap_count_unknown_if_type
, "");
99 static int pktap_log
= 0;
100 SYSCTL_INT(_net_link_pktap
, OID_AUTO
, log
,
101 CTLFLAG_RW
| CTLFLAG_LOCKED
, &pktap_log
, 0, "");
103 #define PKTAP_LOG(mask, fmt, ...) \
105 if ((pktap_log & mask)) \
106 printf("%s:%d " fmt, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
109 #define PKTP_LOG_FUNC 0x01
110 #define PKTP_LOG_FILTER 0x02
111 #define PKTP_LOG_INPUT 0x04
112 #define PKTP_LOG_OUTPUT 0x08
113 #define PKTP_LOG_ERROR 0x10
114 #define PKTP_LOG_NOPCB 0x20
117 * pktap_lck_rw protects the global list of pktap interfaces
119 decl_lck_rw_data(static, pktap_lck_rw_data
);
120 static lck_rw_t
*pktap_lck_rw
= &pktap_lck_rw_data
;
121 static lck_grp_t
*pktap_lck_grp
= NULL
;
122 static lck_attr_t
*pktap_lck_attr
= NULL
;
124 static LIST_HEAD(pktap_list
, pktap_softc
) pktap_list
=
125 LIST_HEAD_INITIALIZER(pktap_list
);
127 int pktap_clone_create(struct if_clone
*, u_int32_t
, void *);
128 int pktap_clone_destroy(struct ifnet
*);
130 static struct if_clone pktap_cloner
=
131 IF_CLONE_INITIALIZER(PKTAP_IFNAME
,
137 errno_t
pktap_if_output(ifnet_t
, mbuf_t
);
138 errno_t
pktap_demux(ifnet_t
, mbuf_t
, char *, protocol_family_t
*);
139 errno_t
pktap_add_proto(ifnet_t
, protocol_family_t
,
140 const struct ifnet_demux_desc
*, u_int32_t
);
141 errno_t
pktap_del_proto(ifnet_t
, protocol_family_t
);
142 errno_t
pktap_getdrvspec(ifnet_t
, struct ifdrv64
*);
143 errno_t
pktap_setdrvspec(ifnet_t
, struct ifdrv64
*);
144 errno_t
pktap_ioctl(ifnet_t
, unsigned long, void *);
145 void pktap_detach(ifnet_t
);
146 int pktap_filter_evaluate(struct pktap_softc
*, struct ifnet
*);
147 void pktap_bpf_tap(struct ifnet
*, protocol_family_t
, struct mbuf
*,
148 u_int32_t
, u_int32_t
, int);
149 errno_t
pktap_tap_callback(ifnet_t
, u_int32_t
, bpf_tap_mode
);
152 pktap_hexdump(int mask
, void *addr
, size_t len
)
154 unsigned char *buf
= addr
;
157 if (!(pktap_log
& mask
))
160 for (i
= 0; i
< len
; i
++) {
161 unsigned char h
= (buf
[i
] & 0xf0) >> 4;
162 unsigned char l
= buf
[i
] & 0x0f;
171 h
< 10 ? h
+ '0' : h
- 10 + 'a',
172 l
< 10 ? l
+ '0' : l
- 10 + 'a');
178 __private_extern__
void
182 lck_grp_attr_t
*lck_grp_attr
= NULL
;
184 /* Make sure we're called only once */
185 VERIFY(pktap_inited
== 0);
189 lck_grp_attr
= lck_grp_attr_alloc_init();
190 pktap_lck_grp
= lck_grp_alloc_init("pktap", lck_grp_attr
);
191 pktap_lck_attr
= lck_attr_alloc_init();
193 lck_attr_setdebug(pktap_lck_attr
);
194 #endif /* PKTAP_DEBUG */
195 lck_rw_init(pktap_lck_rw
, pktap_lck_grp
, pktap_lck_attr
);
196 lck_grp_attr_free(lck_grp_attr
);
198 LIST_INIT(&pktap_list
);
200 error
= if_clone_attach(&pktap_cloner
);
202 panic("%s: if_clone_attach() failed, error %d\n",
206 __private_extern__
int
207 pktap_clone_create(struct if_clone
*ifc
, u_int32_t unit
, __unused
void *params
)
210 struct pktap_softc
*pktap
= NULL
;
211 struct ifnet_init_eparams if_init
;
213 PKTAP_LOG(PKTP_LOG_FUNC
, "unit %u\n", unit
);
215 pktap
= _MALLOC(sizeof(struct pktap_softc
), M_DEVBUF
,
218 printf("%s: _MALLOC failed\n", __func__
);
222 pktap
->pktp_unit
= unit
;
225 * By default accept packet from physical interfaces
227 pktap
->pktp_filters
[0].filter_op
= PKTAP_FILTER_OP_PASS
;
228 pktap
->pktp_filters
[0].filter_param
= PKTAP_FILTER_PARAM_IF_TYPE
;
229 pktap
->pktp_filters
[0].filter_param_if_type
= IFT_ETHER
;
232 pktap
->pktp_filters
[1].filter_op
= PKTAP_FILTER_OP_PASS
;
233 pktap
->pktp_filters
[1].filter_param
= PKTAP_FILTER_PARAM_IF_TYPE
;
234 pktap
->pktp_filters
[1].filter_param_if_type
= IFT_CELLULAR
;
235 #else /* CONFIG_EMBEDDED */
236 pktap
->pktp_filters
[1].filter_op
= PKTAP_FILTER_OP_PASS
;
237 pktap
->pktp_filters
[1].filter_param
= PKTAP_FILTER_PARAM_IF_TYPE
;
238 pktap
->pktp_filters
[1].filter_param_if_type
= IFT_IEEE1394
;
239 #endif /* CONFIG_EMBEDDED */
241 #if (DEVELOPMENT || DEBUG)
242 pktap
->pktp_filters
[2].filter_op
= PKTAP_FILTER_OP_PASS
;
243 pktap
->pktp_filters
[2].filter_param
= PKTAP_FILTER_PARAM_IF_TYPE
;
244 pktap
->pktp_filters
[2].filter_param_if_type
= IFT_OTHER
;
245 #endif /* DEVELOPMENT || DEBUG */
248 * We do not use a set_bpf_tap() function as we rather rely on the more
249 * accurate callback passed to bpf_attach()
251 bzero(&if_init
, sizeof(if_init
));
252 if_init
.ver
= IFNET_INIT_CURRENT_VERSION
;
253 if_init
.len
= sizeof (if_init
);
254 if_init
.flags
= IFNET_INIT_LEGACY
;
255 if_init
.name
= ifc
->ifc_name
;
257 if_init
.type
= IFT_PKTAP
;
258 if_init
.family
= IFNET_FAMILY_LOOPBACK
;
259 if_init
.output
= pktap_if_output
;
260 if_init
.demux
= pktap_demux
;
261 if_init
.add_proto
= pktap_add_proto
;
262 if_init
.del_proto
= pktap_del_proto
;
263 if_init
.softc
= pktap
;
264 if_init
.ioctl
= pktap_ioctl
;
265 if_init
.detach
= pktap_detach
;
267 error
= ifnet_allocate_extended(&if_init
, &pktap
->pktp_ifp
);
269 printf("%s: ifnet_allocate failed, error %d\n",
274 ifnet_set_flags(pktap
->pktp_ifp
, IFF_UP
, IFF_UP
);
276 error
= ifnet_attach(pktap
->pktp_ifp
, NULL
);
278 printf("%s: ifnet_attach failed - error %d\n", __func__
, error
);
279 ifnet_release(pktap
->pktp_ifp
);
283 /* Attach DLT_PKTAP as the default DLT */
284 bpf_attach(pktap
->pktp_ifp
, DLT_PKTAP
, sizeof(struct pktap_header
),
285 NULL
, pktap_tap_callback
);
286 bpf_attach(pktap
->pktp_ifp
, DLT_RAW
, 0, NULL
, pktap_tap_callback
);
288 /* Take a reference and add to the global list */
289 ifnet_reference(pktap
->pktp_ifp
);
290 lck_rw_lock_exclusive(pktap_lck_rw
);
291 LIST_INSERT_HEAD(&pktap_list
, pktap
, pktp_link
);
292 lck_rw_done(pktap_lck_rw
);
296 _FREE(pktap
, M_DEVBUF
);
301 __private_extern__
int
302 pktap_clone_destroy(struct ifnet
*ifp
)
306 PKTAP_LOG(PKTP_LOG_FUNC
, "%s\n", ifp
->if_xname
);
308 (void) ifnet_detach(ifp
);
314 * This function is called whenever a DLT is set on the interface:
315 * - When interface is attached to a BPF device via BIOCSETIF for the
317 * - Whenever a new DLT is selected via BIOCSDLT
318 * - When the interface is detached from a BPF device (direction is zero)
320 __private_extern__ errno_t
321 pktap_tap_callback(ifnet_t ifp
, u_int32_t dlt
, bpf_tap_mode direction
)
323 struct pktap_softc
*pktap
;
325 pktap
= ifp
->if_softc
;
327 printf("%s: if_softc is NULL for ifp %s\n", __func__
,
333 if (direction
== 0) {
334 if (pktap
->pktp_dlt_raw_count
> 0) {
335 pktap
->pktp_dlt_raw_count
--;
336 OSAddAtomic(-1, &pktap_total_tap_count
);
340 pktap
->pktp_dlt_raw_count
++;
341 OSAddAtomic(1, &pktap_total_tap_count
);
345 if (direction
== 0) {
346 if (pktap
->pktp_dlt_pkttap_count
> 0) {
347 pktap
->pktp_dlt_pkttap_count
--;
348 OSAddAtomic(-1, &pktap_total_tap_count
);
351 pktap
->pktp_dlt_pkttap_count
++;
352 OSAddAtomic(1, &pktap_total_tap_count
);
358 * Attachements count must be positive and we're in trouble
359 * if we have more that 2**31 attachements
361 VERIFY(pktap_total_tap_count
>= 0);
366 __private_extern__ errno_t
367 pktap_if_output(ifnet_t ifp
, mbuf_t m
)
369 PKTAP_LOG(PKTP_LOG_FUNC
, "%s\n", ifp
->if_xname
);
374 __private_extern__ errno_t
375 pktap_demux(ifnet_t ifp
, __unused mbuf_t m
, __unused
char *header
,
376 __unused protocol_family_t
*ppf
)
378 PKTAP_LOG(PKTP_LOG_FUNC
, "%s\n", ifp
->if_xname
);
382 __private_extern__ errno_t
383 pktap_add_proto(__unused ifnet_t ifp
, protocol_family_t pf
,
384 __unused
const struct ifnet_demux_desc
*dmx
, __unused u_int32_t cnt
)
386 PKTAP_LOG(PKTP_LOG_FUNC
, "%s pf %u\n", ifp
->if_xname
, pf
);
390 __private_extern__ errno_t
391 pktap_del_proto(__unused ifnet_t ifp
, __unused protocol_family_t pf
)
393 PKTAP_LOG(PKTP_LOG_FUNC
, "%s pf %u\n", ifp
->if_xname
, pf
);
397 __private_extern__ errno_t
398 pktap_getdrvspec(ifnet_t ifp
, struct ifdrv64
*ifd
)
401 struct pktap_softc
*pktap
;
404 PKTAP_LOG(PKTP_LOG_FUNC
, "%s\n", ifp
->if_xname
);
406 pktap
= ifp
->if_softc
;
409 printf("%s: pktap NULL - error %d\n", __func__
, error
);
413 switch (ifd
->ifd_cmd
) {
414 case PKTP_CMD_FILTER_GET
: {
415 struct x_pktap_filter x_filters
[PKTAP_MAX_FILTERS
];
417 bzero(&x_filters
, sizeof(x_filters
));
419 if (ifd
->ifd_len
< PKTAP_MAX_FILTERS
* sizeof(struct x_pktap_filter
)) {
420 printf("%s: PKTP_CMD_FILTER_GET ifd_len %llu too small - error %d\n",
421 __func__
, ifd
->ifd_len
, error
);
425 for (i
= 0; i
< PKTAP_MAX_FILTERS
; i
++) {
426 struct pktap_filter
*pktap_filter
= pktap
->pktp_filters
+ i
;
427 struct x_pktap_filter
*x_filter
= x_filters
+ i
;
429 x_filter
->filter_op
= pktap_filter
->filter_op
;
430 x_filter
->filter_param
= pktap_filter
->filter_param
;
432 if (pktap_filter
->filter_param
== PKTAP_FILTER_PARAM_IF_TYPE
)
433 x_filter
->filter_param_if_type
= pktap_filter
->filter_param_if_type
;
434 else if (pktap_filter
->filter_param
== PKTAP_FILTER_PARAM_IF_NAME
)
435 strlcpy(x_filter
->filter_param_if_name
,
436 pktap_filter
->filter_param_if_name
,
437 sizeof(x_filter
->filter_param_if_name
));
439 error
= copyout(x_filters
, ifd
->ifd_data
,
440 PKTAP_MAX_FILTERS
* sizeof(struct x_pktap_filter
));
442 printf("%s: PKTP_CMD_FILTER_GET copyout - error %d\n", __func__
, error
);
447 case PKTP_CMD_TAP_COUNT
: {
448 uint32_t tap_count
= pktap
->pktp_dlt_raw_count
+ pktap
->pktp_dlt_pkttap_count
;
450 if (ifd
->ifd_len
< sizeof(tap_count
)) {
451 printf("%s: PKTP_CMD_TAP_COUNT ifd_len %llu too small - error %d\n",
452 __func__
, ifd
->ifd_len
, error
);
456 error
= copyout(&tap_count
, ifd
->ifd_data
, sizeof(tap_count
));
458 printf("%s: PKTP_CMD_TAP_COUNT copyout - error %d\n", __func__
, error
);
472 __private_extern__ errno_t
473 pktap_setdrvspec(ifnet_t ifp
, struct ifdrv64
*ifd
)
476 struct pktap_softc
*pktap
;
478 PKTAP_LOG(PKTP_LOG_FUNC
, "%s\n", ifp
->if_xname
);
480 pktap
= ifp
->if_softc
;
483 printf("%s: pktap NULL - error %d\n", __func__
, error
);
487 switch (ifd
->ifd_cmd
) {
488 case PKTP_CMD_FILTER_SET
: {
489 struct x_pktap_filter user_filters
[PKTAP_MAX_FILTERS
];
493 if (ifd
->ifd_len
!= PKTAP_MAX_FILTERS
* sizeof(struct x_pktap_filter
)) {
494 printf("%s: PKTP_CMD_FILTER_SET bad ifd_len %llu - error %d\n",
495 __func__
, ifd
->ifd_len
, error
);
499 error
= copyin(ifd
->ifd_data
, &user_filters
, ifd
->ifd_len
);
501 printf("%s: copyin - error %d\n", __func__
, error
);
505 * Validate user provided parameters
507 for (i
= 0; i
< PKTAP_MAX_FILTERS
; i
++) {
508 struct x_pktap_filter
*x_filter
= user_filters
+ i
;
510 switch (x_filter
->filter_op
) {
511 case PKTAP_FILTER_OP_NONE
:
512 /* Following entries must be PKTAP_FILTER_OP_NONE */
515 case PKTAP_FILTER_OP_PASS
:
516 case PKTAP_FILTER_OP_SKIP
:
517 /* Invalid after PKTAP_FILTER_OP_NONE */
530 switch (x_filter
->filter_param
) {
531 case PKTAP_FILTER_OP_NONE
:
532 if (x_filter
->filter_op
!= PKTAP_FILTER_OP_NONE
) {
539 * Do not allow to tap a pktap from a pktap
541 case PKTAP_FILTER_PARAM_IF_TYPE
:
542 if (x_filter
->filter_param_if_type
== IFT_PKTAP
||
543 x_filter
->filter_param_if_type
> 0xff) {
549 case PKTAP_FILTER_PARAM_IF_NAME
:
550 if (strncmp(x_filter
->filter_param_if_name
, PKTAP_IFNAME
,
551 strlen(PKTAP_IFNAME
)) == 0) {
566 for (i
= 0; i
< PKTAP_MAX_FILTERS
; i
++) {
567 struct pktap_filter
*pktap_filter
= pktap
->pktp_filters
+ i
;
568 struct x_pktap_filter
*x_filter
= user_filters
+ i
;
570 pktap_filter
->filter_op
= x_filter
->filter_op
;
571 pktap_filter
->filter_param
= x_filter
->filter_param
;
573 if (pktap_filter
->filter_param
== PKTAP_FILTER_PARAM_IF_TYPE
)
574 pktap_filter
->filter_param_if_type
= x_filter
->filter_param_if_type
;
575 else if (pktap_filter
->filter_param
== PKTAP_FILTER_PARAM_IF_NAME
) {
578 strlcpy(pktap_filter
->filter_param_if_name
,
579 x_filter
->filter_param_if_name
,
580 sizeof(pktap_filter
->filter_param_if_name
));
582 * If name does not end with a number then it's a "wildcard" match
583 * where we compare the prefix of the interface name
585 len
= strlen(pktap_filter
->filter_param_if_name
);
586 if (pktap_filter
->filter_param_if_name
[len
] < '0' ||
587 pktap_filter
->filter_param_if_name
[len
] > '9')
588 pktap_filter
->filter_ifname_prefix_len
= len
;
602 __private_extern__ errno_t
603 pktap_ioctl(ifnet_t ifp
, unsigned long cmd
, void *data
)
607 PKTAP_LOG(PKTP_LOG_FUNC
, "%s\n", ifp
->if_xname
);
609 if ((cmd
& IOC_IN
)) {
610 error
= kauth_authorize_generic(kauth_cred_get(), KAUTH_GENERIC_ISSUSER
);
612 PKTAP_LOG(PKTP_LOG_ERROR
,
613 "%s: kauth_authorize_generic(KAUTH_GENERIC_ISSUSER) - error %d\n",
620 case SIOCGDRVSPEC32
: {
622 struct ifdrv32
*ifd32
= (struct ifdrv32
*)data
;
624 memcpy(ifd
.ifd_name
, ifd32
->ifd_name
, sizeof(ifd
.ifd_name
));
625 ifd
.ifd_cmd
= ifd32
->ifd_cmd
;
626 ifd
.ifd_len
= ifd32
->ifd_len
;
627 ifd
.ifd_data
= ifd32
->ifd_data
;
629 error
= pktap_getdrvspec(ifp
, &ifd
);
633 case SIOCGDRVSPEC64
: {
634 struct ifdrv64
*ifd64
= (struct ifdrv64
*)data
;
636 error
= pktap_getdrvspec(ifp
, ifd64
);
640 case SIOCSDRVSPEC32
: {
642 struct ifdrv32
*ifd32
= (struct ifdrv32
*)data
;
644 memcpy(ifd
.ifd_name
, ifd32
->ifd_name
, sizeof(ifd
.ifd_name
));
645 ifd
.ifd_cmd
= ifd32
->ifd_cmd
;
646 ifd
.ifd_len
= ifd32
->ifd_len
;
647 ifd
.ifd_data
= ifd32
->ifd_data
;
649 error
= pktap_setdrvspec(ifp
, &ifd
);
652 case SIOCSDRVSPEC64
: {
653 struct ifdrv64
*ifd64
= (struct ifdrv64
*)data
;
655 error
= pktap_setdrvspec(ifp
, ifd64
);
667 __private_extern__
void
668 pktap_detach(ifnet_t ifp
)
670 struct pktap_softc
*pktap
;
672 PKTAP_LOG(PKTP_LOG_FUNC
, "%s\n", ifp
->if_xname
);
674 lck_rw_lock_exclusive(pktap_lck_rw
);
676 pktap
= ifp
->if_softc
;
677 ifp
->if_softc
= NULL
;
678 LIST_REMOVE(pktap
, pktp_link
);
680 lck_rw_done(pktap_lck_rw
);
682 /* Drop reference as it's no more on the global list */
685 _FREE(pktap
, M_DEVBUF
);
687 /* This is for the reference taken by ifnet_attach() */
688 (void) ifnet_release(ifp
);
691 __private_extern__
int
692 pktap_filter_evaluate(struct pktap_softc
*pktap
, struct ifnet
*ifp
)
695 int result
= PKTAP_FILTER_SKIP
; /* Need positive matching rule to pass */
698 for (i
= 0; i
< PKTAP_MAX_FILTERS
; i
++) {
699 struct pktap_filter
*pktap_filter
= pktap
->pktp_filters
+ i
;
700 size_t len
= pktap_filter
->filter_ifname_prefix_len
!= 0 ?
701 pktap_filter
->filter_ifname_prefix_len
: PKTAP_IFXNAMESIZE
;
703 switch (pktap_filter
->filter_op
) {
704 case PKTAP_FILTER_OP_NONE
:
708 case PKTAP_FILTER_OP_PASS
:
709 if (pktap_filter
->filter_param
== PKTAP_FILTER_PARAM_IF_TYPE
) {
710 if (pktap_filter
->filter_param_if_type
== 0 ||
711 ifp
->if_type
== pktap_filter
->filter_param_if_type
) {
712 result
= PKTAP_FILTER_OK
;
714 PKTAP_LOG(PKTP_LOG_FILTER
, "pass %s match type %u\n",
715 ifp
->if_xname
, pktap_filter
->filter_param_if_type
);
719 if (pktap_filter
->filter_param
== PKTAP_FILTER_PARAM_IF_NAME
) {
720 if (strncmp(ifp
->if_xname
, pktap_filter
->filter_param_if_name
,
722 result
= PKTAP_FILTER_OK
;
724 PKTAP_LOG(PKTP_LOG_FILTER
, "pass %s match name %s\n",
725 ifp
->if_xname
, pktap_filter
->filter_param_if_name
);
731 case PKTAP_FILTER_OP_SKIP
:
732 if (pktap_filter
->filter_param
== PKTAP_FILTER_PARAM_IF_TYPE
) {
733 if (pktap_filter
->filter_param_if_type
== 0 ||
734 ifp
->if_type
== pktap_filter
->filter_param_if_type
) {
735 result
= PKTAP_FILTER_SKIP
;
737 PKTAP_LOG(PKTP_LOG_FILTER
, "skip %s match type %u\n",
738 ifp
->if_xname
, pktap_filter
->filter_param_if_type
);
742 if (pktap_filter
->filter_param
== PKTAP_FILTER_PARAM_IF_NAME
) {
743 if (strncmp(ifp
->if_xname
, pktap_filter
->filter_param_if_name
,
745 result
= PKTAP_FILTER_SKIP
;
747 PKTAP_LOG(PKTP_LOG_FILTER
, "skip %s match name %s\n",
748 ifp
->if_xname
, pktap_filter
->filter_param_if_name
);
759 PKTAP_LOG(PKTP_LOG_FILTER
, "%s no match\n",
766 pktap_set_procinfo(struct pktap_header
*hdr
, struct so_procinfo
*soprocinfo
)
768 hdr
->pth_pid
= soprocinfo
->spi_pid
;
769 proc_name(soprocinfo
->spi_pid
, hdr
->pth_comm
, MAXCOMLEN
);
770 if (soprocinfo
->spi_pid
!= 0)
771 uuid_copy(hdr
->pth_uuid
, soprocinfo
->spi_uuid
);
774 * When not delegated, the effective pid is the same as the real pid
776 if (soprocinfo
->spi_delegated
!= 0) {
777 hdr
->pth_flags
|= PTH_FLAG_PROC_DELEGATED
;
778 hdr
->pth_epid
= soprocinfo
->spi_epid
;
779 proc_name(soprocinfo
->spi_epid
, hdr
->pth_ecomm
, MAXCOMLEN
);
780 uuid_copy(hdr
->pth_euuid
, soprocinfo
->spi_euuid
);
784 __private_extern__
void
785 pktap_finalize_proc_info(struct pktap_header
*hdr
)
788 struct so_procinfo soprocinfo
;
790 if (!(hdr
->pth_flags
& PTH_FLAG_DELAY_PKTAP
))
794 * Clear the flag as it's internal
796 hdr
->pth_flags
&= ~PTH_FLAG_DELAY_PKTAP
;
798 if (hdr
->pth_ipproto
== IPPROTO_TCP
)
799 found
= inp_findinpcb_procinfo(&tcbinfo
, hdr
->pth_flowid
,
801 else if (hdr
->pth_ipproto
== IPPROTO_UDP
)
802 found
= inp_findinpcb_procinfo(&udbinfo
, hdr
->pth_flowid
,
805 found
= inp_findinpcb_procinfo(&ripcbinfo
, hdr
->pth_flowid
,
809 pktap_set_procinfo(hdr
, &soprocinfo
);
812 __private_extern__
void
813 pktap_fill_proc_info(struct pktap_header
*hdr
, protocol_family_t proto
,
814 struct mbuf
*m
, u_int32_t pre
, int outgoing
, struct ifnet
*ifp
)
817 struct so_procinfo soprocinfo
;
820 * Getting the pid and procname is expensive
821 * For outgoing, do the lookup only if there's an
822 * associated socket as indicated by the flowhash
824 if (outgoing
!= 0 && m
->m_pkthdr
.pkt_flowsrc
== FLOWSRC_INPCB
) {
826 * To avoid lock ordering issues we delay the process lookup
827 * to the BPF read as we cannot
828 * assume the socket lock is unlocked on output
831 hdr
->pth_flags
|= PTH_FLAG_DELAY_PKTAP
;
832 hdr
->pth_flowid
= m
->m_pkthdr
.pkt_flowid
;
833 if (m
->m_pkthdr
.pkt_flags
& PKTF_FLOW_RAWSOCK
)
834 hdr
->pth_ipproto
= IPPROTO_RAW
;
836 hdr
->pth_ipproto
= m
->m_pkthdr
.pkt_proto
;
837 if (m
->m_pkthdr
.pkt_flags
& PKTF_NEW_FLOW
)
838 hdr
->pth_flags
|= PTH_FLAG_NEW_FLOW
;
839 } else if (outgoing
== 0) {
840 struct inpcb
*inp
= NULL
;
842 if (proto
== PF_INET
) {
846 struct in_addr faddr
, laddr
;
847 u_short fport
= 0, lport
= 0;
848 struct inpcbinfo
*pcbinfo
= NULL
;
851 error
= mbuf_copydata(m
, pre
, sizeof(struct ip
), &ip
);
853 PKTAP_LOG(PKTP_LOG_ERROR
,
854 "mbuf_copydata tcp v4 failed for %s\n",
858 hlen
= IP_VHL_HL(ip
.ip_vhl
) << 2;
863 if (ip
.ip_p
== IPPROTO_TCP
) {
866 error
= mbuf_copydata(m
, pre
+ hlen
,
867 sizeof(struct tcphdr
), &th
);
875 } else if (ip
.ip_p
== IPPROTO_UDP
) {
878 error
= mbuf_copydata(m
, pre
+ hlen
,
879 sizeof(struct udphdr
), &uh
);
881 PKTAP_LOG(PKTP_LOG_ERROR
,
882 "mbuf_copydata udp v4 failed for %s\n",
892 if (pcbinfo
!= NULL
) {
893 inp
= in_pcblookup_hash(pcbinfo
, faddr
, fport
,
894 laddr
, lport
, wildcard
, outgoing
? NULL
: ifp
);
896 if (inp
== NULL
&& hdr
->pth_iftype
!= IFT_LOOP
)
897 PKTAP_LOG(PKTP_LOG_NOPCB
,
898 "in_pcblookup_hash no pcb %s\n",
901 PKTAP_LOG(PKTP_LOG_NOPCB
,
902 "unknown ip_p %u on %s\n",
903 ip
.ip_p
, hdr
->pth_ifname
);
904 pktap_hexdump(PKTP_LOG_NOPCB
, &ip
, sizeof(struct ip
));
906 } else if (proto
== PF_INET6
) {
909 struct in6_addr
*faddr
;
910 struct in6_addr
*laddr
;
911 u_short fport
= 0, lport
= 0;
912 struct inpcbinfo
*pcbinfo
= NULL
;
915 error
= mbuf_copydata(m
, pre
, sizeof(struct ip6_hdr
), &ip6
);
919 faddr
= &ip6
.ip6_src
;
920 laddr
= &ip6
.ip6_dst
;
922 if (ip6
.ip6_nxt
== IPPROTO_TCP
) {
925 error
= mbuf_copydata(m
, pre
+ sizeof(struct ip6_hdr
),
926 sizeof(struct tcphdr
), &th
);
928 PKTAP_LOG(PKTP_LOG_ERROR
,
929 "mbuf_copydata tcp v6 failed for %s\n",
938 } else if (ip6
.ip6_nxt
== IPPROTO_UDP
) {
941 error
= mbuf_copydata(m
, pre
+ sizeof(struct ip6_hdr
),
942 sizeof(struct udphdr
), &uh
);
944 PKTAP_LOG(PKTP_LOG_ERROR
,
945 "mbuf_copydata udp v6 failed for %s\n",
956 if (pcbinfo
!= NULL
) {
957 inp
= in6_pcblookup_hash(pcbinfo
, faddr
, fport
,
958 laddr
, lport
, wildcard
, outgoing
? NULL
: ifp
);
960 if (inp
== NULL
&& hdr
->pth_iftype
!= IFT_LOOP
)
961 PKTAP_LOG(PKTP_LOG_NOPCB
,
962 "in6_pcblookup_hash no pcb %s\n",
965 PKTAP_LOG(PKTP_LOG_NOPCB
,
966 "unknown ip6.ip6_nxt %u on %s\n",
967 ip6
.ip6_nxt
, hdr
->pth_ifname
);
968 pktap_hexdump(PKTP_LOG_NOPCB
, &ip6
, sizeof(struct ip6_hdr
));
972 if (inp
->inp_state
!= INPCB_STATE_DEAD
&& inp
->inp_socket
!= NULL
) {
974 inp_get_soprocinfo(inp
, &soprocinfo
);
976 in_pcb_checkstate(inp
, WNT_RELEASE
, 0);
981 * -1 means PID not found
986 pktap_set_procinfo(hdr
, &soprocinfo
);
989 __private_extern__
void
990 pktap_bpf_tap(struct ifnet
*ifp
, protocol_family_t proto
, struct mbuf
*m
,
991 u_int32_t pre
, u_int32_t post
, int outgoing
)
993 struct pktap_softc
*pktap
;
994 void (*bpf_tap_func
)(ifnet_t
, u_int32_t
, mbuf_t
, void *, size_t) =
995 outgoing
? bpf_tap_out
: bpf_tap_in
;
999 * Skip the coprocessor interface
1001 if (!intcoproc_unrestricted
&& IFNET_IS_INTCOPROC(ifp
))
1004 lck_rw_lock_shared(pktap_lck_rw
);
1007 * No need to take the ifnet_lock as the struct ifnet field if_bpf is
1008 * protected by the BPF subsystem
1010 LIST_FOREACH(pktap
, &pktap_list
, pktp_link
) {
1013 filter_result
= pktap_filter_evaluate(pktap
, ifp
);
1014 if (filter_result
== PKTAP_FILTER_SKIP
)
1017 if (pktap
->pktp_dlt_raw_count
> 0) {
1018 /* We accept only IPv4 and IPv6 packets for the raw DLT */
1019 if ((proto
== AF_INET
||proto
== AF_INET6
) &&
1020 !(m
->m_pkthdr
.pkt_flags
& PKTF_INET_RESOLVE
)) {
1022 * We can play just with the length of the first mbuf in the
1023 * chain because bpf_tap_imp() disregard the packet length
1024 * of the mbuf packet header.
1026 if (mbuf_setdata(m
, m
->m_data
+ pre
, m
->m_len
- pre
) == 0) {
1027 bpf_tap_func(pktap
->pktp_ifp
, DLT_RAW
, m
, NULL
, 0);
1028 mbuf_setdata(m
, m
->m_data
- pre
, m
->m_len
+ pre
);
1033 if (pktap
->pktp_dlt_pkttap_count
> 0) {
1035 struct pktap_header hdr
;
1038 struct pktap_header
*hdr
= &hdr_buffer
.hdr
;
1039 size_t hdr_size
= sizeof(struct pktap_header
);
1040 int unknown_if_type
= 0;
1041 size_t data_adjust
= 0;
1042 u_int32_t pre_adjust
= 0;
1044 /* Verify the structure is packed */
1045 _CASSERT(sizeof(hdr_buffer
) == sizeof(struct pktap_header
) + sizeof(u_int32_t
));
1047 bzero(&hdr_buffer
, sizeof(hdr_buffer
));
1048 hdr
->pth_length
= sizeof(struct pktap_header
);
1049 hdr
->pth_type_next
= PTH_TYPE_PACKET
;
1052 * Set DLT of packet based on interface type
1054 switch (ifp
->if_type
) {
1060 * Packets from pdp interfaces have no loopback
1061 * header that contain the protocol number.
1062 * As BPF just concatenate the header and the
1063 * packet content in a single buffer,
1064 * stash the protocol after the pktap header
1065 * and adjust the size of the header accordingly
1067 hdr
->pth_dlt
= DLT_NULL
;
1069 hdr_buffer
.proto
= proto
;
1070 hdr_size
= sizeof(hdr_buffer
);
1071 pre_adjust
= sizeof(hdr_buffer
.proto
);
1077 case IFT_IEEE8023ADLAG
:
1078 hdr
->pth_dlt
= DLT_EN10MB
;
1081 hdr
->pth_dlt
= DLT_PPP
;
1084 hdr
->pth_dlt
= DLT_APPLE_IP_OVER_IEEE1394
;
1087 if (strncmp(ifp
->if_name
, "utun", strlen("utun")) == 0) {
1090 * - incoming packets do not have the prefix set to four
1091 * - some packets are as small as two bytes!
1093 if (m_pktlen(m
) < 4)
1095 if (proto
!= AF_INET
&& proto
!= AF_INET6
)
1097 if (proto
== AF_INET
&& (size_t) m_pktlen(m
) - 4 < sizeof(struct ip
))
1099 if (proto
== AF_INET6
&& (size_t) m_pktlen(m
) - 4 < sizeof(struct ip6_hdr
))
1104 * - The old utun encapsulation with the protocol family in network order
1105 * - A raw IPv4 or IPv6 packet
1107 uint8_t data
= *(uint8_t *)mbuf_data(m
);
1108 if ((data
>> 4) == 4 || (data
>> 4) == 6) {
1112 * Skip the protocol in the mbuf as it's in network order
1118 hdr
->pth_dlt
= DLT_NULL
;
1119 hdr_buffer
.proto
= proto
;
1120 hdr_size
= sizeof(hdr_buffer
);
1124 hdr
->pth_dlt
= DLT_RAW
;
1126 unknown_if_type
= 1;
1129 if (unknown_if_type
) {
1130 PKTAP_LOG(PKTP_LOG_FUNC
,
1131 "unknown if_type %u for %s\n",
1132 ifp
->if_type
, ifp
->if_xname
);
1133 pktap_count_unknown_if_type
+= 1;
1135 strlcpy(hdr
->pth_ifname
, ifp
->if_xname
,
1136 sizeof(hdr
->pth_ifname
));
1137 hdr
->pth_flags
|= outgoing
? PTH_FLAG_DIR_OUT
: PTH_FLAG_DIR_IN
;
1138 hdr
->pth_protocol_family
= proto
;
1139 hdr
->pth_frame_pre_length
= pre
+ pre_adjust
;
1140 hdr
->pth_frame_post_length
= post
;
1141 hdr
->pth_iftype
= ifp
->if_type
;
1142 hdr
->pth_ifunit
= ifp
->if_unit
;
1144 pktap_fill_proc_info(hdr
, proto
, m
, pre
, outgoing
, ifp
);
1146 hdr
->pth_svc
= so_svc2tc(m
->m_pkthdr
.pkt_svc
);
1148 if (data_adjust
== 0) {
1149 bpf_tap_func(pktap
->pktp_ifp
, DLT_PKTAP
, m
, hdr
, hdr_size
);
1152 * We can play just with the length of the first mbuf in the
1153 * chain because bpf_tap_imp() disregard the packet length
1154 * of the mbuf packet header.
1156 if (mbuf_setdata(m
, m
->m_data
+ data_adjust
, m
->m_len
- data_adjust
) == 0) {
1157 bpf_tap_func(pktap
->pktp_ifp
, DLT_PKTAP
, m
, hdr
, hdr_size
);
1158 mbuf_setdata(m
, m
->m_data
- data_adjust
, m
->m_len
+ data_adjust
);
1165 lck_rw_done(pktap_lck_rw
);
1168 __private_extern__
void
1169 pktap_input(struct ifnet
*ifp
, protocol_family_t proto
, struct mbuf
*m
,
1176 if (pktap_total_tap_count
== 0)
1179 hdr
= (char *)mbuf_data(m
);
1180 start
= (char *)mbuf_datastart(m
);
1181 /* Make sure the frame header is fully contained in the mbuf */
1182 if (frame_header
!= NULL
&& frame_header
>= start
&& frame_header
<= hdr
) {
1183 size_t o_len
= m
->m_len
;
1184 u_int32_t pre
= hdr
- frame_header
;
1186 if (mbuf_setdata(m
, frame_header
, o_len
+ pre
) == 0) {
1187 PKTAP_LOG(PKTP_LOG_INPUT
, "ifp %s proto %u pre %u post %u\n",
1188 ifp
->if_xname
, proto
, pre
, 0);
1190 pktap_bpf_tap(ifp
, proto
, m
, pre
, 0, 0);
1191 mbuf_setdata(m
, hdr
, o_len
);
1194 PKTAP_LOG(PKTP_LOG_INPUT
, "ifp %s proto %u pre %u post %u\n",
1195 ifp
->if_xname
, proto
, 0, 0);
1197 pktap_bpf_tap(ifp
, proto
, m
, 0, 0, 0);
1201 __private_extern__
void
1202 pktap_output(struct ifnet
*ifp
, protocol_family_t proto
, struct mbuf
*m
,
1203 u_int32_t pre
, u_int32_t post
)
1206 if (pktap_total_tap_count
== 0)
1209 PKTAP_LOG(PKTP_LOG_OUTPUT
, "ifp %s proto %u pre %u post %u\n",
1210 ifp
->if_xname
, proto
, pre
, post
);
1212 pktap_bpf_tap(ifp
, proto
, m
, pre
, post
, 1);