]> git.saurik.com Git - apple/configd.git/blobdiff - Plugins/InterfaceNamer/ifnamer.c
configd-204.tar.gz
[apple/configd.git] / Plugins / InterfaceNamer / ifnamer.c
index a0a96207dd89bf3870ae24fd6f9d4d77f1142fba..6d94985b9c68a821c02e83945e748745633db3ee 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2001-2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2001-2007 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 /*
  * Modification History
  *
 /*
  * Modification History
  *
+ * November 6, 2006            Allan Nathanson <ajn@apple.com>
+ *                             Dan Markarian <markarian@apple.com>
+ *                             Dieter Siegmund <dieter@apple.com>
+ * - updated code to name interfaces quicker (without need for
+ *   calling IOKitWaitQuiet).
+ *
  * October 3, 2003             Allan Nathanson <ajn@apple.com>
  * - sort new interfaces by IOKit path (rather than MAC address) to
  *   help facilitate a more predictable interface-->name mapping for
  * October 3, 2003             Allan Nathanson <ajn@apple.com>
  * - sort new interfaces by IOKit path (rather than MAC address) to
  *   help facilitate a more predictable interface-->name mapping for
@@ -56,6 +62,7 @@
 #include <sys/stat.h>
 #include <sys/param.h>
 #include <mach/mach.h>
 #include <sys/stat.h>
 #include <sys/param.h>
 #include <mach/mach.h>
+#include <net/ethernet.h>
 #include <net/if_types.h>
 
 #include <CoreFoundation/CoreFoundation.h>
 #include <net/if_types.h>
 
 #include <CoreFoundation/CoreFoundation.h>
 #include <SystemConfiguration/SCPrivate.h>     // for SCLog(), SCPrint()
 #include <SystemConfiguration/SCValidation.h>
 
 #include <SystemConfiguration/SCPrivate.h>     // for SCLog(), SCPrint()
 #include <SystemConfiguration/SCValidation.h>
 
-#include <SystemConfiguration/BondConfiguration.h>
-#include <SystemConfiguration/BondConfigurationPrivate.h>
-
-#include <SystemConfiguration/VLANConfiguration.h>
-#include <SystemConfiguration/VLANConfigurationPrivate.h>
-
 #include <IOKit/IOKitLib.h>
 #include <IOKit/IOBSD.h>
 #include <IOKit/IOKitLib.h>
 #include <IOKit/IOBSD.h>
+#include <IOKit/IOMessage.h>
 #include <IOKit/network/IONetworkController.h>
 #include <IOKit/network/IONetworkInterface.h>
 
 #include <IOKit/network/IONetworkController.h>
 #include <IOKit/network/IONetworkInterface.h>
 
 #define        kIOBuiltin                      "IOBuiltin"
 #endif
 
 #define        kIOBuiltin                      "IOBuiltin"
 #endif
 
-#ifndef        kIOLocation
-#define        kIOLocation                     "IOLocation"
-#endif
-
 #define kIONetworkStackUserCommand     "IONetworkStackUserCommand"
 #define kIONetworkStackUserCommand     "IONetworkStackUserCommand"
-#define kIORegisterOne                 1
+#define kRegisterInterface             1
+
+#define        kSCNetworkInterfaceType         "SCNetworkInterfaceType"
+#define        kSCNetworkInterfaceActive       "Active"
 
 #define MY_PLUGIN_NAME                 "InterfaceNamer"
 
 #define MY_PLUGIN_NAME                 "InterfaceNamer"
+#define        MY_PLUGIN_ID                    CFSTR("com.apple.SystemConfiguration." MY_PLUGIN_NAME)
 
 
-static boolean_t                       S_debug = FALSE;
-static CFMutableArrayRef               S_dblist = NULL;
-static io_connect_t                    S_connect = MACH_PORT_NULL;
-static io_iterator_t                   S_iter = MACH_PORT_NULL;
-static IONotificationPortRef           S_notify = NULL;
+#define WAIT_QUIET_TIMEOUT_KEY         "WaitQuietTimeout"
+#define WAIT_QUIET_TIMEOUT_DEFAULT     60.0
 
 
-static void
-writeInterfaceList(CFArrayRef ilist);
+/*
+ * S_connect
+ *   "IONetworkStack" connect object used to "name" an interface.
+ */
+static io_connect_t            S_connect               = MACH_PORT_NULL;
 
 
-static void
-displayInterface(CFDictionaryRef if_dict);
+/*
+ * S_dblist
+ *   An array of CFDictionary's representing the interfaces
+ *   that have been identified and [need to be] named.
+ */
+static CFMutableArrayRef       S_dblist                = NULL;
 
 
-static CFDictionaryRef
-lookupIOKitPath(CFStringRef if_path);
+/*
+ * S_debug
+ *   A boolean that enables additional logging.
+ */
+static boolean_t               S_debug                 = FALSE;
+
+/*
+ * S_iflist
+ *   An array of SCNetworkInterface's representing the
+ *   interfaces that have been identified.
+ */
+static CFMutableArrayRef       S_iflist                = NULL;
+
+/*
+ * S_iter
+ *   IOServiceAddMatchingNotification object used to watch for
+ *   new network interfaces.
+ */
+static io_iterator_t           S_iter                  = MACH_PORT_NULL;
+
+/*
+ * S_notify
+ *   notification object for receiving IOKit notifications of
+ *   new devices or state changes.
+ */
+static IONotificationPortRef   S_notify                = NULL;
+
+/* S_prev_active_list
+ *   An array of CFDictionary's representing the previously
+ *   named interfaces.
+ */
+static CFMutableArrayRef       S_prev_active_list      = NULL;
+
+/*
+ * S_quiet
+ *   IOServiceAddInterestNotification object used to watch for
+ *   IOKit matching to quiesce.
+ */
+static io_object_t             S_quiet                 = MACH_PORT_NULL;
+
+/*
+ * S_stack
+ *   IOServiceAddMatchingNotification object used to watch for
+ *   the availability of the "IONetworkStack" object.
+ */
+static io_iterator_t           S_stack                 = MACH_PORT_NULL;
 
 
-static __inline__ CFComparisonResult
-compareMacAddress(CFDataRef addr1, CFDataRef addr2)
+/*
+ * S_state
+ *   A dictionary containing Information about each network
+ *   interface.  For now, the key is the BSD name and the
+ *   value is a CFNumber noting how long (in milliseconds)
+ *   it took for the interface to be recognized/named.
+ */
+static CFMutableDictionaryRef  S_state                 = NULL;
+
+/*
+ * S_timer
+ *   CFRunLoopTimer tracking how long we are willing to wait
+ *   for IOKit matching to quiesce (IOKitWaitQuiet).
+ */
+static CFRunLoopTimerRef       S_timer                 = NULL;
+
+/*
+ * Virtual network interface configuration
+ *   S_prefs : SCPreferences to configuration
+ *   S_bonds : most recently actived Bond configuration
+ *   S_vlans : most recently actived VLAN configuration
+ */
+static SCPreferencesRef                S_prefs                 = NULL;
+static CFArrayRef              S_bonds                 = NULL;
+static CFArrayRef              S_vlans                 = NULL;
+
+static void
+addTimestamp(CFMutableDictionaryRef dict, CFStringRef key)
 {
 {
-    int len1;
-    int len2;
-    int clen;
-    int res;
-
-    len1 = CFDataGetLength(addr1);
-    len2 = CFDataGetLength(addr2);
-
-    if (len1 == len2) {
-       if (len1 == 0)
-           return (kCFCompareEqualTo);
-       return (memcmp(CFDataGetBytePtr(addr1),
-                      CFDataGetBytePtr(addr2),
-                      len1));
-    }
-    clen = len1;
-    if (len2 < clen)
-       clen = len2;
-    res = memcmp(CFDataGetBytePtr(addr1),
-                CFDataGetBytePtr(addr2),
-                clen);
-    if (res == 0) {
-       return (len1 - len2);
-    }
-    return (res);
+    CFAbsoluteTime     now;
+    CFNumberRef                val;
+
+    now = CFAbsoluteTimeGetCurrent();
+    val = CFNumberCreate(NULL, kCFNumberDoubleType, &now);
+    CFDictionaryAddValue(dict, key, val);
+    CFRelease(val);
+    return;
 }
 
 static CFComparisonResult
 }
 
 static CFComparisonResult
@@ -158,249 +217,16 @@ if_unit_compare(const void *val1, const void *val2, void *context)
     return (CFNumberCompare(unit1, unit2, NULL));
 }
 
     return (CFNumberCompare(unit1, unit2, NULL));
 }
 
