]> git.saurik.com Git - apple/configd.git/blobdiff - Plugins/KernelEventMonitor/eventmon.c
configd-453.16.tar.gz
[apple/configd.git] / Plugins / KernelEventMonitor / eventmon.c
index 24946f3603acbf03d8213750f96d6f611553f7a7..c2cad274232cbc7d19cd99bfdd07c86709d001c3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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[] = {
        "",
@@ -69,6 +72,7 @@ static const char *inetEventName[] = {
        "INET broadcast address changed",
        "INET netmask changed",
        "INET ARP collision",
+       "INET port in use",
 };
 
 static const char *dlEventName[] = {
@@ -88,17 +92,17 @@ 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[] = {
@@ -109,14 +113,19 @@ 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)
@@ -131,9 +140,9 @@ ifflags_set(int s, char * name, short 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;
@@ -147,9 +156,9 @@ ifflags_clear(int s, char * name, short 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;
@@ -160,7 +169,7 @@ static void
 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);
@@ -170,20 +179,41 @@ static void
 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,
@@ -192,51 +222,41 @@ logEvent(CFStringRef evStr, struct kern_event_msg *ev_msg)
              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;
 }
 
@@ -247,7 +267,7 @@ processEvent_Apple_Network(struct kern_event_msg *ev_msg)
        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 : {
@@ -286,6 +306,18 @@ processEvent_Apple_Network(struct kern_event_msg *ev_msg)
                                                                 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;
@@ -360,17 +392,6 @@ processEvent_Apple_Network(struct kern_event_msg *ev_msg)
                                        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;
@@ -390,6 +411,21 @@ processEvent_Apple_Network(struct kern_event_msg *ev_msg)
                                        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 :
                                        /*
@@ -403,42 +439,48 @@ processEvent_Apple_Network(struct kern_event_msg *ev_msg)
                                        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 :
@@ -447,6 +489,10 @@ processEvent_Apple_Network(struct kern_event_msg *ev_msg)
                        }
                        break;
                }
+#endif // KEV_ND6_SUBCLASS
+               case KEV_LOG_SUBCLASS : {
+                       break;
+               }
                default :
                        handled = FALSE;
                        break;
@@ -464,27 +510,16 @@ processEvent_Apple_Network(struct kern_event_msg *ev_msg)
        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);
@@ -508,7 +543,10 @@ eventCallback(CFSocketRef s, CFSocketCallBackType type, CFDataRef address, const
                                                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 */
@@ -522,11 +560,12 @@ eventCallback(CFSocketRef s, CFSocketCallBackType type, CFDataRef address, const
                                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;
 
@@ -538,7 +577,6 @@ eventCallback(CFSocketRef s, CFSocketCallBackType type, CFDataRef address, const
 
 }
 
-
 __private_extern__
 void
 prime_KernelEventMonitor()
@@ -557,7 +595,7 @@ 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"),
@@ -587,35 +625,42 @@ prime_KernelEventMonitor()
         */
        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;
@@ -629,7 +674,7 @@ load_KernelEventMonitor(CFBundleRef bundle, Boolean bundleVerbose)
                                     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;
@@ -638,10 +683,10 @@ load_KernelEventMonitor(CFBundleRef bundle, Boolean bundleVerbose)
        /* 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));
@@ -670,11 +715,11 @@ load_KernelEventMonitor(CFBundleRef bundle, Boolean bundleVerbose)
        }
 
        /* 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);
@@ -705,12 +750,6 @@ load_KernelEventMonitor(CFBundleRef bundle, Boolean bundleVerbose)
 #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)
 {