#include <sys/socketvar.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
-#include <sys/proc.h>
+#include <sys/proc.h>
#include <net/if.h>
#include <net/if_var.h>
#include <string.h>
struct iptap_softc {
- LIST_ENTRY(iptap_softc) iptap_link;
- uint32_t iptap_unit;
- uint32_t iptap_dlt_raw_count;
- uint32_t iptap_dlt_pkttap_count;
- struct ifnet *iptap_ifp;
+ LIST_ENTRY(iptap_softc) iptap_link;
+ uint32_t iptap_unit;
+ uint32_t iptap_dlt_raw_count;
+ uint32_t iptap_dlt_pkttap_count;
+ struct ifnet *iptap_ifp;
};
static LIST_HEAD(iptap_list, iptap_softc) iptap_list = LIST_HEAD_INITIALIZER(iptap_list);
-static void iptap_lock_shared(void);
-static void iptap_lock_exclusive(void);
-static void iptap_lock_done(void);
-static void iptap_alloc_lock(void);
+static void iptap_lock_shared(void);
+static void iptap_lock_exclusive(void);
+static void iptap_lock_done(void);
+static void iptap_alloc_lock(void);
decl_lck_rw_data(static, iptap_lck_rw);
-static lck_grp_t *iptap_grp;
+static lck_grp_t *iptap_grp;
errno_t iptap_if_output(ifnet_t, mbuf_t);
-errno_t iptap_demux(ifnet_t , mbuf_t, char *, protocol_family_t *);
+errno_t iptap_demux(ifnet_t, mbuf_t, char *, protocol_family_t *);
errno_t iptap_add_proto(ifnet_t, protocol_family_t, const struct ifnet_demux_desc *,
- u_int32_t);
+ u_int32_t);
errno_t iptap_del_proto(ifnet_t, protocol_family_t);
-errno_t iptap_getdrvspec(ifnet_t , struct ifdrv64 *);
+errno_t iptap_getdrvspec(ifnet_t, struct ifdrv64 *);
errno_t iptap_ioctl(ifnet_t, unsigned long, void *);
void iptap_detach(ifnet_t);
-errno_t iptap_tap_callback(ifnet_t , u_int32_t , bpf_tap_mode );
+errno_t iptap_tap_callback(ifnet_t, u_int32_t, bpf_tap_mode );
int iptap_clone_create(struct if_clone *, u_int32_t, void *);
int iptap_clone_destroy(struct ifnet *);
static ipfilter_t iptap_ipf4, iptap_ipf6;
-void iptap_bpf_tap(struct mbuf *m, u_int32_t proto, int outgoing);
+void iptap_bpf_tap(struct mbuf *m, u_int32_t proto, int outgoing);
-#define IPTAP_MAXUNIT IF_MAXUNIT
-#define IPTAP_ZONE_MAX_ELEM MIN(IFNETS_MAX, IPTAP_MAXUNIT)
+#define IPTAP_MAXUNIT IF_MAXUNIT
+#define IPTAP_ZONE_MAX_ELEM MIN(IFNETS_MAX, IPTAP_MAXUNIT)
-static struct if_clone iptap_cloner =
- IF_CLONE_INITIALIZER(IPTAP_IFNAME,
- iptap_clone_create,
- iptap_clone_destroy,
- 0,
- IPTAP_MAXUNIT,
- IPTAP_ZONE_MAX_ELEM,
- sizeof(struct iptap_softc));
+static struct if_clone iptap_cloner =
+ IF_CLONE_INITIALIZER(IPTAP_IFNAME,
+ iptap_clone_create,
+ iptap_clone_destroy,
+ 0,
+ IPTAP_MAXUNIT,
+ IPTAP_ZONE_MAX_ELEM,
+ sizeof(struct iptap_softc));
SYSCTL_DECL(_net_link);
-SYSCTL_NODE(_net_link, OID_AUTO, iptap, CTLFLAG_RW|CTLFLAG_LOCKED, 0,
+SYSCTL_NODE(_net_link, OID_AUTO, iptap, CTLFLAG_RW | CTLFLAG_LOCKED, 0,
"iptap virtual interface");
-static int iptap_total_tap_count = 0;
-SYSCTL_INT(_net_link_iptap, OID_AUTO, total_tap_count, CTLFLAG_RD | CTLFLAG_LOCKED,
- &iptap_total_tap_count, 0, "");
+static int iptap_total_tap_count = 0;
+SYSCTL_INT(_net_link_iptap, OID_AUTO, total_tap_count, CTLFLAG_RD | CTLFLAG_LOCKED,
+ &iptap_total_tap_count, 0, "");
static int iptap_log = 0;
SYSCTL_INT(_net_link_iptap, OID_AUTO, log, CTLFLAG_RW | CTLFLAG_LOCKED,
- &iptap_log, 0, "");
+ &iptap_log, 0, "");
#define IPTAP_LOG(fmt, ...) \
do { \
if ((iptap_log)) \
- printf("%s:%d " fmt, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
+ printf("%s:%d " fmt, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
} while(false)
__private_extern__ void
iptap_init(void)
{
errno_t error;
-
+
iptap_alloc_lock();
-
+
error = if_clone_attach(&iptap_cloner);
- if (error != 0)
+ if (error != 0) {
panic("%s: if_clone_attach() failed, error %d\n", __func__, error);
+ }
}
static void
{
lck_grp_attr_t *grp_attr;
lck_attr_t *attr;
-
+
grp_attr = lck_grp_attr_alloc_init();
lck_grp_attr_setdefault(grp_attr);
iptap_grp = lck_grp_alloc_init(IPTAP_IFNAME, grp_attr);
lck_grp_attr_free(grp_attr);
-
+
attr = lck_attr_alloc_init();
lck_attr_setdefault(attr);
-
+
lck_rw_init(&iptap_lck_rw, iptap_grp, attr);
lck_attr_free(attr);
}
int error = 0;
struct iptap_softc *iptap = NULL;
struct ifnet_init_eparams if_init;
-
+
iptap = if_clone_softc_allocate(&iptap_cloner);
if (iptap == NULL) {
printf("%s: _MALLOC failed\n", __func__);
iptap->iptap_unit = unit;
/*
- * We do not use a set_bpf_tap() function as we rather rely on the more
+ * We do not use a set_bpf_tap() function as we rather rely on the more
* accurate callback passed to bpf_attach()
*/
bzero(&if_init, sizeof(if_init));
if_init.ver = IFNET_INIT_CURRENT_VERSION;
- if_init.len = sizeof (if_init);
+ if_init.len = sizeof(if_init);
if_init.flags = IFNET_INIT_LEGACY;
if_init.name = ifc->ifc_name;
if_init.unit = unit;
printf("%s: ifnet_allocate failed, error %d\n", __func__, error);
goto done;
}
-
+
ifnet_set_flags(iptap->iptap_ifp, IFF_UP, IFF_UP);
-
+
error = ifnet_attach(iptap->iptap_ifp, NULL);
if (error != 0) {
printf("%s: ifnet_attach failed - error %d\n", __func__, error);
ifnet_release(iptap->iptap_ifp);
goto done;
}
-
- /*
+
+ /*
* Attach by default as DLT_PKTAP for packet metadata
* Provide DLT_RAW for legacy
*/
- bpf_attach(iptap->iptap_ifp, DLT_PKTAP, sizeof(struct pktap_header), NULL,
- iptap_tap_callback);
+ bpf_attach(iptap->iptap_ifp, DLT_PKTAP, sizeof(struct pktap_header), NULL,
+ iptap_tap_callback);
bpf_attach(iptap->iptap_ifp, DLT_RAW, 0, NULL,
- iptap_tap_callback);
-
+ iptap_tap_callback);
+
/* Take a reference and add to the global list */
ifnet_reference(iptap->iptap_ifp);
-
+
iptap_lock_exclusive();
-
- if (LIST_EMPTY(&iptap_list))
+
+ if (LIST_EMPTY(&iptap_list)) {
iptap_ipf_register();
+ }
LIST_INSERT_HEAD(&iptap_list, iptap, iptap_link);
iptap_lock_done();
done:
if (error != 0) {
- if (iptap != NULL)
+ if (iptap != NULL) {
if_clone_softc_deallocate(&iptap_cloner, iptap);
+ }
}
- return (error);
+ return error;
}
__private_extern__ int
int error = 0;
(void) ifnet_detach(ifp);
-
- return (error);
+
+ return error;
}
/*
goto done;
}
switch (dlt) {
- case DLT_RAW:
- if (direction == 0) {
- if (iptap->iptap_dlt_raw_count > 0) {
- iptap->iptap_dlt_raw_count--;
- OSAddAtomic(-1, &iptap_total_tap_count);
-
- }
- } else {
- iptap->iptap_dlt_raw_count++;
- OSAddAtomic(1, &iptap_total_tap_count);
+ case DLT_RAW:
+ if (direction == 0) {
+ if (iptap->iptap_dlt_raw_count > 0) {
+ iptap->iptap_dlt_raw_count--;
+ OSAddAtomic(-1, &iptap_total_tap_count);
}
- break;
- case DLT_PKTAP:
- if (direction == 0) {
- if (iptap->iptap_dlt_pkttap_count > 0) {
- iptap->iptap_dlt_pkttap_count--;
- OSAddAtomic(-1, &iptap_total_tap_count);
- }
- } else {
- iptap->iptap_dlt_pkttap_count++;
- OSAddAtomic(1, &iptap_total_tap_count);
+ } else {
+ iptap->iptap_dlt_raw_count++;
+ OSAddAtomic(1, &iptap_total_tap_count);
+ }
+ break;
+ case DLT_PKTAP:
+ if (direction == 0) {
+ if (iptap->iptap_dlt_pkttap_count > 0) {
+ iptap->iptap_dlt_pkttap_count--;
+ OSAddAtomic(-1, &iptap_total_tap_count);
}
- break;
+ } else {
+ iptap->iptap_dlt_pkttap_count++;
+ OSAddAtomic(1, &iptap_total_tap_count);
+ }
+ break;
}
done:
- /*
- * Attachements count must be positive and we're in trouble
+ /*
+ * Attachements count must be positive and we're in trouble
* if we have more that 2**31 attachements
*/
VERIFY(iptap_total_tap_count >= 0);
- return (0);
+ return 0;
}
__private_extern__ errno_t
#pragma unused(ifp)
mbuf_freem(m);
- return (ENOTSUP);
+ return ENOTSUP;
}
__private_extern__ errno_t
-iptap_demux(ifnet_t ifp, mbuf_t m, char *header,
- protocol_family_t *ppf)
+iptap_demux(ifnet_t ifp, mbuf_t m, char *header,
+ protocol_family_t *ppf)
{
#pragma unused(ifp)
#pragma unused(m)
#pragma unused(header)
#pragma unused(ppf)
- return (ENOTSUP);
+ return ENOTSUP;
}
__private_extern__ errno_t
#pragma unused(dmx)
#pragma unused(cnt)
- return (0);
+ return 0;
}
__private_extern__ errno_t
#pragma unused(ifp)
#pragma unused(pf)
- return (0);
+ return 0;
}
__private_extern__ errno_t
switch (ifd->ifd_cmd) {
case PKTP_CMD_TAP_COUNT: {
uint32_t tap_count = iptap->iptap_dlt_raw_count + iptap->iptap_dlt_pkttap_count;
-
+
if (ifd->ifd_len < sizeof(tap_count)) {
- printf("%s: PKTP_CMD_TAP_COUNT ifd_len %llu too small - error %d\n",
- __func__, ifd->ifd_len, error);
+ printf("%s: PKTP_CMD_TAP_COUNT ifd_len %llu too small - error %d\n",
+ __func__, ifd->ifd_len, error);
error = EINVAL;
break;
}
}
done:
- return (error);
+ return error;
}
__private_extern__ errno_t
goto done;
}
}
-
+
switch (cmd) {
case SIOCGDRVSPEC32: {
struct ifdrv64 ifd;
struct ifdrv32 *ifd32 = (struct ifdrv32 *)data;
-
+
memcpy(ifd.ifd_name, ifd32->ifd_name, sizeof(ifd.ifd_name));
ifd.ifd_cmd = ifd32->ifd_cmd;
ifd.ifd_len = ifd32->ifd_len;
ifd.ifd_data = ifd32->ifd_data;
-
+
error = iptap_getdrvspec(ifp, &ifd);
-
+
break;
}
case SIOCGDRVSPEC64: {
struct ifdrv64 *ifd64 = (struct ifdrv64 *)data;
-
+
error = iptap_getdrvspec(ifp, ifd64);
break;
break;
}
done:
- return (error);
+ return error;
}
__private_extern__ void
iptap_detach(ifnet_t ifp)
{
struct iptap_softc *iptap = NULL;
-
+
iptap_lock_exclusive();
iptap = ifp->if_softc;
ifp->if_softc = NULL;
LIST_REMOVE(iptap, iptap_link);
- if (LIST_EMPTY(&iptap_list))
+ if (LIST_EMPTY(&iptap_list)) {
iptap_ipf_unregister();
+ }
iptap_lock_done();
IPTAP_LOG("\n");
- bzero(&iptap_ipfinit, sizeof (iptap_ipfinit));
+ bzero(&iptap_ipfinit, sizeof(iptap_ipfinit));
iptap_ipfinit.name = IPTAP_IFNAME;
iptap_ipfinit.cookie = &iptap_ipf4;
iptap_ipfinit.ipf_input = iptap_ipf_input;
}
done:
- return (err);
+ return err;
}
static int
iptap_ipf6 = NULL;
}
done:
- return (err);
+ return err;
}
static errno_t
-iptap_ipf_input(void *arg, mbuf_t *mp, int off, u_int8_t proto)
+iptap_ipf_input(void *arg, mbuf_t *mp, int off, u_int8_t proto)
{
#pragma unused(off)
#pragma unused(proto)
- if (arg == (void *)&iptap_ipf4)
+ if (arg == (void *)&iptap_ipf4) {
iptap_bpf_tap(*mp, AF_INET, 0);
- else if (arg == (void *)&iptap_ipf6)
+ } else if (arg == (void *)&iptap_ipf6) {
iptap_bpf_tap(*mp, AF_INET6, 0);
- else
+ } else {
IPTAP_LOG("%s:%d bad cookie 0x%llx &iptap_ipf4 0x%llx "
"&iptap_ipf6 0x%llx\n", __func__, __LINE__,
(uint64_t)VM_KERNEL_ADDRPERM(arg),
(uint64_t)VM_KERNEL_ADDRPERM(&iptap_ipf4),
(uint64_t)VM_KERNEL_ADDRPERM(&iptap_ipf6));
+ }
- return (0);
+ return 0;
}
static errno_t
{
#pragma unused(opt)
- if (arg == (void *)&iptap_ipf4)
+ if (arg == (void *)&iptap_ipf4) {
iptap_bpf_tap(*mp, AF_INET, 1);
- else if (arg == (void *)&iptap_ipf6)
+ } else if (arg == (void *)&iptap_ipf6) {
iptap_bpf_tap(*mp, AF_INET6, 1);
- else
+ } else {
IPTAP_LOG("%s:%d bad cookie 0x%llx &iptap_ipf4 0x%llx "
"&iptap_ipf6 0x%llx\n", __func__, __LINE__,
(uint64_t)VM_KERNEL_ADDRPERM(arg),
(uint64_t)VM_KERNEL_ADDRPERM(&iptap_ipf4),
(uint64_t)VM_KERNEL_ADDRPERM(&iptap_ipf6));
+ }
- return (0);
+ return 0;
}
static void
}
__private_extern__ void
-iptap_bpf_tap(struct mbuf *m, u_int32_t proto, int outgoing)
+iptap_bpf_tap(struct mbuf *m, u_int32_t proto, int outgoing)
{
struct iptap_softc *iptap;
- void (*bpf_tap_func)(ifnet_t , u_int32_t , mbuf_t , void * , size_t ) =
- outgoing ? bpf_tap_out : bpf_tap_in;
+ void (*bpf_tap_func)(ifnet_t, u_int32_t, mbuf_t, void *, size_t ) =
+ outgoing ? bpf_tap_out : bpf_tap_in;
uint16_t src_scope_id = 0;
uint16_t dst_scope_id = 0;
iptap_lock_shared();
LIST_FOREACH(iptap, &iptap_list, iptap_link) {
- if (iptap->iptap_dlt_raw_count > 0) {
- bpf_tap_func(iptap->iptap_ifp, DLT_RAW, m,
- NULL, 0);
- }
- if (iptap->iptap_dlt_pkttap_count > 0) {
- struct {
- struct pktap_header hdr;
- u_int32_t proto;
- } hdr_buffer;
- struct pktap_header *hdr = &hdr_buffer.hdr;
- size_t hdr_size = sizeof(hdr_buffer);
- struct ifnet *ifp = outgoing ? NULL : m->m_pkthdr.rcvif;
-
- /* Verify the structure is packed */
- _CASSERT(sizeof(hdr_buffer) == sizeof(struct pktap_header) + sizeof(u_int32_t));
-
- bzero(hdr, sizeof(hdr_buffer));
- hdr->pth_length = sizeof(struct pktap_header);
- hdr->pth_type_next = PTH_TYPE_PACKET;
- hdr->pth_dlt = DLT_NULL;
- if (ifp != NULL)
- snprintf(hdr->pth_ifname, sizeof(hdr->pth_ifname), "%s",
- ifp->if_xname);
- hdr_buffer.proto = proto;
- hdr->pth_flags = outgoing ? PTH_FLAG_DIR_OUT : PTH_FLAG_DIR_IN;
- hdr->pth_protocol_family = proto;
- hdr->pth_frame_pre_length = 0;
- hdr->pth_frame_post_length = 0;
- hdr->pth_iftype = ifp != NULL ? ifp->if_type : 0;
- hdr->pth_ifunit = ifp != NULL ? ifp->if_unit : 0;
-
- pktap_fill_proc_info(hdr, proto, m, 0, outgoing, ifp);
-
- hdr->pth_svc = so_svc2tc(m->m_pkthdr.pkt_svc);
-
- bpf_tap_func(iptap->iptap_ifp, DLT_PKTAP, m, hdr, hdr_size);
+ if (iptap->iptap_dlt_raw_count > 0) {
+ bpf_tap_func(iptap->iptap_ifp, DLT_RAW, m,
+ NULL, 0);
+ }
+ if (iptap->iptap_dlt_pkttap_count > 0) {
+ struct {
+ struct pktap_header hdr;
+ u_int32_t proto;
+ } hdr_buffer;
+ struct pktap_header *hdr = &hdr_buffer.hdr;
+ size_t hdr_size = sizeof(hdr_buffer);
+ struct ifnet *ifp = outgoing ? NULL : m->m_pkthdr.rcvif;
+
+ /* Verify the structure is packed */
+ _CASSERT(sizeof(hdr_buffer) == sizeof(struct pktap_header) + sizeof(u_int32_t));
+
+ bzero(hdr, sizeof(hdr_buffer));
+ hdr->pth_length = sizeof(struct pktap_header);
+ hdr->pth_type_next = PTH_TYPE_PACKET;
+ hdr->pth_dlt = DLT_NULL;
+ if (ifp != NULL) {
+ snprintf(hdr->pth_ifname, sizeof(hdr->pth_ifname), "%s",
+ ifp->if_xname);
}
+ hdr_buffer.proto = proto;
+ hdr->pth_flags = outgoing ? PTH_FLAG_DIR_OUT : PTH_FLAG_DIR_IN;
+ hdr->pth_protocol_family = proto;
+ hdr->pth_frame_pre_length = 0;
+ hdr->pth_frame_post_length = 0;
+ hdr->pth_iftype = ifp != NULL ? ifp->if_type : 0;
+ hdr->pth_ifunit = ifp != NULL ? ifp->if_unit : 0;
+
+ pktap_fill_proc_info(hdr, proto, m, 0, outgoing, ifp);
+
+ hdr->pth_svc = so_svc2tc(m->m_pkthdr.pkt_svc);
+
+ bpf_tap_func(iptap->iptap_ifp, DLT_PKTAP, m, hdr, hdr_size);
+ }
}
-
+
iptap_lock_done();
-
+
if (proto == AF_INET6) {
struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);