-static CFArrayRef
-split_path(CFStringRef path)
-{
-       CFArrayRef              components;
-       CFMutableStringRef      nPath;
-
-       // turn '@'s into '/'s
-       nPath = CFStringCreateMutableCopy(NULL, 0, path);
-       (void) CFStringFindAndReplace(nPath,
-                                     CFSTR("@"),
-                                     CFSTR("/"),
-                                     CFRangeMake(0, CFStringGetLength(nPath)),
-                                     0);
-
-       // split path into components to be compared
-       components = CFStringCreateArrayBySeparatingStrings(NULL, nPath, CFSTR("/"));
-       CFRelease(nPath);
-
-       return components;
-}
-
-
-static CFComparisonResult
-if_path_compare(const void *val1, const void *val2, void *context)
-{
-    CFBooleanRef       builtin;
-    Boolean            builtin_val1    = FALSE;
-    Boolean            builtin_val2    = FALSE;
-    CFArrayRef         elements1       = NULL;
-    CFArrayRef         elements2       = NULL;
-    CFIndex            i;
-    CFIndex            n;
-    CFIndex            n1              = 0;
-    CFIndex            n2              = 0;
-    CFStringRef                path;
-    CFComparisonResult res;
-    CFNumberRef                type1;
-    CFNumberRef                type2;
-
-    /* sort by interface type */
-
-    type1 = CFDictionaryGetValue((CFDictionaryRef)val1, CFSTR(kIOInterfaceType));
-    type2 = CFDictionaryGetValue((CFDictionaryRef)val2, CFSTR(kIOInterfaceType));
-    res = CFNumberCompare(type1, type2, NULL);
-    if (res != kCFCompareEqualTo) {
-       return (res);
-    }
-
-    /* built-in interfaces sort first */
-    builtin = CFDictionaryGetValue((CFDictionaryRef)val1, CFSTR(kIOBuiltin));
-    if (isA_CFBoolean(builtin) != NULL) {
-       builtin_val1 = CFBooleanGetValue(builtin);
-    }
-    builtin = CFDictionaryGetValue((CFDictionaryRef)val2, CFSTR(kIOBuiltin));
-    if (isA_CFBoolean(builtin) != NULL) {
-       builtin_val2 = CFBooleanGetValue(builtin);
-    }
-    if (builtin_val1 != builtin_val2) {
-       if (builtin_val1) {
-           res = kCFCompareLessThan;
-       } else {
-           res = kCFCompareGreaterThan;
-       }
-       return (res);
-    }
-
-    /* ... and then sort built-in interfaces by "location" */
-    if (builtin_val1) {
-       CFStringRef     location1;
-       CFStringRef     location2;
-
-       location1 = CFDictionaryGetValue((CFDictionaryRef)val1, CFSTR(kIOLocation));
-       location2 = CFDictionaryGetValue((CFDictionaryRef)val2, CFSTR(kIOLocation));
-       if (location1 != location2) {
-           if (isA_CFString(location1)) {
-               if (isA_CFString(location2)) {
-                   res = CFStringCompare(location1, location2, 0);
-               } else {
-                   res = kCFCompareLessThan;
-               }
-           } else {
-               res = kCFCompareGreaterThan;
-           }
-
-           if (res != kCFCompareEqualTo) {
-               return (res);
-           }
-       }
-    }
-
-    /* ... and then sort by IOPathMatch */
-
-    path = CFDictionaryGetValue((CFDictionaryRef)val1, CFSTR(kIOPathMatchKey));
-    if (isA_CFString(path)) {
-       elements1 = split_path(path);
-       n1 = CFArrayGetCount(elements1);
-    } else {
-       goto done;
-    }
-
-    path = CFDictionaryGetValue((CFDictionaryRef)val2, CFSTR(kIOPathMatchKey));
-    if (isA_CFString(path)) {
-       elements2 = split_path(path);
-       n2 = CFArrayGetCount(elements2);
-    } else {
-       goto done;
-    }
-
-    n = (n1 <= n2) ? n1 : n2;
-    for (i = 0; i < n; i++) {
-       CFStringRef     e1;
-       CFStringRef     e2;
-       char            *end;
-       quad_t          q1;
-       quad_t          q2;
-       char            *str;
-       Boolean         isNum;
-
-       e1 = CFArrayGetValueAtIndex(elements1, i);
-       e2 = CFArrayGetValueAtIndex(elements2, i);
-
-       str = _SC_cfstring_to_cstring(e1, NULL, 0, kCFStringEncodingASCII);
-       errno = 0;
-       q1 = strtoq(str, &end, 16);
-       isNum = ((*str != '\0') && (*end == '\0') && (errno == 0));
-       CFAllocatorDeallocate(NULL, str);
-
-       if (isNum) {
-           // if e1 is a valid numeric string
-           str = _SC_cfstring_to_cstring(e2, NULL, 0, kCFStringEncodingASCII);
-           errno = 0;
-           q2 = strtoq(str, &end, 16);
-           isNum = ((*str != '\0') && (*end == '\0') && (errno == 0));
-           CFAllocatorDeallocate(NULL, str);
-
-           if (isNum) {
-               // if e2 is also a valid numeric string
-
-               if (q1 == q2) {
-                   res = kCFCompareEqualTo;
-                   continue;
-               } else if (q1 < q2) {
-                   res = kCFCompareLessThan;
-               } else {
-                   res = kCFCompareGreaterThan;
-               }
-               break;
-           }
-       }
-
-       res = CFStringCompare(e1, e2, 0);
-       if (res != kCFCompareEqualTo) {
-           break;
-       }
-    }
-
-    if (res == kCFCompareEqualTo) {
-       if (n1 < n2) {
-           res = kCFCompareLessThan;
-       } else if (n1 < n2) {
-           res = kCFCompareGreaterThan;
-       }
-    }
-
- done :
-    if ( elements1 ) CFRelease( elements1 );
-    if ( elements2 ) CFRelease( elements2 );
-
-    return res;
-}
-
-static boolean_t
-addCFStringProperty( CFMutableDictionaryRef dict,
-                    const char *           key,
-                    const char *           string )
-{
-    boolean_t    ret = false;
-    CFStringRef  valObj, keyObj;
-
-    if ( (string == 0) || (key == 0) || (dict == 0) )
-       return false;
-
-    keyObj = CFStringCreateWithCString(NULL,
-                                      key,
-                                      kCFStringEncodingASCII );
-
-    valObj = CFStringCreateWithCString(NULL,
-                                      string,
-                                      kCFStringEncodingASCII );
-
-    if (valObj && keyObj) {
-       CFDictionarySetValue( dict, keyObj, valObj );
-       ret = true;
-    }
-
-    if ( keyObj ) CFRelease( keyObj );
-    if ( valObj ) CFRelease( valObj );
-
-    return ret;
-}
-
-static boolean_t
-addCFNumberProperty( CFMutableDictionaryRef dict,
-                    const char *           key,
-                    unsigned int           number )
-{
-    boolean_t    ret = false;
-    CFNumberRef  numObj;
-    CFStringRef  keyObj;
-
-    if ( (key == 0) || (dict == 0) )
-       return false;
-
-    numObj = CFNumberCreate(NULL,
-                           kCFNumberLongType,
-                           &number);
-
-    keyObj = CFStringCreateWithCString(NULL,
-                                      key,
-                                      kCFStringEncodingASCII );
-
-    if ( numObj && keyObj )
-       {
-           CFDictionarySetValue( dict, keyObj, numObj );
-           ret = true;
-       }
-
-    if ( numObj ) CFRelease( numObj );
-    if ( keyObj ) CFRelease( keyObj );
-
-    return ret;
-}
-
 static void *
 read_file(char * filename, size_t * data_length)
 {
 static void *
 read_file(char * filename, size_t * data_length)
 {
-    void *             data = NULL;
-    size_t             len = 0;
-    int                        fd = -1;
+    void *             data    = NULL;
+    size_t             len     = 0;
+    int                        fd      = -1;
     struct stat                sb;
 
     *data_length = 0;
     struct stat                sb;
 
     *data_length = 0;
-    if (stat(filename, &sb) < 0)
+    if (stat(filename, &sb) == -1)
        goto done;
     len = sb.st_size;
     if (len == 0)
        goto done;
     len = sb.st_size;
     if (len == 0)
@@ -411,17 +237,18 @@ read_file(char * filename, size_t * data_length)
        goto done;
 
     fd = open(filename, O_RDONLY);
        goto done;
 
     fd = open(filename, O_RDONLY);
-    if (fd < 0)
+    if (fd == -1)
        goto done;
 
     if (read(fd, data, len) != len) {
        goto done;
 
     if (read(fd, data, len) != len) {
-       SCLog(TRUE, LOG_INFO,
+       SCLog(TRUE, LOG_ERR,
              CFSTR(MY_PLUGIN_NAME ": read %s failed, %s"),
              filename, strerror(errno));
        goto done;
     }
              CFSTR(MY_PLUGIN_NAME ": read %s failed, %s"),
              filename, strerror(errno));
        goto done;
     }
+
  done:
  done:
-    if (fd >= 0)
+    if (fd != -1)
        close(fd);
     if (data) {
        *data_length = len;
        close(fd);
     if (data) {
        *data_length = len;
@@ -434,9 +261,9 @@ readPropertyList(char * filename)
 {
     void *             buf;
     size_t             bufsize;
 {
     void *             buf;
     size_t             bufsize;
-    CFDataRef          data = NULL;
-    CFPropertyListRef  plist = NULL;
-    CFStringRef                errorString = NULL;
+    CFDataRef          data            = NULL;
+    CFPropertyListRef  plist           = NULL;
+    CFStringRef                errorString     = NULL;
 
     buf = read_file(filename, &bufsize);
     if (buf == NULL) {
 
     buf = read_file(filename, &bufsize);
     if (buf == NULL) {
@@ -451,9 +278,9 @@ readPropertyList(char * filename)
                                            kCFPropertyListMutableContainers,
                                            &errorString);
     if (plist == NULL) {
                                            kCFPropertyListMutableContainers,
                                            &errorString);
     if (plist == NULL) {
-       if (errorString) {
-           SCLog(TRUE, LOG_INFO,
-                 CFSTR(MY_PLUGIN_NAME ":%@"),
+       if (errorString != NULL) {
+           SCLog(TRUE, LOG_ERR,
+                 CFSTR(MY_PLUGIN_NAME ": %@"),
                  errorString);
            CFRelease(errorString);
        }
                  errorString);
            CFRelease(errorString);
        }
@@ -466,173 +293,314 @@ readPropertyList(char * filename)
     return (plist);
 }
 
     return (plist);
 }
 
-#define        IFNAMER_ID                      CFSTR("com.apple.SystemConfiguration.InterfaceNamer")
 #define        INTERFACES                      CFSTR("Interfaces")
 #define        NETWORK_INTERFACES_PREFS        CFSTR("NetworkInterfaces.plist")
 #define        OLD_NETWORK_INTERFACES_FILE     "/var/db/NetworkInterfaces.xml"
 
 #define        INTERFACES                      CFSTR("Interfaces")
 #define        NETWORK_INTERFACES_PREFS        CFSTR("NetworkInterfaces.plist")
 #define        OLD_NETWORK_INTERFACES_FILE     "/var/db/NetworkInterfaces.xml"
 
+static void
+writeInterfaceList(CFArrayRef if_list)
+{
+    CFArrayRef         cur_list;
+    SCPreferencesRef   prefs;
+
+    if (isA_CFArray(if_list) == NULL) {
+       return;
+    }
+
+    prefs = SCPreferencesCreate(NULL, MY_PLUGIN_ID, NETWORK_INTERFACES_PREFS);
+    if (prefs == NULL) {
+       SCLog(TRUE, LOG_ERR,
+             CFSTR(MY_PLUGIN_NAME ": SCPreferencesCreate failed, %s"),
+             SCErrorString(SCError()));
+       return;
+    }
+
+    cur_list = SCPreferencesGetValue(prefs, INTERFACES);
+    if (_SC_CFEqual(cur_list, if_list)) {
+       goto done;
+    }
+
+    if (!SCPreferencesSetValue(prefs, INTERFACES, if_list)) {
+       SCLog(TRUE, LOG_ERR,
+             CFSTR(MY_PLUGIN_NAME ": SCPreferencesSetValue failed, %s"),
+             SCErrorString(SCError()));
+       goto done;
+    }
+
+    if (!SCPreferencesCommitChanges(prefs)) {
+       SCLog((SCError() != EROFS), LOG_ERR,
+             CFSTR(MY_PLUGIN_NAME ": SCPreferencesCommitChanges failed, %s"),
+             SCErrorString(SCError()));
+       goto done;
+    }
+
+done:
+
+    CFRelease(prefs);
+    return;
+}
+
 static CFMutableArrayRef
 readInterfaceList()
 {
 static CFMutableArrayRef
 readInterfaceList()
 {
-    CFArrayRef         ilist;
+    CFArrayRef         if_list;
     CFMutableArrayRef  plist = NULL;
     SCPreferencesRef   prefs = NULL;
 
     CFMutableArrayRef  plist = NULL;
     SCPreferencesRef   prefs = NULL;
 
-    prefs = SCPreferencesCreate(NULL, IFNAMER_ID, NETWORK_INTERFACES_PREFS);
+    prefs = SCPreferencesCreate(NULL, MY_PLUGIN_ID, NETWORK_INTERFACES_PREFS);
     if (!prefs) {
     if (!prefs) {
-       SCLog(TRUE, LOG_INFO,
+       SCLog(TRUE, LOG_ERR,
              CFSTR(MY_PLUGIN_NAME ": SCPreferencesCreate failed, %s"),
              SCErrorString(SCError()));
        return (NULL);
     }
 
              CFSTR(MY_PLUGIN_NAME ": SCPreferencesCreate failed, %s"),
              SCErrorString(SCError()));
        return (NULL);
     }
 
-    ilist = SCPreferencesGetValue(prefs, INTERFACES);
-    if (isA_CFArray(ilist)) {
-       plist = CFArrayCreateMutableCopy(NULL, 0, ilist);
-    } else {
-       plist = (CFMutableArrayRef)readPropertyList(OLD_NETWORK_INTERFACES_FILE);
-       if (plist == NULL) {
+    if_list = SCPreferencesGetValue(prefs, INTERFACES);
+    if (!isA_CFArray(if_list)) {
+       if_list = (CFArrayRef)readPropertyList(OLD_NETWORK_INTERFACES_FILE);
+       if (if_list == NULL) {
            goto done;
        }
            goto done;
        }
-       if (isA_CFArray(plist) == NULL) {
-           CFRelease(plist);
+       if (!isA_CFArray(if_list)) {
+           CFRelease(if_list);
+           if_list = NULL;
            goto done;
        }
            goto done;
        }
-       writeInterfaceList(plist);
+       writeInterfaceList(if_list);
        (void)unlink(OLD_NETWORK_INTERFACES_FILE);
     }
 
   done:
        (void)unlink(OLD_NETWORK_INTERFACES_FILE);
     }
 
   done:
+    if (if_list != NULL) {
+       CFIndex i;
+       CFIndex n       = CFArrayGetCount(if_list);
+
+       plist = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+       for (i = 0; i < n; i++) {
+           CFDictionaryRef     dict;
+
+           dict = CFArrayGetValueAtIndex(if_list, i);
+           if (isA_CFDictionary(dict) &&
+               CFDictionaryContainsKey(dict, CFSTR(kIOInterfaceType)) &&
+               CFDictionaryContainsKey(dict, CFSTR(kIOInterfaceUnit)) &&
+               CFDictionaryContainsKey(dict, CFSTR(kIOMACAddress))) {
+                   CFArrayAppendValue(plist, dict);
+           }
+       }
+    }
     if (prefs) {
        CFRelease(prefs);
     }
     return (plist);
 }
 
     if (prefs) {
        CFRelease(prefs);
     }
     return (plist);
 }
 
-static void
-writeInterfaceList(CFArrayRef ilist)
+static CFMutableArrayRef
+previouslyActiveInterfaces()
 {
 {
-    SCPreferencesRef   prefs;
+    CFMutableArrayRef  active;
+    CFIndex            i;
+    CFIndex            n;
 
 
-    if (isA_CFArray(ilist) == NULL) {
-       return;
+    if (S_dblist == NULL) {
+       return NULL;
     }
 
     }
 
-    prefs = SCPreferencesCreate(NULL, IFNAMER_ID, NETWORK_INTERFACES_PREFS);
-    if (prefs == NULL) {
-       SCLog(TRUE, LOG_INFO,
-             CFSTR(MY_PLUGIN_NAME ": SCPreferencesCreate failed, %s"),
-             SCErrorString(SCError()));
-       return;
-    }
+    active = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
 
 
-    if (!SCPreferencesSetValue(prefs, INTERFACES, ilist)) {
-       SCLog(TRUE, LOG_INFO,
-             CFSTR(MY_PLUGIN_NAME ": SCPreferencesSetValue failed, %s"),
-             SCErrorString(SCError()));
-       goto done;
+    n = CFArrayGetCount(S_dblist);
+    for (i = 0; i < n; i++) {
+       CFDictionaryRef if_dict;
+
+       if_dict = CFArrayGetValueAtIndex(S_dblist, i);
+       if (CFDictionaryContainsKey(if_dict, CFSTR(kSCNetworkInterfaceActive))) {
+           CFMutableDictionaryRef      new_dict;
+
+           new_dict = CFDictionaryCreateMutableCopy(NULL, 0, if_dict);
+           CFDictionaryRemoveValue(new_dict, CFSTR(kSCNetworkInterfaceActive));
+           CFArraySetValueAtIndex(S_dblist, i, new_dict);
+           CFArrayAppendValue(active, new_dict);
+           CFRelease(new_dict);
+       }
     }
 
     }
 
-    if (!SCPreferencesCommitChanges(prefs)) {
-       SCLog(TRUE, LOG_INFO,
-             CFSTR(MY_PLUGIN_NAME ": SCPreferencesCommitChanges failed, %s"),
-             SCErrorString(SCError()));
-       goto done;
+    return active;
+}
+
+static void
+updateStore(void)
+{
+    CFStringRef                key;
+    SCDynamicStoreRef  store;
+
+    store = SCDynamicStoreCreate(NULL, CFSTR(MY_PLUGIN_NAME), NULL, NULL);
+    if (store == NULL) {
+       return;
     }
 
     }
 
-done:
+    key = SCDynamicStoreKeyCreate(NULL, CFSTR("%@" MY_PLUGIN_NAME),
+                                 kSCDynamicStoreDomainPlugin);
+    (void)SCDynamicStoreSetValue(store, key, S_state);
+    CFRelease(key);
+    CFRelease(store);
 
 
-    CFRelease(prefs);
     return;
 }
 
 static void
     return;
 }
 
 static void
-updateBondConfiguration(void)
+updateVirtualNetworkInterfaceConfiguration(SCPreferencesRef            prefs,
+                                          SCPreferencesNotification   notificationType,
+                                          void                         *info)
 {
 {
-    BondPreferencesRef prefs;
+    CFArrayRef interfaces;
 
 
-    prefs = BondPreferencesCreate(NULL);
-    if (prefs == NULL) {
-       SCLog(TRUE, LOG_INFO,
-             CFSTR(MY_PLUGIN_NAME ": BondPreferencesCreate failed, %s"),
-             SCErrorString(SCError()));
+    if ((notificationType & kSCPreferencesNotificationApply) != kSCPreferencesNotificationApply) {
        return;
     }
 
        return;
     }
 
-    if (!_BondPreferencesUpdateConfiguration(prefs)) {
-       SCLog(TRUE, LOG_INFO,
-             CFSTR(MY_PLUGIN_NAME ": _BondPreferencesUpdateConfiguration failed, %s"),
+    if (prefs == NULL) {
+       // if a new interface has been "named"
+       prefs = S_prefs;
+       if (S_bonds != NULL) {
+           CFRelease(S_bonds);
+           S_bonds = NULL;
+       }
+       if (S_vlans != NULL) {
+           CFRelease(S_vlans);
+           S_vlans = NULL;
+       }
+    }
+
+    // update Bond configuration
+
+    interfaces = SCBondInterfaceCopyAll(prefs);
+    if ((S_bonds == NULL) && (interfaces == NULL)) {
+       // if no change
+       goto vlan;
+    }
+    if ((S_bonds != NULL) && (interfaces != NULL) && CFEqual(S_bonds, interfaces)) {
+       // if no change
+       CFRelease(interfaces);
+       goto vlan;
+    }
+    if (S_bonds != NULL) CFRelease(S_bonds);
+    S_bonds = interfaces;
+
+    if (!_SCBondInterfaceUpdateConfiguration(prefs)) {
+       SCLog(TRUE, LOG_ERR,
+             CFSTR(MY_PLUGIN_NAME ": _SCBondInterfaceUpdateConfiguration failed, %s"),
              SCErrorString(SCError()));
              SCErrorString(SCError()));
+    }
+
+  vlan :
+
+    // update VLAN configuration
+
+    interfaces = SCVLANInterfaceCopyAll(prefs);
+    if ((S_vlans == NULL) && (interfaces == NULL)) {
+       // if no change
        goto done;
     }
        goto done;
     }
+    if ((S_vlans != NULL) && (interfaces != NULL) && CFEqual(S_vlans, interfaces)) {
+       // if no change
+       CFRelease(interfaces);
+       goto done;
+    }
+    if (S_vlans != NULL) CFRelease(S_vlans);
+    S_vlans = interfaces;
 
 
-done:
+    if (!_SCVLANInterfaceUpdateConfiguration(prefs)) {
+       SCLog(TRUE, LOG_ERR,
+             CFSTR(MY_PLUGIN_NAME ": _SCVLANInterfaceUpdateConfiguration failed, %s"),
+             SCErrorString(SCError()));
+    }
 
 
-    CFRelease(prefs);
+  done :
+
+    // we are finished with current prefs, wait for changes
+
+    SCPreferencesSynchronize(prefs);
     return;
 }
 
     return;
 }
 
-static void
-updateVLANConfiguration(void)
+static CFDictionaryRef
+createInterfaceDict(SCNetworkInterfaceRef interface)
 {
 {
-    VLANPreferencesRef prefs;
+    CFMutableDictionaryRef     new_if;
+    CFTypeRef                  val;
 
 
-    prefs = VLANPreferencesCreate(NULL);
-    if (prefs == NULL) {
-       SCLog(TRUE, LOG_INFO,
-             CFSTR(MY_PLUGIN_NAME ": VLANPreferencesCreate failed, %s"),
-             SCErrorString(SCError()));
-       return;
+    new_if = CFDictionaryCreateMutable(NULL,
+                                      0,
+                                      &kCFTypeDictionaryKeyCallBacks,
+                                      &kCFTypeDictionaryValueCallBacks);
+
+    val = _SCNetworkInterfaceGetIOPath(interface);
+    if (val != NULL) {
+       CFDictionarySetValue(new_if, CFSTR(kIOPathMatchKey), val);
     }
 
     }
 
-    if (!_VLANPreferencesUpdateConfiguration(prefs)) {
-       SCLog(TRUE, LOG_INFO,
-             CFSTR(MY_PLUGIN_NAME ": _VLANPreferencesUpdateConfiguration failed, %s"),
-             SCErrorString(SCError()));
-       goto done;
+    val = _SCNetworkInterfaceGetIOInterfaceType(interface);
+    if (val != NULL) {
+       CFDictionarySetValue(new_if, CFSTR(kIOInterfaceType), val);
     }
 
     }
 
-done:
+    val = _SCNetworkInterfaceGetIOInterfaceUnit(interface);
+    if (val != NULL) {
+       CFDictionarySetValue(new_if, CFSTR(kIOInterfaceUnit), val);
+    }
 
 
-    CFRelease(prefs);
-    return;
-}
+    val = _SCNetworkInterfaceGetHardwareAddress(interface);
+    if (val != NULL) {
+       CFDictionarySetValue(new_if, CFSTR(kIOMACAddress), val);
+    }
+
+    val = SCNetworkInterfaceGetBSDName(interface);
+    if (val != NULL) {
+       CFDictionarySetValue(new_if, CFSTR(kIOBSDNameKey), val);
+    }
+
+    val = SCNetworkInterfaceGetInterfaceType(interface);
+    if (val != NULL) {
+       CFDictionarySetValue(new_if, CFSTR(kSCNetworkInterfaceType), val);
+    }
 
 
-#define INDEX_BAD      (-1)
+    CFDictionarySetValue(new_if,
+                        CFSTR(kIOBuiltin),
+                        _SCNetworkInterfaceIsBuiltin(interface) ? kCFBooleanTrue : kCFBooleanFalse);
+
+    CFDictionarySetValue(new_if, CFSTR(kSCNetworkInterfaceActive), kCFBooleanTrue);
+
+    return new_if;
+}
 
 static CFDictionaryRef
 
 static CFDictionaryRef
-lookupInterfaceByType(CFArrayRef list, CFDictionaryRef if_dict, int * where)
+lookupInterfaceByAddress(CFArrayRef db_list, SCNetworkInterfaceRef interface, CFIndex * where)
 {
     CFDataRef  addr;
     CFIndex    i;
     CFIndex    n;
     CFNumberRef        type;
 
 {
     CFDataRef  addr;
     CFIndex    i;
     CFIndex    n;
     CFNumberRef        type;
 
-    if (where) {
-       *where = INDEX_BAD;
-    }
-    if (list == NULL) {
+    if (db_list == NULL) {
        return (NULL);
     }
        return (NULL);
     }
-    addr = CFDictionaryGetValue(if_dict, CFSTR(kIOMACAddress));
-    type = CFDictionaryGetValue(if_dict, CFSTR(kIOInterfaceType));
+    type = _SCNetworkInterfaceGetIOInterfaceType(interface);
+    addr = _SCNetworkInterfaceGetHardwareAddress(interface);
     if (type == NULL || addr == NULL) {
        return (NULL);
     }
 
     if (type == NULL || addr == NULL) {
        return (NULL);
     }
 
-    n = CFArrayGetCount(list);
+    n = CFArrayGetCount(db_list);
     for (i = 0; i < n; i++) {
     for (i = 0; i < n; i++) {
-       CFDictionaryRef dict = CFArrayGetValueAtIndex(list, i);
        CFDataRef       a;
        CFDataRef       a;
+       CFDictionaryRef dict = CFArrayGetValueAtIndex(db_list, i);
        CFNumberRef     t;
 
        CFNumberRef     t;
 
-       a = CFDictionaryGetValue(dict, CFSTR(kIOMACAddress));
        t = CFDictionaryGetValue(dict, CFSTR(kIOInterfaceType));
        t = CFDictionaryGetValue(dict, CFSTR(kIOInterfaceType));
-       if (a == NULL || t == NULL)
+       a = CFDictionaryGetValue(dict, CFSTR(kIOMACAddress));
+       if (t == NULL || a == NULL)
            continue;
 
            continue;
 
-       if (CFNumberCompare(type, t, NULL) == kCFCompareEqualTo
-           && compareMacAddress(addr, a) == kCFCompareEqualTo) {
+       if (CFEqual(type, t) && CFEqual(addr, a)) {
            if (where) {
                *where = i;
            }
            if (where) {
                *where = i;
            }
@@ -643,28 +611,25 @@ lookupInterfaceByType(CFArrayRef list, CFDictionaryRef if_dict, int * where)
 }
 
 static CFDictionaryRef
 }
 
 static CFDictionaryRef
-lookupInterfaceByUnit(CFArrayRef list, CFDictionaryRef if_dict, int * where)
+lookupInterfaceByUnit(CFArrayRef db_list, SCNetworkInterfaceRef interface, CFIndex * where)
 {
     CFIndex    i;
     CFIndex    n;
     CFNumberRef        type;
     CFNumberRef        unit;
 
 {
     CFIndex    i;
     CFIndex    n;
     CFNumberRef        type;
     CFNumberRef        unit;
 
-    if (where) {
-       *where = INDEX_BAD;
-    }
-    if (list == NULL) {
+    if (db_list == NULL) {
        return (NULL);
     }
        return (NULL);
     }
-    type = CFDictionaryGetValue(if_dict, CFSTR(kIOInterfaceType));
-    unit = CFDictionaryGetValue(if_dict, CFSTR(kIOInterfaceUnit));
+    type = _SCNetworkInterfaceGetIOInterfaceType(interface);
+    unit = _SCNetworkInterfaceGetIOInterfaceUnit(interface);
     if (type == NULL || unit == NULL) {
        return (NULL);
     }
 
     if (type == NULL || unit == NULL) {
        return (NULL);
     }
 
-    n = CFArrayGetCount(list);
+    n = CFArrayGetCount(db_list);
     for (i = 0; i < n; i++) {
     for (i = 0; i < n; i++) {
-       CFDictionaryRef dict = CFArrayGetValueAtIndex(list, i);
+       CFDictionaryRef dict = CFArrayGetValueAtIndex(db_list, i);
        CFNumberRef     t;
        CFNumberRef     u;
 
        CFNumberRef     t;
        CFNumberRef     u;
 
@@ -674,8 +639,7 @@ lookupInterfaceByUnit(CFArrayRef list, CFDictionaryRef if_dict, int * where)
            continue;
        }
 
            continue;
        }
 
-       if (CFNumberCompare(type, t, NULL) == kCFCompareEqualTo
-           && CFNumberCompare(unit, u, NULL) == kCFCompareEqualTo) {
+       if (CFEqual(type, t) && CFEqual(unit, u)) {
            if (where)
                *where = i;
            return (dict);
            if (where)
                *where = i;
            return (dict);
@@ -684,55 +648,24 @@ lookupInterfaceByUnit(CFArrayRef list, CFDictionaryRef if_dict, int * where)
     return (NULL);
 }
 
     return (NULL);
 }
 
-#define kAirPortDriverPath     CFSTR("AirPort")
-#define kIO80211InterfacePath  CFSTR("IO80211Interface")
-#define APPLE_WIRELESS_80211   CFSTR("AppleWireless80211")
-
-static __inline__ boolean_t
-pathIsAirPort(CFStringRef path)
+static CFDictionaryRef
+lookupAirPortInterface(CFArrayRef db_list, CFIndex * where)
 {
 {
-    CFRange r;
-
-    r = CFStringFind(path, kIO80211InterfacePath, 0);
-    if (r.location != kCFNotFound) {
-       return (TRUE);
-    }
+    CFIndex    i;
+    CFIndex    n;
 
 
-    r = CFStringFind(path, kAirPortDriverPath, 0);
-    if (r.location != kCFNotFound) {
-       return (TRUE);
+    if (db_list == NULL) {
+       return (NULL);
     }
     }
+    n = CFArrayGetCount(db_list);
+    for (i = 0; i < n; i++) {
+       CFDictionaryRef dict;
+       CFStringRef     if_type;
 
 
-    r = CFStringFind(path, APPLE_WIRELESS_80211, 0);
-    if (r.location != kCFNotFound) {
-       return (TRUE);
-    }
-
-    return (FALSE);
-}
-
-static CFDictionaryRef
-lookupAirPortInterface(CFArrayRef list, int * where)
-{
-    CFIndex    i;
-    CFIndex    n;
-
-    if (where) {
-       *where = INDEX_BAD;
-    }
-    if (list == NULL) {
-       return (NULL);
-    }
-    n = CFArrayGetCount(list);
-    for (i = 0; i < n; i++) {
-       CFDictionaryRef dict = CFArrayGetValueAtIndex(list, i);
-       CFStringRef     path;
-
-       path = CFDictionaryGetValue(dict, CFSTR(kIOPathMatchKey));
-       if (path == NULL) {
-           continue;
-       }
-       if (pathIsAirPort(path) == TRUE) {
+       dict = CFArrayGetValueAtIndex(db_list, i);
+       if_type = CFDictionaryGetValue(dict, CFSTR(kSCNetworkInterfaceType));
+       if ((if_type != NULL) &&
+           CFEqual(if_type, kSCNetworkInterfaceTypeIEEE80211)) {
            if (where)
                *where = i;
            return (dict);
            if (where)
                *where = i;
            return (dict);
@@ -742,54 +675,70 @@ lookupAirPortInterface(CFArrayRef list, int * where)
 }
 
 static void
 }
 
 static void
-insertInterface(CFMutableArrayRef list, CFDictionaryRef if_dict)
+insertInterface(CFMutableArrayRef db_list, SCNetworkInterfaceRef interface)
 {
     CFIndex            i;
 {
     CFIndex            i;
+    CFDictionaryRef    if_dict;
+    CFStringRef                if_name;
     CFNumberRef                if_type;
     CFNumberRef                if_unit;
     CFNumberRef                if_type;
     CFNumberRef                if_unit;
-    CFIndex            n       = CFArrayGetCount(list);
+    CFIndex            n       = CFArrayGetCount(db_list);
     CFComparisonResult res;
 
     CFComparisonResult res;
 
-    if_type = CFDictionaryGetValue(if_dict, CFSTR(kIOInterfaceType));
-    if_unit = CFDictionaryGetValue(if_dict, CFSTR(kIOInterfaceUnit));
+    if_name = SCNetworkInterfaceGetBSDName(interface);
+    if (if_name != NULL) {
+       addTimestamp(S_state, if_name);
+    }
+
+    if_dict = createInterfaceDict(interface);
+    if_type = _SCNetworkInterfaceGetIOInterfaceType(interface);
+    if_unit = _SCNetworkInterfaceGetIOInterfaceUnit(interface);
+    if ((if_type == NULL) || (if_unit == NULL)) {
+       CFRelease(if_dict);
+       return;
+    }
+
     for (i = 0; i < n; i++) {
     for (i = 0; i < n; i++) {
-       CFDictionaryRef dict = CFArrayGetValueAtIndex(list, i);
-       CFNumberRef     type;
-       CFNumberRef     unit;
+       CFNumberRef     db_type;
+       CFNumberRef     db_unit;
+       CFDictionaryRef dict    = CFArrayGetValueAtIndex(db_list, i);
 
 
-       type = CFDictionaryGetValue(dict, CFSTR(kIOInterfaceType));
-       unit = CFDictionaryGetValue(dict, CFSTR(kIOInterfaceUnit));
-       res = CFNumberCompare(if_type, type, NULL);
+       db_type = CFDictionaryGetValue(dict, CFSTR(kIOInterfaceType));
+       db_unit = CFDictionaryGetValue(dict, CFSTR(kIOInterfaceUnit));
+       res = CFNumberCompare(if_type, db_type, NULL);
        if (res == kCFCompareLessThan
            || (res == kCFCompareEqualTo
        if (res == kCFCompareLessThan
            || (res == kCFCompareEqualTo
-               && (CFNumberCompare(if_unit, unit, NULL)
+               && (CFNumberCompare(if_unit, db_unit, NULL)
                    == kCFCompareLessThan))) {
                    == kCFCompareLessThan))) {
-           CFArrayInsertValueAtIndex(list, i, if_dict);
+           CFArrayInsertValueAtIndex(db_list, i, if_dict);
+           CFRelease(if_dict);
            return;
        }
     }
            return;
        }
     }
+
     CFArrayAppendValue(S_dblist, if_dict);
     CFArrayAppendValue(S_dblist, if_dict);
+    CFRelease(if_dict);
     return;
 }
 
 static void
     return;
 }
 
 static void
-replaceInterface(CFDictionaryRef if_dict)
+replaceInterface(SCNetworkInterfaceRef interface)
 {
 {
-    int where;
+    CFIndex where;
 
     if (S_dblist == NULL) {
        S_dblist = CFArrayCreateMutable(NULL, 0,
                                        &kCFTypeArrayCallBacks);
     }
 
     if (S_dblist == NULL) {
        S_dblist = CFArrayCreateMutable(NULL, 0,
                                        &kCFTypeArrayCallBacks);
     }
-    /* remove any dict that has our type/addr */
-    if (lookupInterfaceByType(S_dblist, if_dict, &where) != NULL) {
+    // remove any dict that has our type/addr
+    if (lookupInterfaceByAddress(S_dblist, interface, &where) != NULL) {
        CFArrayRemoveValueAtIndex(S_dblist, where);
     }
        CFArrayRemoveValueAtIndex(S_dblist, where);
     }
-    /* remove any dict that has the same type/unit */
-    if (lookupInterfaceByUnit(S_dblist, if_dict, &where) != NULL) {
+    // remove any dict that has the same type/unit
+    if (lookupInterfaceByUnit(S_dblist, interface, &where) != NULL) {
        CFArrayRemoveValueAtIndex(S_dblist, where);
     }
        CFArrayRemoveValueAtIndex(S_dblist, where);
     }
-    insertInterface(S_dblist, if_dict);
+    insertInterface(S_dblist, interface);
     return;
 }
 
     return;
 }
 
@@ -798,19 +747,21 @@ getHighestUnitForType(CFNumberRef if_type)
 {
     int                i;
     CFIndex            n;
 {
     int                i;
     CFIndex            n;
-    CFNumberRef                ret_unit = NULL;
+    CFNumberRef                ret_unit        = NULL;
 
 
-    if (S_dblist == NULL)
+    if (S_dblist == NULL) {
        return (NULL);
        return (NULL);
+    }
 
     n = CFArrayGetCount(S_dblist);
     for (i = 0; i < n; i++) {
        CFDictionaryRef dict = CFArrayGetValueAtIndex(S_dblist, i);
        CFNumberRef     type;
 
     n = CFArrayGetCount(S_dblist);
     for (i = 0; i < n; i++) {
        CFDictionaryRef dict = CFArrayGetValueAtIndex(S_dblist, i);
        CFNumberRef     type;
-       CFNumberRef     unit;
 
        type = CFDictionaryGetValue(dict, CFSTR(kIOInterfaceType));
        if (CFEqual(type, if_type)) {
 
        type = CFDictionaryGetValue(dict, CFSTR(kIOInterfaceType));
        if (CFEqual(type, if_type)) {
+           CFNumberRef unit;
+
            unit = CFDictionaryGetValue(dict, CFSTR(kIOInterfaceUnit));
            if (ret_unit == NULL
                || (CFNumberCompare(unit, ret_unit, NULL)
            unit = CFDictionaryGetValue(dict, CFSTR(kIOInterfaceUnit));
            if (ret_unit == NULL
                || (CFNumberCompare(unit, ret_unit, NULL)
@@ -819,254 +770,51 @@ getHighestUnitForType(CFNumberRef if_type)
            }
        }
     }
            }
        }
     }
+
     return (ret_unit);
 }
 
     return (ret_unit);
 }
 
-//------------------------------------------------------------------------
-// Register a single interface with the given service path to the
-// data link layer (BSD), using the specified unit number.
-
+/*
+ * Function: registerInterface
+ * Purpose:
+ *   Register a single interface with the given service path to the
+ *   data link layer (BSD), using the specified unit number.
+ */
 static kern_return_t
 static kern_return_t
-registerInterface(io_connect_t connect,
-                 CFStringRef path,
-                 CFNumberRef unit)
+registerInterface(io_connect_t connect,
+                 CFStringRef   path,
+                 CFNumberRef   unit)
 {
 {
+    static const int           command = kRegisterInterface;
     CFMutableDictionaryRef     dict;
     CFMutableDictionaryRef     dict;
-    kern_return_t              kr = kIOReturnNoMemory;
+    kern_return_t              kr;
+    CFNumberRef                        num;
 
     dict = CFDictionaryCreateMutable(NULL, 0,
                                     &kCFTypeDictionaryKeyCallBacks,
                                     &kCFTypeDictionaryValueCallBacks);
 
     dict = CFDictionaryCreateMutable(NULL, 0,
                                     &kCFTypeDictionaryKeyCallBacks,
                                     &kCFTypeDictionaryValueCallBacks);
-    if (dict == NULL
-       || addCFNumberProperty(dict, kIONetworkStackUserCommand,
-                              kIORegisterOne) == FALSE)
-       ;
-    else {
-       CFDictionarySetValue(dict, CFSTR(kIOPathMatchKey), path);
-       CFDictionarySetValue(dict, CFSTR(kIOInterfaceUnit), unit);
-       kr = IOConnectSetCFProperties(connect, dict);
-    }
-    if (dict) CFRelease( dict );
+    num = CFNumberCreate(NULL, kCFNumberIntType, &command);
+    CFDictionarySetValue(dict, CFSTR(kIONetworkStackUserCommand), num);
+    CFRelease(num);
+    CFDictionarySetValue(dict, CFSTR(kIOPathMatchKey), path);
+    CFDictionarySetValue(dict, CFSTR(kIOInterfaceUnit), unit);
+    kr = IOConnectSetCFProperties(connect, dict);
+    CFRelease(dict);
     return kr;
 }
 
     return kr;
 }
 
-/*
- * Note: this function blocks all other plug-ins until it completes
- */
-static void
-waitForQuiet(mach_port_t masterPort)
-{
-    mach_timespec_t t;
-    kern_return_t   wait_ret;
-
-    t.tv_sec  = 4;
-    t.tv_nsec = 0;
-
-    // kIOReturnTimeout if the wait timed out.
-    // kIOReturnSuccess on success.
-    wait_ret = IOKitWaitQuiet(masterPort, &t);
-    return;
-}
-
-/*
- * Function: createNetworkStackObject
- * Purpose:
- *   Get a reference to the single IONetworkStack object instance in
- *   the kernel. Naming requests must be sent to this object, which is
- *   attached as a client to all network interface objects in the system.
- * Note:
- *   Call IOObjectRelease on the returned object.
- */
-static io_object_t
-createNetworkStackObject(mach_port_t masterPort)
-{
-    io_iterator_t      iter = MACH_PORT_NULL;
-    kern_return_t      kr;
-    io_object_t                stack = MACH_PORT_NULL;
-
-    kr = IOServiceGetMatchingServices(masterPort,
-                                     IOServiceMatching("IONetworkStack"),
-                                     &iter);
-    if (iter != MACH_PORT_NULL) {
-       if (kr == KERN_SUCCESS) {
-           stack = IOIteratorNext(iter);
-       }
-       IOObjectRelease(iter);
-    }
-    return stack;
-}
-
-static void
-printMacAddress(CFDataRef data)
-{
-    int                i;
-    CFIndex    n = CFDataGetLength(data);
-
-    for (i = 0; i < n; i++) {
-       if (i != 0) SCPrint(TRUE, stdout, CFSTR(":"));
-       SCPrint(TRUE, stdout, CFSTR("%02x"), CFDataGetBytePtr(data)[i]);
-    }
-    return;
-}
-
-/*
- * Function: getMacAddress
- *
- * Purpose:
- *   Given an interface object if_obj, return its associated mac address.
- *   The mac address is stored in the parent, the network controller object.
- *
- * Returns:
- *   The CFDataRef containing the bytes of the mac address.
- */
-static CFDataRef
-getMacAddress(io_object_t if_obj)
-{
-    CFMutableDictionaryRef     dict = NULL;
-    CFDataRef                  data = NULL;
-    kern_return_t              kr;
-    io_object_t                        parent_obj = MACH_PORT_NULL;
-
-    /* get the parent node */
-    kr = IORegistryEntryGetParentEntry(if_obj, kIOServicePlane, &parent_obj);
-    if (kr != KERN_SUCCESS) {
-       SCLog(TRUE, LOG_INFO,
-             CFSTR(MY_PLUGIN_NAME
-                   ": IORegistryEntryGetParentEntry returned 0x%x"),
-             kr);
-       goto failed;
-    }
-
-    /* get the dictionary associated with the node */
-    kr = IORegistryEntryCreateCFProperties(parent_obj,
-                                          &dict,
-                                          NULL,
-                                          kNilOptions );
-    if (kr != KERN_SUCCESS) {
-       SCLog(TRUE, LOG_INFO,
-             CFSTR(MY_PLUGIN_NAME
-                   ": IORegistryEntryCreateCFProperties returned 0x%x"),
-             kr);
-       goto failed;
-    }
-    data = CFDictionaryGetValue(dict, CFSTR(kIOMACAddress));
-    if (data) {
-       CFRetain(data);
-    }
-
- failed:
-    if (dict)
-       CFRelease(dict);
-    if (parent_obj)
-       IOObjectRelease(parent_obj);
-    return (data);
-}
-
-static CFDictionaryRef
-getInterface(io_object_t if_obj)
-{
-    CFBooleanRef                       builtin;
-    kern_return_t                      kr;
-    CFDataRef                          mac_address = NULL;
-    CFStringRef                                location;
-    CFMutableDictionaryRef             new_if = NULL;
-    io_string_t                                path;
-    CFMutableDictionaryRef             reginfo_if = NULL;
-    CFDictionaryRef                    ret_dict = NULL;
-    CFStringRef                                string;
-    CFNumberRef                                type;
-    CFNumberRef                                unit;
-
-    kr = IORegistryEntryGetPath(if_obj, kIOServicePlane, path);
-    if (kr != KERN_SUCCESS) {
-       SCLog(TRUE, LOG_INFO,
-             CFSTR(MY_PLUGIN_NAME
-                   ": IORegistryEntryGetPath returned 0x%x"),
-             kr);
-       goto failed;
-    }
-    kr = IORegistryEntryCreateCFProperties(if_obj,
-                                          &reginfo_if,
-                                          NULL,
-                                          kNilOptions);
-    if (kr != KERN_SUCCESS) {
-       SCLog(TRUE, LOG_INFO,
-             CFSTR(MY_PLUGIN_NAME
-                   ": IORegistryEntryCreateCFProperties returned 0x%x"),
-             kr);
-       goto failed;
-    }
-    type = isA_CFNumber(CFDictionaryGetValue(reginfo_if,
-                                            CFSTR(kIOInterfaceType)));
-    if (type == NULL) {
-       goto failed;
-    }
-    mac_address = getMacAddress(if_obj);
-    if (mac_address == NULL) {
-       goto failed;
-    }
-    builtin = isA_CFBoolean(CFDictionaryGetValue(reginfo_if,
-                                                CFSTR(kIOBuiltin)));
-    if ((builtin == NULL) || !CFBooleanGetValue(builtin)) {
-       builtin = isA_CFBoolean(CFDictionaryGetValue(reginfo_if,
-                                                CFSTR(kIOPrimaryInterface)));
-    }
-    location = isA_CFString(CFDictionaryGetValue(reginfo_if,
-                                                CFSTR(kIOLocation)));
-
-    new_if = CFDictionaryCreateMutable(NULL, 0,
-                                      &kCFTypeDictionaryKeyCallBacks,
-                                      &kCFTypeDictionaryValueCallBacks);
-    if (new_if == NULL) {
-       goto failed;
-    }
-    CFDictionarySetValue(new_if, CFSTR(kIOInterfaceType), type);
-    CFDictionarySetValue(new_if, CFSTR(kIOMACAddress), mac_address);
-    if (builtin) {
-       CFDictionarySetValue(new_if, CFSTR(kIOBuiltin), builtin);
-    }
-    if (location) {
-       CFDictionarySetValue(new_if, CFSTR(kIOLocation), location);
-    }
-    addCFStringProperty(new_if, kIOPathMatchKey, path);
-
-    unit = isA_CFNumber(CFDictionaryGetValue(reginfo_if,
-                                            CFSTR(kIOInterfaceUnit)));
-    if (unit) {
-       CFDictionarySetValue(new_if, CFSTR(kIOInterfaceUnit), unit);
-    }
-    string = isA_CFString(CFDictionaryGetValue(reginfo_if, CFSTR(kIOBSDNameKey)));
-    if (string) {
-       CFDictionarySetValue(new_if, CFSTR(kIOBSDNameKey), string);
-    }
-    ret_dict = new_if;
-    new_if = NULL;
-
- failed:
-    if (new_if) {
-       CFRelease(new_if);
-    }
-    if (reginfo_if) {
-       CFRelease(reginfo_if);
-    }
-    if (mac_address) {
-       CFRelease(mac_address);
-    }
-    return (ret_dict);
-}
-
-static CFDictionaryRef
+static SCNetworkInterfaceRef
 lookupIOKitPath(CFStringRef if_path)
 {
 lookupIOKitPath(CFStringRef if_path)
 {
-    CFDictionaryRef            dict = NULL;
-    io_registry_entry_t                entry = MACH_PORT_NULL;
+    io_registry_entry_t                entry           = MACH_PORT_NULL;
+    SCNetworkInterfaceRef      interface       = NULL;
     kern_return_t              kr;
     kern_return_t              kr;
-    mach_port_t                        masterPort = MACH_PORT_NULL;
+    mach_port_t                        masterPort      = MACH_PORT_NULL;
     io_string_t                        path;
 
     kr = IOMasterPort(bootstrap_port, &masterPort);
     if (kr != KERN_SUCCESS) {
     io_string_t                        path;
 
     kr = IOMasterPort(bootstrap_port, &masterPort);
     if (kr != KERN_SUCCESS) {
-       SCLog(TRUE, LOG_INFO,
+       SCLog(TRUE, LOG_ERR,
              CFSTR(MY_PLUGIN_NAME ": IOMasterPort returned 0x%x\n"),
              kr);
        goto error;
              CFSTR(MY_PLUGIN_NAME ": IOMasterPort returned 0x%x\n"),
              kr);
        goto error;
@@ -1074,12 +822,13 @@ lookupIOKitPath(CFStringRef if_path)
     _SC_cfstring_to_cstring(if_path, path, sizeof(path), kCFStringEncodingASCII);
     entry = IORegistryEntryFromPath(masterPort, path);
     if (entry == MACH_PORT_NULL) {
     _SC_cfstring_to_cstring(if_path, path, sizeof(path), kCFStringEncodingASCII);
     entry = IORegistryEntryFromPath(masterPort, path);
     if (entry == MACH_PORT_NULL) {
-       SCLog(TRUE, LOG_INFO,
+       SCLog(TRUE, LOG_ERR,
              CFSTR(MY_PLUGIN_NAME ": IORegistryEntryFromPath(%@) failed"),
              if_path);
        goto error;
     }
              CFSTR(MY_PLUGIN_NAME ": IORegistryEntryFromPath(%@) failed"),
              if_path);
        goto error;
     }
-    dict = getInterface(entry);
+
+    interface = _SCNetworkInterfaceCreateWithIONetworkInterfaceObject(entry);
 
  error:
     if (masterPort != MACH_PORT_NULL) {
 
  error:
     if (masterPort != MACH_PORT_NULL) {
@@ -1088,324 +837,935 @@ lookupIOKitPath(CFStringRef if_path)
     if (entry != MACH_PORT_NULL) {
        IOObjectRelease(entry);
     }
     if (entry != MACH_PORT_NULL) {
        IOObjectRelease(entry);
     }
-    return (dict);
+    return (interface);
 
 }
 
 static void
 
 }
 
 static void
-displayInterface(CFDictionaryRef if_dict)
+displayInterface(SCNetworkInterfaceRef interface)
 {
 {
+    CFStringRef                addr;
     CFStringRef                name;
     CFNumberRef                type;
     CFNumberRef                unit;
 
     CFStringRef                name;
     CFNumberRef                type;
     CFNumberRef                unit;
 
-    name = CFDictionaryGetValue(if_dict, CFSTR(kIOBSDNameKey));
-    if (name) {
-       SCPrint(TRUE, stdout, CFSTR("BSD Name: %@\n"), name);
-    }
-
-    unit = CFDictionaryGetValue(if_dict, CFSTR(kIOInterfaceUnit));
-    if (unit) {
-       SCPrint(TRUE, stdout, CFSTR("Unit: %@\n"), unit);
-    }
-
-    type = CFDictionaryGetValue(if_dict, CFSTR(kIOInterfaceType));
-    SCPrint(TRUE, stdout, CFSTR("Type: %@\n"), type);
-
-    SCPrint(TRUE, stdout, CFSTR("MAC address: "));
-    printMacAddress(CFDictionaryGetValue(if_dict, CFSTR(kIOMACAddress)));
-    SCPrint(TRUE, stdout, CFSTR("\n"));
+    name = SCNetworkInterfaceGetBSDName(interface);
+    unit = _SCNetworkInterfaceGetIOInterfaceUnit(interface);
+    type = _SCNetworkInterfaceGetIOInterfaceType(interface);
+    addr = SCNetworkInterfaceGetHardwareAddressString(interface);
+
+    SCLog(TRUE, LOG_INFO,
+         CFSTR(MY_PLUGIN_NAME ":   %s%@%sType: %@, %s%@%sMAC address: %@"),
+         (name != NULL) ? "BSD Name: " : "",
+         (name != NULL) ? name : CFSTR(""),
+         (name != NULL) ? ", " : "",
+         type,
+         (unit != NULL) ? "Unit: " : "",
+         (unit != NULL) ? (CFTypeRef)unit : (CFTypeRef)CFSTR(""),
+         (unit != NULL) ? ", " : "",
+         addr);
 }
 
 }
 
-static void
-sort_interfaces_by_unit(CFMutableArrayRef if_list)
+static int
+builtinCount(CFArrayRef if_list, CFIndex last, CFNumberRef if_type)
 {
 {
-    int                count = CFArrayGetCount(if_list);
-    CFRange    range = CFRangeMake(0, count);
+    CFIndex    i;
+    int                n       = 0;
 
 
-    if (count < 2)
-       return;
-    CFArraySortValues(if_list, range, if_unit_compare, NULL);
-    return;
+    for (i = 0; i < last; i++) {
+       SCNetworkInterfaceRef   builtin_if;
+       CFNumberRef             builtin_type;
+
+       builtin_if   = CFArrayGetValueAtIndex(if_list, i);
+       builtin_type = _SCNetworkInterfaceGetIOInterfaceType(builtin_if);
+       if (CFEqual(if_type, builtin_type)) {
+           if (_SCNetworkInterfaceIsBuiltin(builtin_if)) {
+               n++;    // if built-in interface
+           }
+       }
+    }
+
+    return n;
 }
 
 }
 
-static void
-sort_interfaces_by_path(CFMutableArrayRef if_list)
+static __inline__ boolean_t
+isQuiet(void)
 {
 {
-    int                count = CFArrayGetCount(if_list);
-    CFRange    range = CFRangeMake(0, count);
-
-    if (count < 2)
-       return;
-    CFArraySortValues(if_list, range, if_path_compare, NULL);
-    return;
+    return (S_quiet == MACH_PORT_NULL);
 }
 
 static void
 }
 
 static void
-name_interfaces(CFArrayRef if_list)
+nameInterfaces(CFMutableArrayRef if_list)
 {
     CFIndex    i;
 {
     CFIndex    i;
-    CFIndex    n = CFArrayGetCount(if_list);
-    CFIndex    i_builtin = 0;
-    CFIndex    n_builtin = 0;
-
-    if (S_debug)
-       SCPrint(TRUE, stdout, CFSTR("\n"));
-
-    for (i = 0; i < n; i++) {
-       CFBooleanRef    builtin;
-       CFDictionaryRef if_dict;
-
-       if_dict = CFArrayGetValueAtIndex(if_list, i);
-       builtin = CFDictionaryGetValue(if_dict, CFSTR(kIOBuiltin));
-       if (builtin && CFBooleanGetValue(builtin)) {
-           n_builtin++;        // reserve unit number for built-in interface
-       }
-    }
+    CFIndex    n       = CFArrayGetCount(if_list);
 
     for (i = 0; i < n; i++) {
 
     for (i = 0; i < n; i++) {
-       CFDictionaryRef if_dict;
-       CFNumberRef     type;
-       CFNumberRef     unit;
-
-       if (S_debug) {
-           if (i != 0)
-               SCPrint(TRUE, stdout, CFSTR("\n"));
-       }
-
-       if_dict = CFArrayGetValueAtIndex(if_list, i);
-       unit = CFDictionaryGetValue(if_dict, CFSTR(kIOInterfaceUnit));
-       type = CFDictionaryGetValue(if_dict, CFSTR(kIOInterfaceType));
-       if (unit) {
+       SCNetworkInterfaceRef   interface;
+       CFStringRef             path;
+       CFNumberRef             type;
+       CFNumberRef             unit;
+       CFIndex                 where;
+
+       interface = CFArrayGetValueAtIndex(if_list, i);
+       path = _SCNetworkInterfaceGetIOPath(interface);
+       type = _SCNetworkInterfaceGetIOInterfaceType(interface);
+       unit = _SCNetworkInterfaceGetIOInterfaceUnit(interface);
+
+       if (unit != NULL) {
            if (S_debug) {
            if (S_debug) {
-               SCPrint(TRUE, stdout, CFSTR("Interface already has a unit number\n"));
-               displayInterface(if_dict);
+               CFStringRef     if_name;
+
+               if_name = SCNetworkInterfaceGetBSDName(interface);
+               if ((if_name == NULL) || !CFDictionaryContainsKey(S_state, if_name)) {
+                       SCLog(TRUE, LOG_INFO,
+                             CFSTR(MY_PLUGIN_NAME ": Interface already has a unit number"));
+                       displayInterface(interface);
+               }
            }
            }
-           replaceInterface(if_dict);
-       }
-       else {
-           CFDictionaryRef             dbdict = NULL;
-           kern_return_t               kr = KERN_SUCCESS;
-           CFStringRef                 path;
-           CFNumberRef                 unit = NULL;
-
-           path = CFDictionaryGetValue(if_dict, CFSTR(kIOPathMatchKey));
-           dbdict = lookupInterfaceByType(S_dblist, if_dict, NULL);
-           if (dbdict == NULL
-               && pathIsAirPort(path) == TRUE) {
-               dbdict = lookupAirPortInterface(S_dblist, NULL);
+
+           // update the list of interfaces that were previously named
+           if ((S_prev_active_list != NULL)
+               && lookupInterfaceByAddress(S_prev_active_list, interface, &where) != NULL) {
+               CFArrayRemoveValueAtIndex(S_prev_active_list, where);
            }
            }
+       } else {
+           CFDictionaryRef     dbdict;
+           kern_return_t       kr;
+
+           dbdict = lookupInterfaceByAddress(S_dblist, interface, NULL);
            if (dbdict != NULL) {
            if (dbdict != NULL) {
-               unit = CFDictionaryGetValue(dbdict,
-                                           CFSTR(kIOInterfaceUnit));
+               unit = CFDictionaryGetValue(dbdict, CFSTR(kIOInterfaceUnit));
                CFRetain(unit);
                CFRetain(unit);
-           }
-           else {
-               int             if_type;
-               boolean_t       is_builtin = FALSE;
-               int             next_unit = 0;
-
-               CFNumberGetValue(type,
-                                kCFNumberIntType, &if_type);
-               if (if_type == IFT_ETHER) { /* ethernet */
-                   CFBooleanRef        builtin;
-
-                   builtin = CFDictionaryGetValue(if_dict,
-                                                  CFSTR(kIOBuiltin));
-                   if (builtin && CFBooleanGetValue(builtin)) {
-                       is_builtin = TRUE;
-                       next_unit = i_builtin++;
-                   }
-                   else {
-#if defined(__ppc__)
-                       /* skip over slots reserved for built-in ethernet interface(s) */
-                       next_unit = n_builtin;
-#endif
+
+               SCLog(S_debug, LOG_INFO,
+                     CFSTR(MY_PLUGIN_NAME ": Interface assigned unit %@ (from database)"),
+                     unit);
+           } else {
+               CFStringRef     if_type;
+
+               if_type = SCNetworkInterfaceGetInterfaceType(interface);
+               if ((if_type != NULL) &&
+                   CFEqual(if_type, kSCNetworkInterfaceTypeIEEE80211)) {
+                   dbdict = lookupAirPortInterface(S_dblist, NULL);
+                   if (dbdict != NULL) {
+                       unit = CFDictionaryGetValue(dbdict, CFSTR(kIOInterfaceUnit));
+                       CFRetain(unit);
+
+                       SCLog(S_debug, LOG_INFO,
+                             CFSTR(MY_PLUGIN_NAME ": Interface assigned unit %@ (updating database)"),
+                             unit);
                    }
                }
                    }
                }
-               if (is_builtin == FALSE) {
+           }
+
+           if ((dbdict != NULL) && (S_prev_active_list != NULL)) {
+               // update the list of interfaces that were previously named
+               where = CFArrayGetFirstIndexOfValue(S_prev_active_list,
+                                                   CFRangeMake(0, CFArrayGetCount(S_prev_active_list)),
+                                                   dbdict);
+               if (where != kCFNotFound) {
+                   CFArrayRemoveValueAtIndex(S_prev_active_list, where);
+               }
+           }
+
+           if (dbdict == NULL) {
+               boolean_t       is_builtin;
+               int             next_unit       = 0;
+
+               if (!isQuiet()) {
+                   // if new interface, wait until quiet before naming
+                   addTimestamp(S_state, path);
+                   continue;
+               }
+
+               is_builtin = _SCNetworkInterfaceIsBuiltin(interface);
+               next_unit = 0;
+               if (is_builtin) {
+                   // built-in interface, use the reserved slots
+                   next_unit = builtinCount(if_list, i, type);
+               } else {
+                   // not built-in, skip over the reserved slots
+                   next_unit = builtinCount(if_list, n, type);
+
                    unit = getHighestUnitForType(type);
                    unit = getHighestUnitForType(type);
-                   if (unit) {
+                   if (unit != NULL) {
                        int     high_unit;
 
                        int     high_unit;
 
-                       CFNumberGetValue(unit,
-                                        kCFNumberIntType, &high_unit);
+                       CFNumberGetValue(unit, kCFNumberIntType, &high_unit);
                        if (high_unit >= next_unit) {
                            next_unit = high_unit + 1;
                        }
                    }
                }
                        if (high_unit >= next_unit) {
                            next_unit = high_unit + 1;
                        }
                    }
                }
-               unit = CFNumberCreate(NULL,
-                                     kCFNumberIntType, &next_unit);
-           }
-           if (S_debug) {
-               SCPrint(TRUE, stdout, CFSTR("Interface assigned unit %@ %s\n"), unit,
-                       dbdict ? "(from database)" : "(next available)");
+               unit = CFNumberCreate(NULL, kCFNumberIntType, &next_unit);
+
+               SCLog(S_debug, LOG_INFO,
+                     CFSTR(MY_PLUGIN_NAME ": Interface assigned unit %@ (%s)"),
+                     unit,
+                     is_builtin ? "built-in" : "next available");
            }
            }
+
            kr = registerInterface(S_connect, path, unit);
            if (kr != KERN_SUCCESS) {
            kr = registerInterface(S_connect, path, unit);
            if (kr != KERN_SUCCESS) {
-               SCLog(TRUE, LOG_INFO,
-                     CFSTR(MY_PLUGIN_NAME
-                           ": failed to name the interface 0x%x"),
+               SCLog(TRUE, LOG_ERR,
+                     CFSTR(MY_PLUGIN_NAME ": failed to name the interface, kr=0x%x"),
                      kr);
                if (S_debug) {
                      kr);
                if (S_debug) {
-                   displayInterface(if_dict);
+                   displayInterface(interface);
                }
                }
-           }
-           else {
-               CFDictionaryRef new_dict;
+           } else {
+               SCNetworkInterfaceRef   new_interface;
 
 
-               path = CFDictionaryGetValue(if_dict,
-                                           CFSTR(kIOPathMatchKey));
-               new_dict = lookupIOKitPath(path);
-               if (new_dict != NULL) {
-                   CFNumberRef         new_unit;
+               new_interface = lookupIOKitPath(path);
+               if (new_interface != NULL) {
+                   CFNumberRef new_unit;
 
 
-                   new_unit = CFDictionaryGetValue(new_dict,
-                                                   CFSTR(kIOInterfaceUnit));
+                   new_unit = _SCNetworkInterfaceGetIOInterfaceUnit(new_interface);
                    if (CFEqual(unit, new_unit) == FALSE) {
                    if (CFEqual(unit, new_unit) == FALSE) {
-                       SCLog(TRUE, LOG_INFO,
+                       SCLog(S_debug, LOG_INFO,
                              CFSTR(MY_PLUGIN_NAME
                                    ": interface type %@ assigned "
                                    "unit %@ instead of %@"),
                              type, new_unit, unit);
                    }
                    if (S_debug) {
                              CFSTR(MY_PLUGIN_NAME
                                    ": interface type %@ assigned "
                                    "unit %@ instead of %@"),
                              type, new_unit, unit);
                    }
                    if (S_debug) {
-                       displayInterface(new_dict);
+                       displayInterface(new_interface);
                    }
                    }
-                   replaceInterface(new_dict);
-                   CFRelease(new_dict);
+
+                   // update if_list (with the interface name & unit)
+                   CFArraySetValueAtIndex(if_list, i, new_interface);
+                   CFRelease(new_interface);
+                   interface = new_interface;  // if_list holds the reference
                }
            }
                }
            }
+
            CFRelease(unit);
        }
            CFRelease(unit);
        }
+
+       // update db
+       replaceInterface(interface);
     }
     }
-    writeInterfaceList(S_dblist);
     return;
 }
 
 static void
     return;
 }
 
 static void
-interfaceArrivalCallback( void * refcon, io_iterator_t iter )
+updateInterfaces()
 {
 {
-    CFMutableArrayRef  if_list = NULL;
-    io_object_t        obj;
+    if (S_connect == MACH_PORT_NULL) {
+       // if we don't have the "IONetworkStack" connect object
+       return;
+    }
 
 
+    if (S_iflist != NULL) {
+       CFIndex n;
 
 
-    while ((obj = IOIteratorNext(iter))) {
-       CFDictionaryRef dict;
+       n = CFArrayGetCount(S_iflist);
+       if (n > 1) {
+           CFArraySortValues(S_iflist, CFRangeMake(0, n), _SCNetworkInterfaceCompare, NULL);
+       }
+       nameInterfaces(S_iflist);
+    }
+
+    if (isQuiet()) {
+       /*
+        * The registry [matching] has quiesced so let's
+        * - save the DB with the interfaces that have been named
+        * - update the VLAN/BOND configuration
+        * - tell everyone that we've finished (at least for now)
+        * - log those interfaces which are no longer present
+        *   in the HW config (or have yet to show up).
+        */
+       writeInterfaceList(S_dblist);
+       updateVirtualNetworkInterfaceConfiguration(NULL, kSCPreferencesNotificationApply, NULL);
+       updateStore();
+
+       if (S_iflist != NULL) {
+           CFRelease(S_iflist);
+           S_iflist = NULL;
+       }
+
+       if (S_prev_active_list != NULL) {
+           if (S_debug) {
+               CFIndex i;
+               CFIndex n;
 
 
-       dict = getInterface(obj);
-       if (dict) {
-           if (if_list == NULL) {
-               if_list = CFArrayCreateMutable(NULL, 0,
-                                              &kCFTypeArrayCallBacks);
+               n = CFArrayGetCount(S_prev_active_list);
+               SCLog(TRUE, LOG_INFO,
+                     CFSTR(MY_PLUGIN_NAME ": Interface%s not [yet] active"),
+                     (n > 0) ? "s" : "");
+               for (i = 0; i < n; i++) {
+                   CFDictionaryRef     if_dict;
+                   CFStringRef         name;
+                   CFNumberRef         type;
+                   CFNumberRef         unit;
+
+                   if_dict = CFArrayGetValueAtIndex(S_prev_active_list, i);
+                   name = CFDictionaryGetValue(if_dict, CFSTR(kIOBSDNameKey));
+                   type = CFDictionaryGetValue(if_dict, CFSTR(kIOInterfaceType));
+                   unit = CFDictionaryGetValue(if_dict, CFSTR(kIOInterfaceUnit));
+                   SCLog(TRUE, LOG_INFO,
+                         CFSTR(MY_PLUGIN_NAME ":   %s%@%sType: %@, Unit: %@"),
+                         (name != NULL) ? "BSD Name: " : "",
+                         (name != NULL) ? name : CFSTR(""),
+                         (name != NULL) ? ", " : "",
+                         type,
+                         unit);
+               }
            }
            }
-           if (if_list)
-               CFArrayAppendValue(if_list, dict);
-           CFRelease(dict);
+           CFRelease(S_prev_active_list);
+           S_prev_active_list = NULL;
        }
        }
-       IOObjectRelease(obj);
+    } else {
+       if ((S_prev_active_list != NULL) && (CFArrayGetCount(S_prev_active_list) == 0)) {
+           /*
+            * if we've named all of the interfaces that
+            * were used during the previous boot.
+            */
+           addTimestamp(S_state, CFSTR("*RELEASE*"));
+           SCLog(S_debug, LOG_INFO,
+                 CFSTR(MY_PLUGIN_NAME ": last boot interfaces have been named"));
+           updateStore();
+           CFRelease(S_prev_active_list);
+           S_prev_active_list = NULL;
+       }
+    }
+
+    return;
+}
+
+static CFComparisonResult
+compareMacAddress(const void *val1, const void *val2, void *context)
+{
+    CFDataRef          mac1    = (CFDataRef)val1;
+    CFDataRef          mac2    = (CFDataRef)val2;
+    CFIndex            n1;
+    CFIndex            n2;
+    CFComparisonResult res;
+
+    n1 = CFDataGetLength(mac1);
+    n2 = CFDataGetLength(mac2);
+    if (n1 < n2) {
+       res = kCFCompareLessThan;
+     } else if (n2 > n1) {
+       res = kCFCompareGreaterThan;
+     } else {
+       res = bcmp(CFDataGetBytePtr(mac1), CFDataGetBytePtr(mac2), n1);
+     }
+
+     return res;
+}
+
+static void
+updatePlatformUUID()
+{
+    CFDataRef          addr;
+    CFMutableArrayRef  addrs   = NULL;
+    CFStringRef                guid;
+    CFIndex            i;
+    CFIndex            n;
+    io_registry_entry_t        platform;
+
+    platform = IORegistryEntryFromPath(kIOMasterPortDefault, kIODeviceTreePlane ":/");
+    if (platform == MACH_PORT_NULL) {
+       return;
+    }
+
+    guid = IORegistryEntryCreateCFProperty(platform, CFSTR(kIOPlatformUUIDKey), NULL, 0);
+    if (guid != NULL) {
+       // if GUID already defined
+       goto done;
     }
     }
-    if (if_list) {
-       sort_interfaces_by_path(if_list);
-       name_interfaces(if_list);
-       updateBondConfiguration();
-       updateVLANConfiguration();
-       CFRelease(if_list);
+
+    addrs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+    n = (S_dblist != NULL) ? CFArrayGetCount(S_dblist) : 0;
+    for (i = 0; i < n; i++) {
+       CFBooleanRef    builtin;
+       CFDictionaryRef dict;
+       CFStringRef     type;
+
+       dict = CFArrayGetValueAtIndex(S_dblist, i);
+       type = CFDictionaryGetValue(dict, CFSTR(kSCNetworkInterfaceType));
+       if (!isA_CFString(type) || !CFEqual(type, kSCNetworkInterfaceTypeEthernet)) {
+           continue;
+       }
+       builtin = CFDictionaryGetValue(dict, CFSTR(kIOBuiltin));
+       if (!isA_CFBoolean(builtin) || !CFBooleanGetValue(builtin)) {
+           continue;
+       }
+       addr = CFDictionaryGetValue(dict, CFSTR(kIOMACAddress));
+       if (!isA_CFData(addr) || (CFDataGetLength(addr) != ETHER_ADDR_LEN)) {
+           continue;
+       }
+       CFArrayAppendValue(addrs, addr);
+    }
+
+    if (CFArrayGetCount(addrs) == 0) {
+       // if no ethernet interfaces, look for wireless
+       for (i = 0; i < n; i++) {
+           CFDictionaryRef     dict;
+           CFStringRef         type;
+
+           dict = CFArrayGetValueAtIndex(S_dblist, i);
+           type = CFDictionaryGetValue(dict, CFSTR(kSCNetworkInterfaceType));
+           if (!isA_CFString(type) || !CFEqual(type, kSCNetworkInterfaceTypeIEEE80211)) {
+               continue;
+           }
+           addr = CFDictionaryGetValue(dict, CFSTR(kIOMACAddress));
+           if (!isA_CFData(addr) || (CFDataGetLength(addr) != ETHER_ADDR_LEN)) {
+               continue;
+           }
+           CFArrayAppendValue(addrs, addr);
+       }
+    }
+
+    n = CFArrayGetCount(addrs);
+    switch (n) {
+       case 0 :
+           SCLog(TRUE, LOG_ERR,
+                 CFSTR(MY_PLUGIN_NAME ": no network interfaces, could not update platform UUID"));
+           break;
+       default :
+           // sort by MAC address
+           CFArraySortValues(addrs, CFRangeMake(0, n), compareMacAddress, NULL);
+
+           // fall through
+       case 1 : {
+           CFUUIDBytes         bytes   = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+                                           0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+           kern_return_t       kr;
+           CFUUIDRef           uuid;
+
+           // set GUID
+           addr = CFArrayGetValueAtIndex(addrs, 0);
+           bcopy(CFDataGetBytePtr(addr),
+                 (void *)&bytes + sizeof(bytes) - ETHER_ADDR_LEN,
+                 ETHER_ADDR_LEN);
+           uuid = CFUUIDCreateFromUUIDBytes(NULL, bytes);
+           guid = CFUUIDCreateString(NULL, uuid);
+           CFRelease(uuid);
+
+           SCLog(TRUE, LOG_INFO,
+                 CFSTR(MY_PLUGIN_NAME ": setting platform UUID = %@"),
+                 guid);
+           kr = IORegistryEntrySetCFProperty(platform, CFSTR(kIOPlatformUUIDKey), guid);
+           if (kr != KERN_SUCCESS) {
+               SCLog(TRUE, LOG_ERR,
+                     CFSTR(MY_PLUGIN_NAME ": IORegistryEntrySetCFProperty(platform UUID) failed, kr=0x%x"),
+                     kr);
+           }
+
+           addTimestamp(S_state, CFSTR("*PLATFORM-UUID*"));
+           updateStore();
+           break;
+       }
     }
     }
+
+  done :
+
+    if (addrs != NULL) CFRelease(addrs);
+    if (platform != MACH_PORT_NULL) IOObjectRelease(platform);
+    if (guid != NULL) CFRelease(guid);
     return;
 }
 
     return;
 }
 
+static void
+interfaceArrivalCallback(void *refcon, io_iterator_t iter)
+{
+    io_object_t        obj;
 
 
-__private_extern__
-void
-load_InterfaceNamer(CFBundleRef bundle, Boolean bundleVerbose)
+    while ((obj = IOIteratorNext(iter)) != MACH_PORT_NULL) {
+       SCNetworkInterfaceRef   interface;
+
+       interface = _SCNetworkInterfaceCreateWithIONetworkInterfaceObject(obj);
+       if (interface != NULL) {
+           if (S_iflist == NULL) {
+               S_iflist = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+           }
+           CFArrayAppendValue(S_iflist, interface);
+           CFRelease(interface);
+       }
+       IOObjectRelease(obj);
+    }
+
+    updateInterfaces();
+    return;
+}
+
+/*
+ * Function: stackCallback
+ * Purpose:
+ *   Get a reference to the single IONetworkStack object instance in
+ *   the kernel. Naming requests must be sent to this object, which is
+ *   attached as a client to all network interface objects in the system.
+ * Note:
+ *   Call IOObjectRelease on the returned object.
+ */
+static void
+stackCallback(void *refcon, io_iterator_t iter)
 {
     kern_return_t      kr;
 {
     kern_return_t      kr;
-    mach_port_t                masterPort = MACH_PORT_NULL;
-    io_object_t                stack = MACH_PORT_NULL;
+    io_object_t                stack;
 
 
-    if (bundleVerbose) {
-       S_debug++;
+    stack = IOIteratorNext(iter);
+    if (stack == MACH_PORT_NULL) {
+       goto error;
     }
 
     }
 
-    kr = IOMasterPort(bootstrap_port, &masterPort);
+    kr = IOServiceOpen(stack, mach_task_self(), 0, &S_connect);
     if (kr != KERN_SUCCESS) {
     if (kr != KERN_SUCCESS) {
-       SCLog(TRUE, LOG_INFO,
-             CFSTR(MY_PLUGIN_NAME ": IOMasterPort returned 0x%x"),
+       SCLog(TRUE, LOG_ERR,
+             CFSTR(MY_PLUGIN_NAME ": IOServiceOpen returned 0x%x"),
              kr);
        goto error;
     }
 
              kr);
        goto error;
     }
 
-    /* synchronize with any drivers that might be loading at boot time */
-    waitForQuiet(masterPort);
+    addTimestamp(S_state, CFSTR("*STACK*"));
+    SCLog(S_debug, LOG_INFO,
+         CFSTR(MY_PLUGIN_NAME ": IONetworkStack found"));
 
 
-    stack = createNetworkStackObject(masterPort);
-    if (stack == MACH_PORT_NULL) {
-       SCLog(TRUE, LOG_INFO,
+    if (S_stack != MACH_PORT_NULL) {
+       IOObjectRelease(S_stack);
+       S_stack = MACH_PORT_NULL;
+    }
+
+    updateInterfaces();
+
+ error:
+    if (stack != MACH_PORT_NULL) {
+       IOObjectRelease(stack);
+    }
+
+    return;
+}
+
+static void
+quietCallback(void             *refcon,
+             io_service_t      service,
+             natural_t         messageType,
+             void              *messageArgument)
+{
+    if (messageArgument != NULL) {
+       // if not yet quiet
+       return;
+    }
+
+    if (messageType == kIOMessageServiceBusyStateChange) {
+       addTimestamp(S_state, CFSTR("*QUIET*"));
+       SCLog(S_debug, LOG_INFO,
+             CFSTR(MY_PLUGIN_NAME ": IOKit quiet"));
+    }
+
+    if (S_connect == MACH_PORT_NULL) {
+       SCLog(TRUE, LOG_ERR,
              CFSTR(MY_PLUGIN_NAME ": No network stack object"));
              CFSTR(MY_PLUGIN_NAME ": No network stack object"));
-       goto error;
+       return;
     }
     }
-    kr = IOServiceOpen(stack, mach_task_self(), 0, &S_connect);
-    if (kr != KERN_SUCCESS) {
-       SCPrint(TRUE, stdout, CFSTR(MY_PLUGIN_NAME ": IOServiceOpen returned 0x%x\n"), kr);
-       goto error;
+
+    if (S_quiet != MACH_PORT_NULL) {
+       IOObjectRelease(S_quiet);
+       S_quiet = MACH_PORT_NULL;
+    }
+
+    if (S_timer != NULL) {
+       CFRunLoopTimerInvalidate(S_timer);
+       CFRelease(S_timer);
+       S_timer = NULL;
+    }
+
+    // grab (and name) any additional interfaces.
+    interfaceArrivalCallback((void *)S_notify, S_iter);
+
+    updatePlatformUUID();
+
+    return;
+}
+
+static void
+iterateRegistryBusy(io_iterator_t iterator, CFArrayRef nodes, int *count)
+{
+    kern_return_t      kr  = kIOReturnSuccess;;
+    io_object_t                obj;
+
+    while ((kr == kIOReturnSuccess) &&
+          ((obj = IOIteratorNext(iterator)) != MACH_PORT_NULL)) {
+       uint32_t                busy;
+       io_name_t               location;
+       io_name_t               name;
+       CFMutableArrayRef       newNodes;
+       CFMutableStringRef      str     = NULL;
+
+       if (nodes == NULL) {
+           newNodes = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+       } else {
+           newNodes = CFArrayCreateMutableCopy(NULL, 0, nodes);
+       }
+
+       kr = IORegistryEntryGetName(obj, name);
+       if (kr != kIOReturnSuccess) {
+           SCLog(TRUE, LOG_ERR,
+                 CFSTR(MY_PLUGIN_NAME ": reportBusy IORegistryEntryGetName returned 0x%x"),
+                 kr);
+           goto next;
+       }
+
+       str = CFStringCreateMutable(NULL, 0);
+       CFStringAppendCString(str, name, kCFStringEncodingUTF8);
+
+       kr = IORegistryEntryGetLocationInPlane(obj, kIOServicePlane, location);
+       switch (kr) {
+           case kIOReturnSuccess :
+               CFStringAppendCString(str, "@", kCFStringEncodingUTF8);
+               CFStringAppendCString(str, location, kCFStringEncodingUTF8);
+               break;
+           case kIOReturnNotFound :
+               break;
+           default :
+               SCLog(TRUE, LOG_ERR,
+                     CFSTR(MY_PLUGIN_NAME ": reportBusy IORegistryEntryGetLocationInPlane returned 0x%x"),
+                     kr);
+               goto next;
+               break;
+       }
+
+       CFArrayAppendValue(newNodes, str);
+       CFRelease(str);
+
+       kr = IOServiceGetBusyState(obj, &busy);
+       if (kr != kIOReturnSuccess) {
+           SCLog(TRUE, LOG_ERR,
+                 CFSTR(MY_PLUGIN_NAME ": reportBusy IOServiceGetBusyState returned 0x%x"),
+                 kr);
+           goto next;
+       }
+
+       if (busy != 0) {
+           CFStringRef path;
+
+           if ((*count)++ == 0) {
+               SCLog(TRUE, LOG_WARNING, CFSTR(MY_PLUGIN_NAME ": Busy services :"));
+           }
+
+           path = CFStringCreateByCombiningStrings(NULL, newNodes, CFSTR("/"));
+           SCLog(TRUE, LOG_WARNING, CFSTR(MY_PLUGIN_NAME ":   %@ [%d]"), path, busy);
+           CFRelease(path);
+       }
+
+       kr = IORegistryIteratorEnterEntry(iterator);
+       if (kr != kIOReturnSuccess) {
+           SCLog(TRUE, LOG_ERR,
+                 CFSTR(MY_PLUGIN_NAME ": reportBusy IORegistryIteratorEnterEntry returned 0x%x"),
+                 kr);
+           goto next;
+       }
+
+       iterateRegistryBusy(iterator, newNodes, count);
+
+       kr = IORegistryIteratorExitEntry(iterator);
+       if (kr != kIOReturnSuccess) {
+           SCLog(TRUE, LOG_ERR,
+                 CFSTR(MY_PLUGIN_NAME ": reportBusy IORegistryIteratorExitEntry returned 0x%x"),
+                 kr);
+       }
+
+      next :
+
+       CFRelease(newNodes);
+       IOObjectRelease(obj);
+    }
+
+    return;
+}
+
+static void
+reportBusy()
+{
+    int                        count           = 0;
+    io_iterator_t      iterator        = MACH_PORT_NULL;
+    kern_return_t      kr;
+
+    kr = IORegistryCreateIterator(kIOMasterPortDefault,
+                                 kIOServicePlane,
+                                 0,
+                                 &iterator);
+    if (kr != kIOReturnSuccess) {
+       SCLog(TRUE, LOG_ERR,
+             CFSTR(MY_PLUGIN_NAME ": reportBusy IORegistryCreateIterator returned 0x%x"),
+             kr);
+       return;
+    }
+
+    iterateRegistryBusy(iterator, NULL, &count);
+    SCLog((count == 0), LOG_WARNING,
+         CFSTR(MY_PLUGIN_NAME ":   w/no busy services"));
+    IOObjectRelease(iterator);
+    return;
+}
+
+static void
+timerCallback(CFRunLoopTimerRef        timer, void *info)
+{
+    /*
+     * We've been waiting for IOKit to quiesce and it just
+     * hasn't happenned.  Time to just move on!
+     */
+    addTimestamp(S_state, CFSTR("*TIMEOUT*"));
+    SCLog(TRUE, LOG_ERR,
+         CFSTR(MY_PLUGIN_NAME ": timed out waiting for IOKit to quiesce"));
+
+    reportBusy();
+    quietCallback((void *)S_notify, MACH_PORT_NULL, 0, NULL);
+    return;
+}
+
+static Boolean
+setup_IOKit(CFBundleRef bundle)
+{
+    uint32_t           busy;
+    CFDictionaryRef    dict;
+    kern_return_t      kr;
+    mach_port_t                masterPort      = MACH_PORT_NULL;
+    Boolean            ok              = FALSE;
+    io_object_t                root            = MACH_PORT_NULL;
+    double             timeout         = WAIT_QUIET_TIMEOUT_DEFAULT;
+
+    // read DB of previously named network interfaces
+    S_dblist = readInterfaceList();
+    if (S_dblist != NULL) {
+       CFIndex n;
+
+       n = CFArrayGetCount(S_dblist);
+       if (n > 1) {
+           CFArraySortValues(S_dblist, CFRangeMake(0, n), if_unit_compare, NULL);
+       }
     }
 
     }
 
+    // get interfaces that were named during the last boot
+    S_prev_active_list = previouslyActiveInterfaces();
+
+    // track how long we've waited to see each interface.
+    S_state = CFDictionaryCreateMutable(NULL,
+                                       0,
+                                       &kCFTypeDictionaryKeyCallBacks,
+                                       &kCFTypeDictionaryValueCallBacks);
+    addTimestamp(S_state, CFSTR("*START*"));
+
     // Creates and returns a notification object for receiving IOKit
     // notifications of new devices or state changes.
     // Creates and returns a notification object for receiving IOKit
     // notifications of new devices or state changes.
+    kr = IOMasterPort(bootstrap_port, &masterPort);
+    if (kr != KERN_SUCCESS) {
+       SCLog(TRUE, LOG_ERR,
+             CFSTR(MY_PLUGIN_NAME ": IOMasterPort returned 0x%x"),
+             kr);
+       goto done;
+    }
 
     S_notify = IONotificationPortCreate(masterPort);
     if (S_notify == NULL) {
 
     S_notify = IONotificationPortCreate(masterPort);
     if (S_notify == NULL) {
-       SCLog(TRUE, LOG_INFO,
+       SCLog(TRUE, LOG_ERR,
              CFSTR(MY_PLUGIN_NAME ": IONotificationPortCreate failed"));
              CFSTR(MY_PLUGIN_NAME ": IONotificationPortCreate failed"));
-       goto error;
+       goto done;
+    }
+
+    // watch IOKit matching activity
+    root = IORegistryEntryFromPath(masterPort, kIOServicePlane ":/");
+    if (root == MACH_PORT_NULL) {
+       SCLog(TRUE, LOG_ERR,
+             CFSTR(MY_PLUGIN_NAME ": IORegistryEntryFromPath failed"));
+       goto done;
+    }
+
+    kr = IOServiceAddInterestNotification(S_notify,
+                                         root,
+                                         kIOBusyInterest,
+                                         &quietCallback,
+                                         (void *)S_notify,     // refCon
+                                         &S_quiet);            // notification
+    if (kr != KERN_SUCCESS) {
+       SCLog(TRUE, LOG_ERR,
+             CFSTR(MY_PLUGIN_NAME ": IOServiceAddInterestNotification returned 0x%x"),
+             kr);
+       goto done;
+    }
+
+    kr = IOServiceGetBusyState(root, &busy);
+    if (kr != KERN_SUCCESS) {
+       SCLog(TRUE, LOG_ERR,
+             CFSTR(MY_PLUGIN_NAME ": IOServiceGetBusyState returned 0x%x"),
+             kr);
+       goto done;
     }
     }
+
+    // add a timer so we don't wait forever for IOKit to quiesce
+    dict = CFBundleGetInfoDictionary(bundle);
+    if (isA_CFDictionary(dict)) {
+       CFNumberRef     num;
+
+       num = CFDictionaryGetValue(dict, CFSTR(WAIT_QUIET_TIMEOUT_KEY));
+       if (num != NULL) {
+           if (!isA_CFNumber(num) ||
+               !CFNumberGetValue(num, kCFNumberDoubleType, &timeout) ||
+               (timeout <= 0.0)) {
+               SCLog(TRUE, LOG_ERR,
+                     CFSTR(MY_PLUGIN_NAME ": " WAIT_QUIET_TIMEOUT_KEY " value error"));
+               timeout = WAIT_QUIET_TIMEOUT_DEFAULT;
+           }
+       }
+    }
+    S_timer = CFRunLoopTimerCreate(NULL,
+                                  CFAbsoluteTimeGetCurrent() + timeout,
+                                  0,
+                                  0,
+                                  0,
+                                  timerCallback,
+                                  NULL);
+    if (S_timer == NULL) {
+       SCLog(TRUE, LOG_ERR,
+             CFSTR(MY_PLUGIN_NAME ": CFRunLoopTimerCreate failed"));
+       goto done;
+    }
+
+    CFRunLoopAddTimer(CFRunLoopGetCurrent(), S_timer, kCFRunLoopDefaultMode);
+
+    // watch for the introduction of the IONetworkStack
+    kr = IOServiceAddMatchingNotification(S_notify,
+                                         kIOFirstMatchNotification,
+                                         IOServiceMatching("IONetworkStack"),
+                                         &stackCallback,
+                                         (void *)S_notify,     // refCon
+                                         &S_stack);            // notification
+    if (kr != KERN_SUCCESS) {
+       SCLog(TRUE, LOG_ERR,
+             CFSTR(MY_PLUGIN_NAME ": IOServiceAddMatchingNotification returned 0x%x"),
+             kr);
+       goto done;
+    }
+
+    // check and see if the stack is already available and arm the
+    // notification for its introduction.
+    stackCallback((void *)S_notify, S_stack);
+
+    // watch for the introduction of new network interfaces
     kr = IOServiceAddMatchingNotification(S_notify,
                                          kIOFirstMatchNotification,
                                          IOServiceMatching("IONetworkInterface"),
                                          &interfaceArrivalCallback,
     kr = IOServiceAddMatchingNotification(S_notify,
                                          kIOFirstMatchNotification,
                                          IOServiceMatching("IONetworkInterface"),
                                          &interfaceArrivalCallback,
-                                         (void *) S_notify, /* refCon */
-                                         &S_iter );         /* notification */
-
+                                         (void *)S_notify,     // refCon
+                                         &S_iter);             // notification
     if (kr != KERN_SUCCESS) {
     if (kr != KERN_SUCCESS) {
-       SCLog(TRUE, LOG_INFO,
-             CFSTR(MY_PLUGIN_NAME
-                   ": IOServiceAddMatchingNotification returned 0x%x"),
+       SCLog(TRUE, LOG_ERR,
+             CFSTR(MY_PLUGIN_NAME ": IOServiceAddMatchingNotification returned 0x%x"),
              kr);
              kr);
-       goto error;
+       goto done;
     }
 
     }
 
-    S_dblist = readInterfaceList();
-    if (S_dblist) {
-       sort_interfaces_by_unit(S_dblist);
-    }
-    // Get the current list of matches and arms the notification for
+    // Get the current list of matches and arm the notification for
     // future interface arrivals.
     // future interface arrivals.
+    interfaceArrivalCallback((void *)S_notify, S_iter);
 
 
-    interfaceArrivalCallback((void *) S_notify, S_iter);
+    // Check if IOKit has already quiesced.
+    quietCallback((void *)S_notify,
+                 MACH_PORT_NULL,
+                 kIOMessageServiceBusyStateChange,
+                 (void *)busy);
 
     CFRunLoopAddSource(CFRunLoopGetCurrent(),
                       IONotificationPortGetRunLoopSource(S_notify),
                       kCFRunLoopDefaultMode);
 
     CFRunLoopAddSource(CFRunLoopGetCurrent(),
                       IONotificationPortGetRunLoopSource(S_notify),
                       kCFRunLoopDefaultMode);
-    if (stack != MACH_PORT_NULL) {
-       IOObjectRelease(stack);
+
+#ifdef WAIT_PREVIOUS_BOOT_INTERFACES_OR_QUIET
+    /*
+     * Start the wheels turning until we've named all of
+     * the interfaces that were used during the previous
+     * boot, until IOKit [matching] has quiesced, or
+     * until we've waited long enough.
+     */
+    CFRunLoopAddTimer(CFRunLoopGetCurrent(), S_timer, MY_PLUGIN_ID);
+    CFRunLoopAddSource(CFRunLoopGetCurrent(),
+                      IONotificationPortGetRunLoopSource(S_notify),
+                      MY_PLUGIN_ID);
+    while (S_prev_active_list != NULL) {
+       int     rlStatus;
+
+       rlStatus = CFRunLoopRunInMode(MY_PLUGIN_ID, 1.0e10, TRUE);
+    }
+#endif /* WAIT_PREVIOUS_BOOT_INTERFACES_OR_QUIET */
+
+    ok = TRUE;
+
+ done:
+    if (root != MACH_PORT_NULL) {
+       IOObjectRelease(root);
     }
     if (masterPort != MACH_PORT_NULL) {
        mach_port_deallocate(mach_task_self(), masterPort);
     }
     }
     if (masterPort != MACH_PORT_NULL) {
        mach_port_deallocate(mach_task_self(), masterPort);
     }
-    return;
- error:
-    if (stack != MACH_PORT_NULL) {
-       IOObjectRelease(stack);
+
+    return ok;
+}
+
+static Boolean
+setup_Virtual(CFBundleRef bundle)
+{
+    // open a SCPreferences session
+    S_prefs = SCPreferencesCreate(NULL, CFSTR(MY_PLUGIN_NAME), NULL);
+    if (S_prefs == NULL) {
+       SCLog(TRUE, LOG_ERR,
+             CFSTR(MY_PLUGIN_NAME ": SCPreferencesCreate() failed: %s"),
+             SCErrorString(SCError()));
+       return FALSE;
     }
     }
-    if (masterPort != MACH_PORT_NULL) {
-       mach_port_deallocate(mach_task_self(), masterPort);
+
+    // register for change notifications.
+    if (!SCPreferencesSetCallback(S_prefs, updateVirtualNetworkInterfaceConfiguration, NULL)) {
+       SCLog(TRUE, LOG_ERR,
+             CFSTR(MY_PLUGIN_NAME ": SCPreferencesSetCallBack() failed: %s"),
+             SCErrorString(SCError()));
+       CFRelease(S_prefs);
+       return FALSE;
+    }
+
+    // schedule
+    if (!SCPreferencesScheduleWithRunLoop(S_prefs, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)) {
+       SCLog(TRUE, LOG_ERR,
+             CFSTR(MY_PLUGIN_NAME ": SCPreferencesScheduleWithRunLoop() failed: %s"),
+             SCErrorString(SCError()));
+       CFRelease(S_prefs);
+       return FALSE;
+    }
+
+    return TRUE;
+}
+
+__private_extern__
+void
+load_InterfaceNamer(CFBundleRef bundle, Boolean bundleVerbose)
+{
+    if (bundleVerbose) {
+       S_debug = TRUE;
+    }
+
+    // setup virtual network interface monitoring
+    if (!setup_Virtual(bundle)) {
+       goto error;
+    }
+
+    // setup [IOKit] network interface monitoring
+    if (!setup_IOKit(bundle)) {
+       goto error;
     }
     }
+
+    return;
+
+  error :
     if (S_connect != MACH_PORT_NULL) {
        IOServiceClose(S_connect);
        S_connect = MACH_PORT_NULL;
     }
     if (S_connect != MACH_PORT_NULL) {
        IOServiceClose(S_connect);
        S_connect = MACH_PORT_NULL;
     }
+    if (S_dblist != NULL) {
+       CFRelease(S_dblist);
+       S_dblist = NULL;
+    }
     if (S_iter != MACH_PORT_NULL) {
        IOObjectRelease(S_iter);
        S_iter = MACH_PORT_NULL;
     if (S_iter != MACH_PORT_NULL) {
        IOObjectRelease(S_iter);
        S_iter = MACH_PORT_NULL;
@@ -1413,6 +1773,24 @@ load_InterfaceNamer(CFBundleRef bundle, Boolean bundleVerbose)
     if (S_notify != MACH_PORT_NULL) {
        IONotificationPortDestroy(S_notify);
     }
     if (S_notify != MACH_PORT_NULL) {
        IONotificationPortDestroy(S_notify);
     }
+    if (S_quiet != MACH_PORT_NULL) {
+       IOObjectRelease(S_quiet);
+       S_quiet = MACH_PORT_NULL;
+    }
+    if (S_stack != MACH_PORT_NULL) {
+       IOObjectRelease(S_stack);
+       S_stack = MACH_PORT_NULL;
+    }
+    if (S_state != NULL) {
+       CFRelease(S_state);
+       S_state = NULL;
+    }
+    if (S_timer != NULL) {
+       CFRunLoopTimerInvalidate(S_timer);
+       CFRelease(S_timer);
+       S_timer = NULL;
+    }
+
     return;
 }
 
     return;
 }
 
@@ -1422,11 +1800,47 @@ load_InterfaceNamer(CFBundleRef bundle, Boolean bundleVerbose)
 int
 main(int argc, char ** argv)
 {
 int
 main(int argc, char ** argv)
 {
-    load_InterfaceNamer(CFBundleGetMainBundle(),
-        (argc > 1) ? TRUE : FALSE);
+    _sc_log     = FALSE;
+    _sc_verbose = (argc > 1) ? TRUE : FALSE;
+
+    load_InterfaceNamer(CFBundleGetMainBundle(), (argc > 1) ? TRUE : FALSE);
     CFRunLoopRun();
     /* not reached */
     exit(0);
     return 0;
 }
 #endif /* MAIN */
     CFRunLoopRun();
     /* not reached */
     exit(0);
     return 0;
 }
 #endif /* MAIN */
+
+#ifdef TEST_PLATFORM_UUID
+int
+main(int argc, char ** argv)
+{
+    CFArrayRef interfaces;
+
+    _sc_log     = FALSE;
+    _sc_verbose = (argc > 1) ? TRUE : FALSE;
+
+    S_dblist = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+    interfaces = SCNetworkInterfaceCopyAll();
+    if (interfaces != NULL) {
+       CFIndex i;
+       CFIndex n;
+
+       n = CFArrayGetCount(interfaces);
+       for (i = 0; i < n; i++) {
+           CFDictionaryRef             dict;
+           SCNetworkInterfaceRef       interface;
+
+           interface = CFArrayGetValueAtIndex(interfaces, i);
+           dict = createInterfaceDict(interface);
+           CFArrayAppendValue(S_dblist, dict);
+           CFRelease(dict);
+       }
+       CFRelease(interfaces);
+    }
+    updatePlatformUUID();
+    CFRelease(S_dblist);
+    exit(0);
+    return 0;
+}
+#endif /* TEST_PLATFORM_UUID */