]> git.saurik.com Git - apple/configd.git/blobdiff - Plugins/PreferencesMonitor/prefsmon.c
configd-1109.101.1.tar.gz
[apple/configd.git] / Plugins / PreferencesMonitor / prefsmon.c
index 8a091e2dffedd76f63af03cdb80666509a20cd98..31ce760baddc4ac204f9ce167a82c48ef83e9b6f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2008, 2010, 2012-2016 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2008, 2010, 2012-2020 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  *
 
 
 #include <TargetConditionals.h>
-#include <fcntl.h>
-#include <net/if.h>
 #include <sys/types.h>
-#include <sys/stat.h>
 #include <unistd.h>
 
-
-#define        SC_LOG_HANDLE   __log_PreferencesMonitor()
+#define        SC_LOG_HANDLE           __log_PreferencesMonitor
+#define SC_LOG_HANDLE_TYPE     static
 #include <SystemConfiguration/SystemConfiguration.h>
 #include <SystemConfiguration/SCPrivate.h>
 #include <SystemConfiguration/SCValidation.h>
+#include "SCNetworkConfigurationInternal.h"
 #include "plugin_shared.h"
 
 
-#include <CommonCrypto/CommonDigest.h>
-
-
 /* globals */
 static SCPreferencesRef                prefs                   = NULL;
 static SCDynamicStoreRef       store                   = NULL;
 
 /* InterfaceNamer[.plugin] monitoring globals */
-Boolean                                haveConfiguration       = FALSE;
+static CFMutableArrayRef       excluded_interfaces     = NULL;         // of SCNetworkInterfaceRef
+static CFMutableArrayRef       excluded_names          = NULL;         // of CFStringRef (BSD name)
+static Boolean                 haveConfiguration       = FALSE;
 static CFStringRef             namerKey                = NULL;
-static CFArrayRef              preconfigured           = NULL;
+static CFMutableArrayRef       preconfigured_interfaces= NULL;         // of SCNetworkInterfaceRef
+static CFMutableArrayRef       preconfigured_names     = NULL;         // of CFStringRef (BSD name)
 
 /* KernelEventMonitor[.plugin] monitoring globals */
 static CFStringRef             interfacesKey           = NULL;
@@ -72,7 +70,6 @@ static CFMutableArrayRef      unchangedPrefsKeys;     /* new prefs keys which match curre
 static CFMutableArrayRef       removedPrefsKeys;       /* old prefs keys to be removed */
 
 static Boolean                 rofs                    = FALSE;
-static Boolean                 restorePrefs            = FALSE;
 
 #define MY_PLUGIN_NAME         "PreferencesMonitor"
 #define        MY_PLUGIN_ID            CFSTR("com.apple.SystemConfiguration." MY_PLUGIN_NAME)
