My interface filter NKE tries to attach to "en1" while the link is down, but still advertised by ifnet_find_by_name() or ifnet_list_get(). While my nke is attached, Airport will not transition to IFF_RUNNING, even after "turning airport on." As soon as I detatch my nke from en1, Airport begins functioning again.
Sample code is below. Thank you for your time.
regards, Brendan
//////////////////////////////////////////////////////////////////////////////
static interface_filter_t filter_ref = NULL;
static struct iff_filter enet_filter;
static char if_name[DEV_NAME_LEN];
bool init_filter()
{
enet_filter.iff_cookie = NULL;
enet_filter.iff_name = MY_BUNDLE_ID;
enet_filter.iff_protocol = 0; // intercept packets with any protocol value
enet_filter.iff_input = b_enet_input_func;
enet_filter.iff_output = b_enet_output_func;
enet_filter.iff_event = b_enet_event_func;
enet_filter.iff_ioctl = b_enet_ioctl_func;
enet_filter.iff_detached = b_enet_detached_func;
bzero(if_name, sizeof(if_name));
strncpy(if_name, "en1", sizeof(if_name));
ifnet_t netif = NULL;
errno_t rv;
rv = ifnet_find_by_name(if_name, &netif);
if (rv != KERN_SUCCESS) {
printf("%s - ifnet_find_by_name(%s), err=%d\n",
__FUNCTION__, if_name, rv);
return false;
}
rv = iflt_attach(netif, &enet_filter, &filter_ref);
// release the reference on the interface
if (netif) {
ifnet_release(netif);
netif = NULL;
}
if (rv != KERN_SUCCESS) {
printf("%s - Failed to attach to %s (err=%d)\n", __FUNCTION__, if_name, rv);
filter_ref = NULL;
return false;
} else {
printf("%s - Successfully attached to %s\n", __FUNCTION__, if_name);
}
return true;
}
void detatch()
{
if (filter_ref) {
printf("%s - detatching from %s\n", __FUNCTION__, if_name);
iflt_detach(filter_ref);
filter_ref = NULL;
}
}
extern "C" {
static errno_t
b_enet_input_func(void* cookie, ifnet_t interface, protocol_family_t protocol,
mbuf_t *m, char **frame_ptr)
{
return KERN_SUCCESS; // pass through packet
}
static errno_t
b_enet_output_func(void* cookie, ifnet_t interface,
protocol_family_t protocol, mbuf_t *m)
{
return KERN_SUCCESS; // pass through packet
}
static void
b_enet_detached_func(void* cookie, ifnet_t interface)
{
detatch();
}
static void
b_enet_event_func(void* cookie, ifnet_t interface, protocol_family_t protocol,
const struct kev_msg *event_msg)
{
// Data-link event
if (event_msg->vendor_code == KEV_VENDOR_APPLE &&
event_msg->kev_class == KEV_NETWORK_CLASS &&
event_msg->kev_subclass == KEV_DL_SUBCLASS)
{
if (event_msg->event_code == KEV_DL_LINK_OFF) {
detatch();
}
}
printf("filter (%s) event: vendor %u, class %u, subclass %u, code %u\n",
if_name, event_msg->vendor_code, event_msg->kev_class,
event_msg->kev_subclass, event_msg->event_code);
}
static errno_t
b_enet_ioctl_func(void* cookie, ifnet_t interface, protocol_family_t protocol,
u_long ioctl_cmd, void* ioctl_arg)
{
const uint8_t basecmd = (uint8_t) (IOCBASECMD(ioctl_cmd) & 0xff);
printf("enet_ioctl() - if=%p, proto=%u, "
"base_cmd=%u, grp='%c', len=%u\n",
interface, protocol, basecmd,
(char)IOCGROUP(ioctl_cmd),
(uint32_t)IOCPARM_LEN(ioctl_cmd));
return KERN_SUCCESS;
}
};