/*
- * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2008, 2010, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include "ev_dlil.h"
#include "ev_ipv4.h"
#include "ev_ipv6.h"
-#include "ev_appletalk.h"
+#include <notify.h>
+
+// from ip_fw2.c
+#define KEV_LOG_SUBCLASS 10
static const char *inetEventName[] = {
"",
"INET broadcast address changed",
"INET netmask changed",
"INET ARP collision",
+ "INET port in use",
};
static const char *dlEventName[] = {
"KEV_DL_LINK_ON",
"KEV_DL_PROTO_ATTACHED",
"KEV_DL_PROTO_DETACHED",
-};
-
-static const char *atalkEventName[] = {
- "",
- "KEV_ATALK_ENABLED",
- "KEV_ATALK_DISABLED",
- "KEV_ATALK_ZONEUPDATED",
- "KEV_ATALK_ROUTERUP",
- "KEV_ATALK_ROUTERUP_INVALID",
- "KEV_ATALK_ROUTERDOWN",
- "KEV_ATALK_ZONELISTCHANGED"
+ "KEV_DL_LINK_ADDRESS_CHANGED",
+ "KEV_DL_WAKEFLAGS_CHANGED",
+#ifdef KEV_DL_IF_IDLE_ROUTE_REFCNT
+ "KEV_DL_IF_IDLE_ROUTE_REFCNT",
+#endif
+#ifdef KEV_DL_IFCAP_CHANGED
+ "KEV_DL_IFCAP_CHANGED",
+#endif
+#ifdef KEV_DL_LINK_QUALITY_METRIC_CHANGED
+ "KEV_DL_LINK_QUALITY_METRIC_CHANGED",
+#endif
};
static const char *inet6EventName[] = {
"KEV_INET6_NEW_LL_ADDR",
"KEV_INET6_NEW_RTADV_ADDR",
"KEV_INET6_DEFROUTER"
-
};
+#ifdef KEV_ND6_SUBCLASS
+static const char *nd6EventNameString[] = {
+ "",
+ "KEV_ND6_RA"
+};
+#endif // KEV_ND6_SUBCLASS
+__private_extern__ Boolean network_changed = FALSE;
__private_extern__ SCDynamicStoreRef store = NULL;
__private_extern__ Boolean _verbose = FALSE;
-
__private_extern__
int
dgram_socket(int domain)
int ret;
bzero(&ifr, sizeof(ifr));
- strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
ret = ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr);
- if (ret < 0) {
+ if (ret == -1) {
return (ret);
}
ifr.ifr_flags |= flags;
int ret;
bzero(&ifr, sizeof(ifr));
- strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
ret = ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr);
- if (ret < 0) {
+ if (ret == -1) {
return (ret);
}
ifr.ifr_flags &= ~flags;
mark_if_up(char * name)
{
int s = dgram_socket(AF_INET);
- if (s < 0)
+ if (s == -1)
return;
ifflags_set(s, name, IFF_UP);
close(s);
mark_if_down(char * name)
{
int s = dgram_socket(AF_INET);
- if (s < 0)
+ if (s == -1)
return;
ifflags_clear(s, name, IFF_UP);
close(s);
}
+static void
+post_network_changed(void)
+{
+ if (network_changed) {
+ uint32_t status;
+
+ status = notify_post("com.apple.system.config.network_change");
+ if (status != NOTIFY_STATUS_OK) {
+ SCLog(TRUE, LOG_ERR, CFSTR("notify_post() failed: error=%ld"), status);
+ }
+
+ network_changed = FALSE;
+ }
+
+ return;
+}
+
static void
logEvent(CFStringRef evStr, struct kern_event_msg *ev_msg)
{
int i;
int j;
- SCLog(_verbose, LOG_DEBUG, CFSTR("%@ event:"), evStr);
- SCLog(_verbose, LOG_DEBUG,
+ if (!_verbose) {
+ return;
+ }
+
+ SCLog(TRUE, LOG_DEBUG, CFSTR("%@ event:"), evStr);
+ SCLog(TRUE, LOG_DEBUG,
CFSTR(" Event size=%d, id=%d, vendor=%d, class=%d, subclass=%d, code=%d"),
ev_msg->total_size,
ev_msg->id,
ev_msg->kev_subclass,
ev_msg->event_code);
for (i = 0, j = KEV_MSG_HEADER_SIZE; j < ev_msg->total_size; i++, j+=4) {
- SCLog(_verbose, LOG_DEBUG, CFSTR(" Event data[%2d] = %08lx"), i, ev_msg->event_data[i]);
+ SCLog(TRUE, LOG_DEBUG, CFSTR(" Event data[%2d] = %08lx"), i, ev_msg->event_data[i]);
}
}
static const char *
-inetEventNameString(u_long event_code)
+inetEventNameString(uint32_t event_code)
{
- if (event_code <= KEV_INET_ARPCOLLISION) {
+ if (event_code < sizeof(inetEventName) / sizeof(inetEventName[0])) {
return (inetEventName[event_code]);
}
return ("New Apple network INET subcode");
}
static const char *
-inet6EventNameString(u_long event_code)
+inet6EventNameString(uint32_t event_code)
{
- if (event_code <= KEV_INET6_DEFROUTER) {
+ if (event_code < sizeof(inet6EventName) / sizeof(inet6EventName[0])) {
return (inet6EventName[event_code]);
}
return ("New Apple network INET6 subcode");
}
static const char *
-dlEventNameString(u_long event_code)
+dlEventNameString(uint32_t event_code)
{
- if (event_code <= KEV_DL_PROTO_DETACHED) {
+ if (event_code < sizeof(dlEventName) / sizeof(dlEventName[0])) {
return (dlEventName[event_code]);
}
return ("New Apple network DL subcode");
}
-static const char *
-atalkEventNameString(u_long event_code)
-{
- if (event_code <= KEV_ATALK_ZONELISTCHANGED) {
- return (atalkEventName[event_code]);
- }
- return ("New Apple network AppleTalk subcode");
-}
-
-
static void
copy_if_name(struct net_event_data * ev, char * ifr_name, int ifr_len)
{
- snprintf(ifr_name, ifr_len, "%s%ld", ev->if_name, ev->if_unit);
+ snprintf(ifr_name, ifr_len, "%s%d", ev->if_name, ev->if_unit);
return;
}
int dataLen = (ev_msg->total_size - KEV_MSG_HEADER_SIZE);
void * event_data = &ev_msg->event_data[0];
Boolean handled = TRUE;
- char ifr_name[IFNAMSIZ+1];
+ char ifr_name[IFNAMSIZ];
switch (ev_msg->kev_subclass) {
case KEV_INET_SUBCLASS : {
ev->hw_addr);
break;
}
+#if !TARGET_OS_IPHONE
+ case KEV_INET_PORTINUSE : {
+ struct kev_in_portinuse * ev;
+ ev = (struct kev_in_portinuse *)event_data;
+ if (dataLen < sizeof(*ev)) {
+ handled = FALSE;
+ break;
+ }
+ port_in_use_ipv4(ev->port, ev->req_pid);
+ break;
+ }
+#endif /* !TARGET_OS_IPHONE */
default :
handled = FALSE;
break;
interface_detaching(ifr_name);
break;
- case KEV_DL_SIFFLAGS :
- case KEV_DL_SIFMETRICS :
- case KEV_DL_SIFMTU :
- case KEV_DL_SIFPHYS :
- case KEV_DL_SIFMEDIA :
- case KEV_DL_SIFGENERIC :
- case KEV_DL_ADDMULTI :
- case KEV_DL_DELMULTI :
- handled = FALSE;
- break;
-
case KEV_DL_PROTO_ATTACHED :
case KEV_DL_PROTO_DETACHED : {
struct kev_dl_proto_data * protoEvent;
break;
}
+#ifdef KEV_DL_IF_IDLE_ROUTE_REFCNT
+ case KEV_DL_IF_IDLE_ROUTE_REFCNT: {
+ /*
+ * interface route refcnt idle
+ */
+ if (dataLen < sizeof(*ev)) {
+ handled = FALSE;
+ break;
+ }
+ copy_if_name(ev, ifr_name, sizeof(ifr_name));
+ interface_update_idle_state(ifr_name);
+ break;
+ }
+#endif // KEV_DL_IF_IDLE_ROUTE_REFCNT
+
case KEV_DL_LINK_OFF :
case KEV_DL_LINK_ON :
/*
link_update_status(ifr_name, FALSE);
break;
+#ifdef KEV_DL_LINK_QUALITY_METRIC_CHANGED
+ case KEV_DL_LINK_QUALITY_METRIC_CHANGED: {
+ struct kev_dl_link_quality_metric_data * lqm_data;
+ lqm_data = (struct kev_dl_link_quality_metric_data *) event_data;
+
+ if (dataLen < sizeof(*ev)) {
+ handled = FALSE;
+ break;
+ }
+ copy_if_name(ev, ifr_name, sizeof(ifr_name));
+ interface_update_quality_metric(ifr_name,
+ lqm_data->link_quality_metric);
+ break;
+ }
+#endif // KEV_DL_LINK_QUALITY_METRIC_CHANGED
+
+ case KEV_DL_SIFFLAGS :
+ case KEV_DL_SIFMETRICS :
+ case KEV_DL_SIFMTU :
+ case KEV_DL_SIFPHYS :
+ case KEV_DL_SIFMEDIA :
+ case KEV_DL_SIFGENERIC :
+ case KEV_DL_ADDMULTI :
+ case KEV_DL_DELMULTI :
+ case KEV_DL_LINK_ADDRESS_CHANGED :
+ case KEV_DL_WAKEFLAGS_CHANGED :
+#ifdef KEV_DL_IFCAP_CHANGED
+ case KEV_DL_IFCAP_CHANGED :
+#endif // KEV_DL_IFCAP_CHANGED
+ break;
+
default :
handled = FALSE;
break;
}
break;
}
- case KEV_ATALK_SUBCLASS: {
- struct kev_atalk_data * ev;
-
- eventName = atalkEventNameString(ev_msg->event_code);
- ev = (struct kev_atalk_data *)event_data;
- if (dataLen < sizeof(*ev)) {
- handled = FALSE;
- break;
- }
- copy_if_name(&ev->link_data, ifr_name, sizeof(ifr_name));
+#ifdef KEV_ND6_SUBCLASS
+ case KEV_ND6_SUBCLASS : {
+ eventName = nd6EventNameString(ev_msg->event_code);
switch (ev_msg->event_code) {
- case KEV_ATALK_ENABLED:
- interface_update_atalk_address(ev, ifr_name);
- break;
-
- case KEV_ATALK_DISABLED:
- interface_update_shutdown_atalk();
- break;
-
- case KEV_ATALK_ZONEUPDATED:
- interface_update_atalk_zone(ev, ifr_name);
- break;
-
- case KEV_ATALK_ROUTERUP:
- case KEV_ATALK_ROUTERUP_INVALID:
- case KEV_ATALK_ROUTERDOWN:
- interface_update_appletalk(NULL, ifr_name);
- break;
-
- case KEV_ATALK_ZONELISTCHANGED:
+ case KEV_KEV_ND6_RA :
break;
default :
}
break;
}
+#endif // KEV_ND6_SUBCLASS
+ case KEV_LOG_SUBCLASS : {
+ break;
+ }
default :
handled = FALSE;
break;
return;
}
-
-static void
-processEvent_Apple_IOKit(struct kern_event_msg *ev_msg)
-{
- switch (ev_msg->kev_subclass) {
- default :
- logEvent(CFSTR("New Apple IOKit subclass"), ev_msg);
- break;
- }
-
- return;
-}
-
-
static void
eventCallback(CFSocketRef s, CFSocketCallBackType type, CFDataRef address, const void *data, void *info)
{
int so = CFSocketGetNative(s);
int status;
- char buf[1024];
- struct kern_event_msg *ev_msg = (struct kern_event_msg *)&buf[0];
+ union {
+ char bytes[1024];
+ struct kern_event_msg ev_msg1; // first kernel event
+ } buf;
+ struct kern_event_msg *ev_msg = &buf.ev_msg1;
int offset = 0;
status = recv(so, &buf, sizeof(buf), 0);
processEvent_Apple_Network(ev_msg);
break;
case KEV_IOKIT_CLASS :
- processEvent_Apple_IOKit(ev_msg);
+ case KEV_SYSTEM_CLASS :
+ case KEV_APPLESHARE_CLASS :
+ case KEV_FIREWALL_CLASS :
+ case KEV_IEEE80211_CLASS :
break;
default :
/* unrecognized (Apple) event class */
break;
}
offset += ev_msg->total_size;
- ev_msg = (struct kern_event_msg *)&buf[offset];
+ ev_msg = (struct kern_event_msg *)(void *)&buf.bytes[offset];
}
cache_write(store);
cache_close();
+ post_network_changed();
return;
}
-
__private_extern__
void
prime_KernelEventMonitor()
goto done;
}
- if (getifaddrs(&ifap) < 0) {
+ if (getifaddrs(&ifap) == -1) {
SCLog(TRUE,
LOG_ERR,
CFSTR("could not get interface info, getifaddrs() failed: %s"),
*/
interface_update_ipv6(ifap, NULL);
- /*
- * update AppleTalk network addresses already assigned
- * to the interfaces.
- */
- interface_update_appletalk(ifap, NULL);
-
freeifaddrs(ifap);
done:
- if (sock >= 0)
+ if (sock != -1)
close(sock);
cache_write(store);
cache_close();
+ network_changed = TRUE;
+ post_network_changed();
+
return;
}
+static CFStringRef
+kevSocketCopyDescription(const void *info)
+{
+ return CFStringCreateWithFormat(NULL, NULL, CFSTR("<kernel event socket>"));
+}
__private_extern__
void
load_KernelEventMonitor(CFBundleRef bundle, Boolean bundleVerbose)
{
- int so;
- int status;
- struct kev_request kev_req;
+ CFSocketContext context = { 0
+ , (void *)1
+ , NULL
+ , NULL
+ , kevSocketCopyDescription
+ };
CFSocketRef es;
- CFSocketContext context = { 0, NULL, NULL, NULL, NULL };
+ struct kev_request kev_req;
CFRunLoopSourceRef rls;
+ int so;
+ int status;
if (bundleVerbose) {
_verbose = TRUE;
CFSTR("Kernel Event Monitor plug-in"),
NULL,
NULL);
- if (!store) {
+ if (store == NULL) {
SCLog(TRUE, LOG_ERR, CFSTR("SCDnamicStoreCreate() failed: %s"), SCErrorString(SCError()));
SCLog(TRUE, LOG_ERR, CFSTR("kernel event monitor disabled."));
return;
/* Open an event socket */
so = socket(PF_SYSTEM, SOCK_RAW, SYSPROTO_EVENT);
if (so != -1) {
- /* establish filter to return all events */
- kev_req.vendor_code = 0;
- kev_req.kev_class = 0; /* Not used if vendor_code is 0 */
- kev_req.kev_subclass = 0; /* Not used if either kev_class OR vendor_code are 0 */
+ /* establish filter to return events of interest */
+ kev_req.vendor_code = KEV_VENDOR_APPLE;
+ kev_req.kev_class = KEV_NETWORK_CLASS;
+ kev_req.kev_subclass = KEV_ANY_SUBCLASS;
status = ioctl(so, SIOCSKEVFILT, &kev_req);
if (status) {
SCLog(TRUE, LOG_ERR, CFSTR("could not establish event filter, ioctl() failed: %s"), strerror(errno));
}
/* Create a CFSocketRef for the PF_SYSTEM kernel event socket */
- es = CFSocketCreateWithNative(NULL,
- so,
- kCFSocketReadCallBack,
- eventCallback,
- &context);
+ es = CFSocketCreateWithNative(NULL,
+ so,
+ kCFSocketReadCallBack,
+ eventCallback,
+ &context);
/* Create and add a run loop source for the event socket */
rls = CFSocketCreateRunLoopSource(NULL, es, 0);
#undef getIF
#undef updateStore
-#define getIF getIF_at
-#define updateStore updateStore_at
-#include "ev_appletalk.c"
-#undef getIF
-#undef updateStore
-
int
main(int argc, char **argv)
{