@@ -85,7 +82,7 @@ updateConfiguration(SCPreferencesRef          prefs,
 
 
 static os_log_t
-__log_PreferencesMonitor()
+__log_PreferencesMonitor(void)
 {
        static os_log_t log     = NULL;
 
@@ -97,116 +94,37 @@ __log_PreferencesMonitor()
 }
 
 
-static Boolean
-restorePreferences()
+static void
+savePastConfiguration(CFStringRef old_model)
 {
-       Boolean                 ok = FALSE;
-       CFStringRef             currentModel = NULL;
-       CFMutableStringRef      modelPrefixStr = NULL;
-       CFArrayRef              keyList = NULL;
-       CFIndex                 keyListCount;
-       CFIndex                 idx;
-       Boolean                 modified = FALSE;
-       int                     sc_status = kSCStatusFailed;
-
-       while (TRUE) {
-               ok = SCPreferencesLock(prefs, TRUE);
-               if (ok) {
-                       break;
-               }
-
-               sc_status = SCError();
-               if (sc_status == kSCStatusStale) {
-                       SCPreferencesSynchronize(prefs);
-               } else {
-                       SC_log(LOG_NOTICE, "Could not acquire network configuration lock: %s",
-                              SCErrorString(sc_status));
-                       return FALSE;
-               }
-       }
-
-       keyList = SCPreferencesCopyKeyList(prefs);
-       if (keyList == NULL) {
-               goto error;
-       }
-
-       currentModel = _SC_hw_model(FALSE);
-       if (currentModel == NULL) {
-               goto error;
-       }
-
-       /* Create "model:" string for prefix-check */
-       modelPrefixStr = CFStringCreateMutableCopy(NULL, 0, currentModel);
-       CFStringAppend(modelPrefixStr, CFSTR(":"));
+       CFDictionaryRef system;
 
-       keyListCount = CFArrayGetCount(keyList);
-       for (idx = 0; idx < keyListCount; idx++) {
-               CFStringRef existingKey = CFArrayGetValueAtIndex(keyList, idx);
-               CFStringRef key;
-               CFArrayRef splitKey = NULL;
-               CFPropertyListRef value;
-
-               if (isA_CFString(existingKey) == NULL) {
-                       continue;
-               }
-
-               if (!CFStringHasPrefix(existingKey, modelPrefixStr)) {
-                           continue;
-               }
-
-               splitKey = CFStringCreateArrayBySeparatingStrings(NULL, existingKey, CFSTR(":"));
-               key = CFArrayGetValueAtIndex(splitKey, 1);
-               value = SCPreferencesGetValue(prefs, existingKey);
-               SCPreferencesSetValue(prefs, key, value);
-               SCPreferencesRemoveValue(prefs, existingKey);
-               modified = TRUE;
-               CFRelease(splitKey);
-       }
-
-       if (modified) {
-               SCPreferencesRef        ni_prefs = NULL;
-               ni_prefs = SCPreferencesCreate(NULL, MY_PLUGIN_ID, CFSTR("NetworkInterfaces.plist"));
-               if (ni_prefs == NULL) {
-                       goto error;
-               }
-
-               ok = _SCNetworkConfigurationCheckValidityWithPreferences(prefs, ni_prefs, NULL);
-               CFRelease(ni_prefs);
-
-               //Commit the changes only if prefs files valid
-               if (ok) {
-                       if (!SCPreferencesCommitChanges(prefs)) {
-                               if (SCError() != EROFS) {
-                                       SC_log(LOG_NOTICE, "SCPreferencesCommitChanges() failed: %s",
-                                              SCErrorString(SCError()));
-                               }
-                               goto error;
-
-                       }
-
-                       (void) SCPreferencesApplyChanges(prefs);
-               }
+       // save "/System" (e.g. host names)
+       system = SCPreferencesGetValue(prefs, kSCPrefSystem);
+       if (system != NULL) {
+               CFRetain(system);
        }
 
-error:
-       (void) SCPreferencesUnlock(prefs);
+       // save the [previous devices] configuration
+       __SCNetworkConfigurationSaveModel(prefs, old_model);
 
-       if (keyList != NULL) {
-               CFRelease(keyList);
-       }
-       if (modelPrefixStr != NULL) {
-               CFRelease(modelPrefixStr);
+       if (system != NULL) {
+               // and retain "/System" (e.g. host names)
+               SCPreferencesSetValue(prefs, kSCPrefSystem, system);
+               CFRelease(system);
        }
 
-       return modified;
+       return;
 }
 
+
 static Boolean
 establishNewPreferences()
 {
        SCNetworkSetRef current         = NULL;
        CFStringRef     new_model;
        Boolean         ok              = FALSE;
+       CFStringRef     old_model;
        int             sc_status       = kSCStatusFailed;
        SCNetworkSetRef set             = NULL;
        Boolean         updated         = FALSE;
@@ -227,58 +145,18 @@ establishNewPreferences()
                }
        }
 
-       /* Ensure that the preferences has the new model */
+       // check if we need to regenerate the configuration for a new model
+       old_model = SCPreferencesGetValue(prefs, MODEL);
        new_model = _SC_hw_model(FALSE);
-
-       /* Need to regenerate the new configuration for new model */
-       if (new_model != NULL) {
-               CFStringRef     old_model;
-
-               old_model = SCPreferencesGetValue(prefs, MODEL);
-               if ((old_model != NULL) && !_SC_CFEqual(old_model, new_model)) {
-                       CFIndex         count;
-                       CFIndex         index;
-                       CFArrayRef      keys;
-
-                       keys = SCPreferencesCopyKeyList(prefs);
-                       count = (keys != NULL) ? CFArrayGetCount(keys) : 0;
-                       // if new hardware
-                       for (index = 0; index < count; index++) {
-                               CFStringRef             existing_key;
-
-                               existing_key = CFArrayGetValueAtIndex(keys, index);
-                               if (isA_CFString(existing_key) != NULL) {
-                                       CFStringRef             new_key;
-                                       CFPropertyListRef       value;
-
-                                       /* If it already contains a Model
-                                          or if it already contains a MODEL:KEY key skip it*/
-                                       if (CFEqual(existing_key, MODEL)
-                                           || CFStringFind(existing_key, CFSTR(":"), 0).location
-                                           != kCFNotFound) {
-                                               continue;
-                                       }
-
-                                       value = SCPreferencesGetValue(prefs, existing_key);
-
-                                       /* Create a new key as OLD_MODEL:OLD_KEY */
-                                       new_key = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@:%@"),
-                                                                          old_model, existing_key);
-                                       SCPreferencesSetValue(prefs, new_key, value);
-                                       if (!CFEqual(existing_key, kSCPrefSystem)) {
-                                               /* preserve existing host names */
-                                               SCPreferencesRemoveValue(prefs, existing_key);
-                                       }
-                                       CFRelease(new_key);
-                               }
-                       }
-
-                       if (keys != NULL) {
-                               CFRelease(keys);
-                       }
-               }
-               /* Set the new model */
-               SCPreferencesSetValue(prefs, MODEL, new_model);
+       if ((old_model != NULL) && !_SC_CFEqual(old_model, new_model)) {
+               SC_log(LOG_NOTICE, "Hardware model changed\n"
+                                  "  created on \"%@\"\n"
+                                  "  now on     \"%@\"",
+                      old_model,
+                      new_model);
+
+               // save (and clean) the configuration that was created for "other" hardware
+               savePastConfiguration(old_model);
        }
 
        current = SCNetworkSetCopyCurrent(prefs);
@@ -326,8 +204,12 @@ establishNewPreferences()
        }
 
        if (!ok) {
-               SC_log(LOG_NOTICE, "Could not establish network configuration: %s",
-                      SCErrorString(sc_status));
+               if (sc_status == kSCStatusOK) {
+                       SC_log(LOG_NOTICE, "Network configuration not updated");
+               } else {
+                       SC_log(LOG_NOTICE, "Could not establish network configuration: %s",
+                              SCErrorString(sc_status));
+               }
        }
 
        (void)SCPreferencesUnlock(prefs);
@@ -381,67 +263,98 @@ watchSCDynamicStore()
 }
 
 
-
-
 static Boolean
-previousConfigurationAvailable()
+findInterfaces(CFArrayRef interfaces, CFMutableArrayRef *matched_interfaces, CFMutableArrayRef *matched_names)
 {
-       CFStringRef             backupKey = NULL;
-       CFStringRef             currentModel = NULL;
-       CFPropertyListRef       properties = NULL;
+       CFIndex         n;
+       CFIndex         nx      = 0;
+       Boolean         updated = FALSE;
 
-       currentModel = _SC_hw_model(FALSE);
-       if (currentModel == NULL) {
-               goto done;
+       // start clean
+       if (*matched_interfaces != NULL) {
+               CFRelease(*matched_interfaces);
+               *matched_interfaces = NULL;
+       }
+       if (*matched_names != NULL) {
+               nx = CFArrayGetCount(*matched_names);
+               CFRelease(*matched_names);
+               *matched_names = NULL;
        }
 
-       /* Currently relying only if a backup of "Sets" is present */
-       backupKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@:Sets"), currentModel);
-       properties = SCPreferencesGetValue(prefs, backupKey);
-       CFRelease(backupKey);
-done:
-       return (properties != NULL);
+       n = (interfaces != NULL) ? CFArrayGetCount(interfaces) : 0;
+       for (CFIndex i = 0; i < n; i++) {
+               CFStringRef             bsdName  = CFArrayGetValueAtIndex(interfaces, i);
+               SCNetworkInterfaceRef   interface;
+
+               for (int retry = 0; retry < 10; retry++) {
+                       if (retry != 0) {
+                               // add short delay (before retry)
+                               usleep(20 * 1000);      // 20ms
+                       }
+
+                       interface = _SCNetworkInterfaceCreateWithBSDName(NULL, bsdName, kIncludeNoVirtualInterfaces);
+                       if (interface == NULL) {
+                               SC_log(LOG_ERR, "could not create network interface for %@", bsdName);
+                       } else if (_SCNetworkInterfaceGetIOPath(interface) == NULL) {
+                               SC_log(LOG_ERR, "could not get IOPath for %@", bsdName);
+                               CFRelease(interface);
+                               interface = NULL;
+                       }
+
+                       if (interface == NULL) {
+                               // if SCNetworkInterface not [currently] available
+                               continue;
+                       }
+
+                       // keep track of the interface name (quicker than having to iterate the list
+                       // of SCNetworkInterfaces, extract the name, and compare).
+                       if (*matched_names == NULL) {
+                               *matched_names = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+                       }
+                       CFArrayAppendValue(*matched_names, bsdName);
+
+                       if (*matched_interfaces == NULL) {
+                               *matched_interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+                       }
+                       CFArrayAppendValue(*matched_interfaces, interface);
+                       CFRelease(interface);
+
+                       updated = TRUE;
+                       break;
+               }
+       }
+
+       // check if all interfaces were detached
+       n = (*matched_names != NULL) ? CFArrayGetCount(*matched_names) : 0;
+       if ((nx > 0) && (n == 0)) {
+               updated = TRUE;
+       }
+
+       return updated;
 }
 
 
 static void
 storeCallback(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info)
 {
+#pragma unused(info)
        CFDictionaryRef dict;
-       CFArrayRef      interfaces      = NULL;
        Boolean         quiet           = FALSE;
        Boolean         timeout         = FALSE;
        Boolean         updated         = FALSE;
 
-       /*
-        * Capture/process KernelEventMonitor[.bundle] info
-        * 1. get list of active network interfaces
-        */
-       dict = SCDynamicStoreCopyValue(store, interfacesKey);
-       if (dict != NULL) {
-               if (isA_CFDictionary(dict)) {
-                       interfaces = CFDictionaryGetValue(dict, kSCPropNetInterfaces);
-                       interfaces = isA_CFArray(interfaces);
-                       if (interfaces != NULL) {
-                               CFRetain(interfaces);
-                       }
-               }
-
-               CFRelease(dict);
-       }
-
        /*
         * Capture/process InterfaceNamer[.bundle] info
         * 1. check if IORegistry "quiet", "timeout"
-        * 2. get list of named pre-configured interfaces
-        * 3. merge list of active interfaces (from KEV) with the
-        *    list of preconfigured interfaces.
+        * 2. update list of excluded interfaces (e.g. those requiring that
+        *    the attached host be trusted)
+        * 3. update list of named pre-configured interfaces
         */
        dict = SCDynamicStoreCopyValue(store, namerKey);
        if (dict != NULL) {
                if (isA_CFDictionary(dict)) {
-                       CFArrayRef              cur_preconfigured;
-                       CFMutableArrayRef       new_preconfigured       = NULL;
+                       CFArrayRef      excluded;
+                       CFArrayRef      preconfigured;
 
                        if (CFDictionaryContainsKey(dict, kInterfaceNamerKey_Quiet)) {
                                quiet = TRUE;
@@ -450,56 +363,54 @@ storeCallback(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info)
                                timeout = TRUE;
                        }
 
-                       cur_preconfigured = CFDictionaryGetValue(dict, kInterfaceNamerKey_PreConfiguredInterfaces);
-                       cur_preconfigured = isA_CFArray(cur_preconfigured);
-                       if ((cur_preconfigured != NULL) && (interfaces != NULL)) {
-                               CFIndex         i;
-                               CFIndex         n;
-                               CFRange         r       = CFRangeMake(0, CFArrayGetCount(interfaces));
-
-                               n = CFArrayGetCount(cur_preconfigured);
-                               for (i = 0; i < n; i++) {
-                                       CFStringRef     bsdName;
-
-                                       bsdName = CFArrayGetValueAtIndex(cur_preconfigured, i);
-                                       if (!CFArrayContainsValue(interfaces, r, bsdName)) {
-                                               // if interface not currently active
-                                               continue;
-                                       }
+                       excluded = CFDictionaryGetValue(dict, kInterfaceNamerKey_ExcludedInterfaces);
+                       excluded = isA_CFArray(excluded);
+                       if (!_SC_CFEqual(excluded, excluded_names)) {
+                               Boolean         excluded_updated;
 
-                                       if (new_preconfigured == NULL) {
-                                               new_preconfigured = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+                               excluded_updated = findInterfaces(excluded, &excluded_interfaces, &excluded_names);
+                               if (excluded_updated) {
+                                       CFStringRef     interfaces      = CFSTR("<empty>");
+
+                                       // report [updated] pre-configured interfaces
+                                       if (excluded_names != NULL) {
+                                               interfaces = CFStringCreateByCombiningStrings(NULL, excluded_names, CFSTR(","));
+                                       } else {
+                                               CFRetain(interfaces);
                                        }
-                                       CFArrayAppendValue(new_preconfigured, bsdName);
+                                       SC_log(LOG_INFO, "excluded interface list changed: %@", interfaces);
+                                       CFRelease(interfaces);
+
+                                       updated = TRUE;
                                }
                        }
 
-                       if (!_SC_CFEqual(preconfigured, new_preconfigured)) {
-                               SC_log(LOG_INFO, "pre-configured interface list changed");
+                       preconfigured = CFDictionaryGetValue(dict, kInterfaceNamerKey_PreConfiguredInterfaces);
+                       preconfigured = isA_CFArray(preconfigured);
+                       if (!_SC_CFEqual(preconfigured, preconfigured_names)) {
+                               Boolean         preconfigured_updated;
 
-                               if (preconfigured != NULL) {
-                                       CFRelease(preconfigured);
-                               }
-                               if (new_preconfigured != NULL) {
-                                       CFRetain(new_preconfigured);
-                               }
-                               preconfigured = new_preconfigured;
+                               preconfigured_updated = findInterfaces(preconfigured, &preconfigured_interfaces, &preconfigured_names);
+                               if (preconfigured_updated) {
+                                       CFStringRef     interfaces      = CFSTR("<empty>");
 
-                               updated = TRUE;
-                       }
+                                       // report [updated] pre-configured interfaces
+                                       if (preconfigured_names != NULL) {
+                                               interfaces = CFStringCreateByCombiningStrings(NULL, preconfigured_names, CFSTR(","));
+                                       } else {
+                                               CFRetain(interfaces);
+                                       }
+                                       SC_log(LOG_INFO, "pre-configured interface list changed: %@", interfaces);
+                                       CFRelease(interfaces);
 
-                       if (new_preconfigured != NULL) {
-                               CFRelease(new_preconfigured);
+                                       updated = TRUE;
+                               }
                        }
                }
 
                CFRelease(dict);
        }
 
-       if (interfaces != NULL) {
-               CFRelease(interfaces);
-       }
-
        if (!haveConfiguration && (quiet || timeout)) {
                static int      logged  = 0;
 
@@ -513,11 +424,6 @@ storeCallback(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info)
 
                (void) establishNewPreferences();
 
-               if (restorePrefs) {
-                       (void) restorePreferences();
-                       restorePrefs = FALSE;
-               }
-
                if (timeout && (logged++ == 0)) {
                        SC_log(LOG_ERR, "Network configuration creation timed out waiting for IORegistry");
                }
@@ -535,6 +441,7 @@ storeCallback(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info)
 static void
 updateCache(const void *key, const void *value, void *context)
 {
+#pragma unused(context)
        CFStringRef             configKey       = (CFStringRef)key;
        CFPropertyListRef       configData      = (CFPropertyListRef)value;
        CFPropertyListRef       cacheData;
@@ -656,75 +563,74 @@ flatten(SCPreferencesRef  prefs,
 }
 
 
-static CF_RETURNS_RETAINED SCNetworkServiceRef
-copyInterfaceService(SCNetworkSetRef set, CFStringRef matchName)
+static void
+excludeConfigurations(SCPreferencesRef prefs)
 {
-       CFIndex                 i;
-       CFIndex                 n;
-       SCNetworkServiceRef     service = NULL;
-       CFArrayRef              services;
+       Boolean         ok;
+       CFRange         range;
+       CFArrayRef      services;
+       SCNetworkSetRef set;
 
-       services = SCNetworkSetCopyServices(set);
-       assert(services != NULL);
+       range = CFRangeMake(0,
+                           (excluded_names != NULL) ? CFArrayGetCount(excluded_names) : 0);
+       if (range.length == 0) {
+               // if no [excluded] interfaces
+               return;
+       }
 
-       n = CFArrayGetCount(services);
-       for (i = 0; i < n; i++) {
-               SCNetworkInterfaceRef   interface;
+       set = SCNetworkSetCopyCurrent(prefs);
+       if (set == NULL) {
+               // if no current set
+               return;
+       }
+
+       /*
+        * Check for (and remove) any network services associated with
+        * an excluded interface from the prefs.
+        */
+       services = SCNetworkSetCopyServices(set);
+       if (services != NULL) {
+               CFIndex         n;
 
-               service = CFArrayGetValueAtIndex(services, i);
-               interface = SCNetworkServiceGetInterface(service);
-               if (interface != NULL) {
+               n = CFArrayGetCount(services);
+               for (CFIndex i = 0; i < n; i++) {
                        CFStringRef             bsdName;
+                       SCNetworkInterfaceRef   interface;
+                       SCNetworkServiceRef     service;
+
+                       service = CFArrayGetValueAtIndex(services, i);
+
+                       interface = SCNetworkServiceGetInterface(service);
+                       if (interface == NULL) {
+                               // if no interface
+                               continue;
+                       }
 
                        bsdName = SCNetworkInterfaceGetBSDName(interface);
-                       if (_SC_CFEqual(bsdName, matchName)) {
-                               // if match
-                               CFRetain(service);
-                               break;
+                       if (bsdName == NULL) {
+                               // if no interface name
+                               continue;
                        }
-               }
 
-               service = NULL;
-       }
+                       if (!CFArrayContainsValue(excluded_names, range, bsdName)) {
+                               // if not excluded
+                               continue;
+                       }
 
-       CFRelease(services);
-       return service;
-}
+                       // remove [excluded] network service from the prefs
+                       SC_log(LOG_NOTICE, "excluding network service for %@", bsdName);
+                       ok = SCNetworkSetRemoveService(set, service);
+                       if (!ok) {
+                               SC_log(LOG_ERR, "SCNetworkSetRemoveService() failed: %s",
+                                      SCErrorString(SCError()));
+                       }
+               }
 
+               CFRelease(services);
+       }
 
-static CF_RETURNS_RETAINED CFStringRef
-copyInterfaceUUID(CFStringRef bsdName)
-{
-       union {
-               unsigned char   sha1_bytes[CC_SHA1_DIGEST_LENGTH];
-               CFUUIDBytes     uuid_bytes;
-       } bytes;
-       CC_SHA1_CTX     ctx;
-       char            if_name[IF_NAMESIZE];
-       CFUUIDRef       uuid;
-       CFStringRef     uuid_str;
-
-       // start with interface name
-       bzero(&if_name, sizeof(if_name));
-       (void) _SC_cfstring_to_cstring(bsdName,
-                                      if_name,
-                                      sizeof(if_name),
-                                      kCFStringEncodingASCII);
-
-       // create SHA1 hash
-       bzero(&bytes, sizeof(bytes));
-       CC_SHA1_Init(&ctx);
-       CC_SHA1_Update(&ctx,
-                      if_name,
-                      sizeof(if_name));
-       CC_SHA1_Final(bytes.sha1_bytes, &ctx);
-
-       // create UUID string
-       uuid = CFUUIDCreateFromUUIDBytes(NULL, bytes.uuid_bytes);
-       uuid_str = CFUUIDCreateString(NULL, uuid);
-       CFRelease(uuid);
-
-       return uuid_str;
+       CFRelease(set);
+       return;
 }
 
 
@@ -733,132 +639,115 @@ updatePreConfiguredConfiguration(SCPreferencesRef prefs)
 {
        Boolean         ok;
        CFRange         range;
+       CFArrayRef      services;
        SCNetworkSetRef set;
        Boolean         updated = FALSE;
 
-       range.length = (preconfigured != NULL) ? CFArrayGetCount(preconfigured) : 0;
+       range = CFRangeMake(0,
+                           (preconfigured_names != NULL) ? CFArrayGetCount(preconfigured_names) : 0);
        if (range.length == 0) {
-               // if no [preconfigured] interfaces
+               // if no [pre-configured] interfaces
                return;
        }
-       range.location = 0;
 
        set = SCNetworkSetCopyCurrent(prefs);
-       if (set != NULL) {
-               CFArrayRef      services;
-
-               /*
-                * Check for (and remove) and network services associated with
-                * a pre-configured interface from the prefs.
-                */
-               services = SCNetworkSetCopyServices(set);
-               if (services != NULL) {
-                       CFIndex         n;
-
-                       n = CFArrayGetCount(services);
-                       for (CFIndex i = 0; i < n; i++) {
-                               CFStringRef             bsdName;
-                               SCNetworkInterfaceRef   interface;
-                               SCNetworkServiceRef     service;
-
-                               service = CFArrayGetValueAtIndex(services, i);
-
-                               interface = SCNetworkServiceGetInterface(service);
-                               if (interface == NULL) {
-                                       // if no interface
-                                       continue;
-                               }
-
-                               bsdName = SCNetworkInterfaceGetBSDName(interface);
-                               if (bsdName == NULL) {
-                                       // if no interface name
-                                       continue;
-                               }
-
-                               if (!CFArrayContainsValue(preconfigured, range, bsdName)) {
-                                       // if not preconfigured
-                                       continue;
-                               }
-
-                               // remove [preconfigured] network service from the prefs
-                               SC_log(LOG_NOTICE, "removing network service for %@", bsdName);
-                               SCNetworkServiceRemove(service);
-                               updated = TRUE;
-                       }
-
-                       CFRelease(services);
-               }
+       if (set == NULL) {
+               // if no current set
+               return;
+       }
 
-               if (updated) {
-                       // commit the updated prefs ... but don't apply
-                       ok = SCPreferencesCommitChanges(prefs);
-                       if (!ok) {
-                               if (SCError() != EROFS) {
-                                       SC_log(LOG_NOTICE, "SCPreferencesCommitChanges() failed: %s",
-                                              SCErrorString(SCError()));
-                               }
-                       }
-               }
+       /*
+        * Check for (and remove) any network services associated with
+        * a pre-configured interface from the prefs.
+        */
+       services = SCNetworkServiceCopyAll(prefs);
+       if (services != NULL) {
+               CFIndex         n;
 
-               /*
-                * Now, add a new network service for each pre-configured interface
-                */
-               for (CFIndex i = 0; i < range.length; i++) {
+               n = CFArrayGetCount(services);
+               for (CFIndex i = 0; i < n; i++) {
                        CFStringRef             bsdName;
                        SCNetworkInterfaceRef   interface;
                        SCNetworkServiceRef     service;
 
-                       bsdName = CFArrayGetValueAtIndex(preconfigured, i);
-                       interface = _SCNetworkInterfaceCreateWithBSDName(NULL, bsdName, kIncludeNoVirtualInterfaces);
+                       service = CFArrayGetValueAtIndex(services, i);
+
+                       interface = SCNetworkServiceGetInterface(service);
                        if (interface == NULL) {
-                               SC_log(LOG_ERR, "could not create network interface for %@", bsdName);
+                               // if no interface
                                continue;
                        }
 
-                       if (_SCNetworkInterfaceGetIOPath(interface) == NULL) {
-                               // if no [real] interface exists
-                               CFRelease(interface);
+                       bsdName = SCNetworkInterfaceGetBSDName(interface);
+                       if (bsdName == NULL) {
+                               // if no interface name
                                continue;
                        }
 
-                       ok = SCNetworkSetEstablishDefaultInterfaceConfiguration(set, interface);
-                       CFRelease(interface);
-                       if (!ok) {
-                               SC_log(LOG_ERR, "could not create network service for %@", bsdName);
+                       if (!CFArrayContainsValue(preconfigured_names, range, bsdName)) {
+                               // if not preconfigured
                                continue;
                        }
 
-                       service = copyInterfaceService(set, bsdName);
-                       if (service != NULL) {
-                               CFStringRef     serviceID;
-
-                               serviceID = copyInterfaceUUID(bsdName);
-                               if (serviceID != NULL) {
-                                       ok = _SCNetworkServiceSetServiceID(service, serviceID);
-                                       CFRelease(serviceID);
-                                       if (!ok) {
-                                               SC_log(LOG_ERR, "_SCNetworkServiceSetServiceID() failed: %s",
-                                                      SCErrorString(SCError()));
-                                               // ... and keep whatever random UUID was created for the service
-                                       }
-                               } else {
-                                       SC_log(LOG_ERR, "could not create serviceID for %@", bsdName);
-                                       // ... and we'll use whatever random UUID was created for the service
-                               }
+                       // remove [preconfigured] network service from the prefs
+                       SC_log(LOG_NOTICE, "removing network service for %@", bsdName);
+                       ok = SCNetworkServiceRemove(service);
+                       if (!ok) {
+                               SC_log(LOG_ERR, "SCNetworkServiceRemove() failed: %s",
+                                      SCErrorString(SCError()));
+                       }
+                       updated = TRUE;
+               }
 
-                               SC_log(LOG_INFO, "network service %@ added for %@",
-                                      SCNetworkServiceGetServiceID(service),
-                                      bsdName);
+               CFRelease(services);
+       }
 
-                               CFRelease(service);
-                       } else {
-                               SC_log(LOG_ERR, "could not find network service for %@", bsdName);
+       if (updated) {
+               // commit the updated prefs ... but don't apply
+               ok = SCPreferencesCommitChanges(prefs);
+               if (!ok) {
+                       if (SCError() != EROFS) {
+                               SC_log(LOG_ERR, "SCPreferencesCommitChanges() failed: %s",
+                                      SCErrorString(SCError()));
                        }
                }
+       }
 
-               CFRelease(set);
+       /*
+        * Now, add a new network service for each pre-configured interface
+        */
+       for (CFIndex i = 0; i < range.length; i++) {
+               CFStringRef             bsdName;
+               SCNetworkInterfaceRef   interface       = CFArrayGetValueAtIndex(preconfigured_interfaces, i);
+               SCNetworkServiceRef     service;
+
+               bsdName = SCNetworkInterfaceGetBSDName(interface);
+
+               // create network service
+               service = _SCNetworkServiceCreatePreconfigured(prefs, interface);
+               if (service == NULL) {
+                       continue;
+               }
+
+               // add network service to the current set
+               ok = SCNetworkSetAddService(set, service);
+               if (!ok) {
+                       SC_log(LOG_ERR, "could not add service for \"%@\": %s",
+                              bsdName,
+                              SCErrorString(SCError()));
+                       SCNetworkServiceRemove(service);
+                       CFRelease(service);
+                       continue;
+               }
+
+               SC_log(LOG_INFO, "network service %@ added for \"%@\"",
+                      SCNetworkServiceGetServiceID(service),
+                      bsdName);
+
+               CFRelease(service);
        }
 
+       CFRelease(set);
        return;
 }
 
@@ -1055,13 +944,7 @@ updateConfiguration(SCPreferencesRef              prefs,
                    SCPreferencesNotification   notificationType,
                    void                        *info)
 {
-       os_activity_t   activity;
-
-       activity = os_activity_create("processing [SC] preferences.plist changes",
-                                     OS_ACTIVITY_CURRENT,
-                                     OS_ACTIVITY_FLAG_DEFAULT);
-       os_activity_scope(activity);
-
+#pragma unused(info)
 #if    !TARGET_OS_IPHONE
        if ((notificationType & kSCPreferencesNotificationCommit) == kSCPreferencesNotificationCommit) {
                SCNetworkSetRef current;
@@ -1084,6 +967,9 @@ updateConfiguration(SCPreferencesRef               prefs,
        /* add any [Apple] pre-configured network services */
        updatePreConfiguredConfiguration(prefs);
 
+       /* remove any excluded network services */
+       excludeConfigurations(prefs);
+
        /* update SCDynamicStore (Setup:) */
        updateSCDynamicStore(prefs);
 
@@ -1094,8 +980,6 @@ updateConfiguration(SCPreferencesRef               prefs,
 
     done :
 
-       os_release(activity);
-
        return;
 }
 
@@ -1113,10 +997,19 @@ prime_PreferencesMonitor()
 }
 
 
+#ifndef        MAIN
+#define        PREFERENCES_MONITOR_PLIST       NULL
+#else  // !MAIN
+#define        PREFERENCES_MONITOR_PLIST       CFSTR("/tmp/preferences.plist")
+#endif // !MAIN
+
+
 __private_extern__
 void
 load_PreferencesMonitor(CFBundleRef bundle, Boolean bundleVerbose)
 {
+#pragma unused(bundle)
+#pragma unused(bundleVerbose)
        SC_log(LOG_DEBUG, "load() called");
        SC_log(LOG_DEBUG, "  bundle ID = %@", CFBundleGetIdentifier(bundle));
 
@@ -1131,27 +1024,34 @@ load_PreferencesMonitor(CFBundleRef bundle, Boolean bundleVerbose)
        }
 
        /* open a SCPreferences session */
-#ifndef        MAIN
-       prefs = SCPreferencesCreate(NULL, CFSTR("PreferencesMonitor.bundle"), NULL);
-#else  // !MAIN
-       prefs = SCPreferencesCreate(NULL, CFSTR("PreferencesMonitor.bundle"), CFSTR("/tmp/preferences.plist"));
-#endif // !MAIN
+       prefs = SCPreferencesCreateWithOptions(NULL,
+                                              MY_PLUGIN_ID,
+                                              PREFERENCES_MONITOR_PLIST,
+                                              NULL,    // authorization
+                                              NULL);
        if (prefs != NULL) {
                Boolean         need_update = FALSE;
-               CFStringRef     new_model;
+               CFStringRef     new_model;
+               CFStringRef     old_model;
+
+               // check if we need to update the configuration
+               __SCNetworkConfigurationUpgrade(&prefs, NULL, TRUE);
 
+               // check if we need to regenerate the configuration for a new model
+               old_model = SCPreferencesGetValue(prefs, MODEL);
                new_model = _SC_hw_model(FALSE);
+               if ((old_model != NULL) && !_SC_CFEqual(old_model, new_model)) {
+                       SC_log(LOG_NOTICE, "Hardware model changed\n"
+                                          "  created on \"%@\"\n"
+                                          "  now on     \"%@\"",
+                              old_model,
+                              new_model);
 
-               /* Need to regenerate the new configuration for new model */
-               if (new_model != NULL) {
-                       CFStringRef     old_model;
+                       // save (and clean) the configuration that was created for "other" hardware
+                       savePastConfiguration(old_model);
 
-                       old_model = SCPreferencesGetValue(prefs, MODEL);
-                       if (old_model != NULL && !_SC_CFEqual(old_model, new_model)) {
-                               // if new hardware
-                               need_update = TRUE;
-                               restorePrefs = previousConfigurationAvailable();
-                       }
+                       // ... and we'll update the configuration later (when the IORegistry quiesces)
+                       need_update = TRUE;
                }
 
                if (!need_update) {
@@ -1207,7 +1107,7 @@ load_PreferencesMonitor(CFBundleRef bundle, Boolean bundleVerbose)
 int
 main(int argc, char **argv)
 {
-       _sc_log     = FALSE;
+       _sc_log     = kSCLogDestinationFile;
        _sc_verbose = (argc > 1) ? TRUE : FALSE;
 
        load_PreferencesMonitor(CFBundleGetMainBundle(), (argc > 1) ? TRUE : FALSE);