]> git.saurik.com Git - apple/configd.git/blobdiff - SystemConfiguration.fproj/SCNetworkSet.c
configd-1061.40.2.tar.gz
[apple/configd.git] / SystemConfiguration.fproj / SCNetworkSet.c
index a9ae4e4ea1348337e6bf810e20655a22e228e9c6..bfcf499e614a4e9e2c0592070ac49ff67927aa66 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2016 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2019 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  *
@@ -66,15 +66,19 @@ __SCNetworkSetCopyDescription(CFTypeRef cf)
 {
        CFAllocatorRef          allocator       = CFGetAllocator(cf);
        CFMutableStringRef      result;
-       SCNetworkSetPrivateRef  setPrivate      = (SCNetworkSetPrivateRef)cf;
+       SCNetworkSetRef         set             = (SCNetworkSetRef)cf;
+       SCNetworkSetPrivateRef  setPrivate      = (SCNetworkSetPrivateRef)set;
 
        result = CFStringCreateMutable(allocator, 0);
-       CFStringAppendFormat(result, NULL, CFSTR("<SCNetworkSet %p [%p]> {"), cf, allocator);
+       CFStringAppendFormat(result, NULL, CFSTR("<SCNetworkSet %p [%p]> {"), set, allocator);
        CFStringAppendFormat(result, NULL, CFSTR("id = %@"), setPrivate->setID);
        CFStringAppendFormat(result, NULL, CFSTR(", prefs = %p"), setPrivate->prefs);
        if (setPrivate->name != NULL) {
                CFStringAppendFormat(result, NULL, CFSTR(", name = %@"), setPrivate->name);
        }
+       if (!__SCNetworkSetExists(set)) {
+               CFStringAppendFormat(result, NULL, CFSTR(", REMOVED"));
+       }
        CFStringAppendFormat(result, NULL, CFSTR("}"));
 
        return result;
@@ -179,15 +183,42 @@ _serviceOrder(SCNetworkServiceRef service)
 }
 
 
+static CFIndex
+_serviceOrder_clear(CFMutableArrayRef order, CFStringRef serviceID)
+{
+       CFIndex f;      // # of serviceID's found
+       CFIndex i;
+       CFIndex n;
+
+       f = 0;
+       i = 0;
+       n = CFArrayGetCount(order);
+       while (i < n) {
+               CFStringRef     thisServiceID   = CFArrayGetValueAtIndex(order, i);
+
+               if (CFEqual(thisServiceID, serviceID)) {
+                       // remove the serviceID
+                       CFArrayRemoveValueAtIndex(order, i);
+                       n--;
+                       f++;
+                       continue;
+               }
+
+               i++;    // move to the next serviceID
+       }
+
+       return f;
+}
+
+
 static void
 _serviceOrder_add(SCNetworkSetRef set, SCNetworkServiceRef service)
 {
-       CFIndex                 i;
        CFIndex                 n;
        CFMutableArrayRef       newOrder;
        CFArrayRef              order;
-       CFStringRef             serviceID;
-       CFIndex                 serviceOrder;
+       CFStringRef             serviceID       = SCNetworkServiceGetServiceID(service);
+       CFIndex                 serviceOrder    = _serviceOrder(service);
        SCNetworkSetPrivateRef  setPrivate      = (SCNetworkSetPrivateRef)set;
        CFIndex                 slot;
 
@@ -198,18 +229,18 @@ _serviceOrder_add(SCNetworkSetRef set, SCNetworkServiceRef service)
                newOrder = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
        }
        assert(newOrder != NULL);
-       n = CFArrayGetCount(newOrder);
 
-       serviceID = SCNetworkServiceGetServiceID(service);
-       if (CFArrayContainsValue(newOrder, CFRangeMake(0, n), serviceID)) {
-               // if serviceID already present
-               goto done;
+       n = _serviceOrder_clear(newOrder, serviceID);
+       if (n > 0) {
+               SC_log(LOG_ERR, "SCNetworkSetAddService() w/service already in ServiceOrder\n  service = %@\n  matched = %ld",
+                      service,
+                      n);
+               _SC_crash_once("SCNetworkSetAddService() w/service already in ServiceOrder", NULL, NULL);
        }
 
-       serviceOrder = _serviceOrder(service);
-
        slot = 0;
-       for (i = 0; i < n; i++) {
+       n = CFArrayGetCount(newOrder);
+       for (CFIndex i = 0; i < n; i++) {
                int                     slotOrder;
                SCNetworkServiceRef     slotService;
                CFStringRef             slotServiceID;
@@ -237,9 +268,6 @@ _serviceOrder_add(SCNetworkSetRef set, SCNetworkServiceRef service)
 
        CFArrayInsertValueAtIndex(newOrder, slot, serviceID);
        (void) SCNetworkSetSetServiceOrder(set, newOrder);
-
-    done :
-
        CFRelease(newOrder);
 
        return;
@@ -249,6 +277,7 @@ _serviceOrder_add(SCNetworkSetRef set, SCNetworkServiceRef service)
 static void
 _serviceOrder_remove(SCNetworkSetRef set, SCNetworkServiceRef service)
 {
+       CFIndex                 n;
        CFMutableArrayRef       newOrder;
        CFArrayRef              order;
        CFStringRef             serviceID;
@@ -257,22 +286,17 @@ _serviceOrder_remove(SCNetworkSetRef set, SCNetworkServiceRef service)
        if (order == NULL) {
                return;
        }
-
-       serviceID = SCNetworkServiceGetServiceID(service);
-
        newOrder = CFArrayCreateMutableCopy(NULL, 0, order);
-       while (TRUE) {
-               CFIndex i;
 
-               i = CFArrayGetFirstIndexOfValue(newOrder,
-                                               CFRangeMake(0, CFArrayGetCount(newOrder)),
-                                               serviceID);
-               if (i == kCFNotFound) {
-                       break;
-               }
+       serviceID = SCNetworkServiceGetServiceID(service);
 
-               CFArrayRemoveValueAtIndex(newOrder, i);
+       n = _serviceOrder_clear(newOrder, serviceID);
+       if (n > 1) {
+               SC_log(LOG_ERR, "SCNetworkSetRemoveService() w/multiple instances of service in ServiceOrder\n  service = %@\n  count = %ld",
+                      service,
+                      n);
        }
+
        (void) SCNetworkSetSetServiceOrder(set, newOrder);
        CFRelease(newOrder);
 
@@ -284,11 +308,61 @@ _serviceOrder_remove(SCNetworkSetRef set, SCNetworkServiceRef service)
 #pragma mark SCNetworkSet APIs
 
 
+#define DEFAULT_SET_NAME       CFSTR("Automatic")
 #define        N_QUICK 16
 
 
-#define PREVENT_DUPLICATE_SERVICE_NAMES
-#ifdef  PREVENT_DUPLICATE_SERVICE_NAMES
+static CFStringRef
+copy_default_set_name(Boolean loc)
+{
+       CFStringRef             name;
+       static CFStringRef      non_localized   = NULL;
+       static CFStringRef      localized       = NULL;
+
+       if (!loc) {
+               static dispatch_once_t  once;
+
+               dispatch_once(&once, ^{
+                       CFBundleRef     bundle;
+
+                       bundle = _SC_CFBundleGet();
+                       if (bundle != NULL) {
+                               non_localized = _SC_CFBundleCopyNonLocalizedString(bundle,
+                                                                                  CFSTR("DEFAULT_SET_NAME"),
+                                                                                  DEFAULT_SET_NAME,
+                                                                                  NULL);
+                       }
+               });
+               name = non_localized;
+       } else {
+               static dispatch_once_t  once;
+
+               dispatch_once(&once, ^{
+                       CFBundleRef     bundle;
+
+                       bundle = _SC_CFBundleGet();
+                       if (bundle != NULL) {
+                               localized = CFBundleCopyLocalizedString(bundle,
+                                                                       CFSTR("DEFAULT_SET_NAME"),
+                                                                       DEFAULT_SET_NAME,
+                                                                       NULL);
+                       }
+               });
+               name = localized;
+       }
+
+       if (name == NULL) {
+               // if bundle or localized names not available
+               name = DEFAULT_SET_NAME;
+       }
+
+       CFRetain(name);
+       return name;
+}
+
+
+#define        PREVENT_DUPLICATE_SERVICE_NAMES
+#ifdef PREVENT_DUPLICATE_SERVICE_NAMES
 static CFStringRef
 copy_next_name(CFStringRef name)
 {
@@ -408,6 +482,23 @@ SCNetworkSetAddService(SCNetworkSetRef set, SCNetworkServiceRef service)
                return FALSE;
        }
 
+       if (!__SCNetworkSetExists(set)) {
+               SC_log(LOG_ERR, "SCNetworkSetAddService() w/removed set\n  set = %@\n  service = %@",
+                      set,
+                      service);
+               _SC_crash_once("SCNetworkSetAddService() w/removed set", NULL, NULL);
+               _SCErrorSet(kSCStatusInvalidArgument);
+       }
+
+       if (!__SCNetworkServiceExists(service)) {
+               SC_log(LOG_ERR, "SCNetworkSetAddService() w/removed service\n  set = %@\n  service =  %@",
+                      set,
+                      service);
+               _SC_crash_once("SCNetworkSetAddService() w/removed service", NULL, NULL);
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return FALSE;
+       }
+
        // make sure that we do not add an orphaned network service if its
        // associated interface is a member of a bond or bridge.
        interface = SCNetworkServiceGetInterface(service);
@@ -467,7 +558,12 @@ SCNetworkSetAddService(SCNetworkSetRef set, SCNetworkServiceRef service)
        ok = SCPreferencesPathSetLink(setPrivate->prefs, path, link);
 #ifdef PREVENT_DUPLICATE_SERVICE_NAMES
        if (ok) {
+               // We use the interface cache here to not reach into the
+               // IORegistry for every service we go through
+               _SCNetworkInterfaceCacheOpen();
                ok = ensure_unique_service_name(service);
+               _SCNetworkInterfaceCacheClose();
+
                if (!ok) {
                        // if we could not ensure a unique name, remove the (just added)
                        // link between the "set" and the "service"
@@ -868,7 +964,7 @@ SCNetworkSetCreate(SCPreferencesRef prefs)
 SCNetworkSetRef
 _SCNetworkSetCreateDefault(SCPreferencesRef prefs)
 {
-       CFBundleRef     bundle;
+       CFStringRef     model;
        Boolean         ok              = TRUE;
        SCNetworkSetRef set;
        CFStringRef     setName         = NULL;
@@ -889,15 +985,9 @@ _SCNetworkSetCreateDefault(SCPreferencesRef prefs)
                goto done;
        }
 
-       bundle = _SC_CFBundleGet();
-       if (bundle != NULL) {
-               setName = CFBundleCopyLocalizedString(bundle,
-                                                     CFSTR("DEFAULT_SET_NAME"),
-                                                     CFSTR("Automatic"),
-                                                     NULL);
-       }
-
-       ok = SCNetworkSetSetName(set, (setName != NULL) ? setName : CFSTR("Automatic"));
+       setName = copy_default_set_name(TRUE);
+       ok = SCNetworkSetSetName(set, setName);
+       CFRelease(setName);
        if (!ok) {
                // if we could not save the new set's "name"
                SC_log(LOG_NOTICE, "could not save the new set's name: %s",
@@ -913,6 +1003,12 @@ _SCNetworkSetCreateDefault(SCPreferencesRef prefs)
 //             goto done;
        }
 
+       model = SCPreferencesGetValue(prefs, MODEL);
+       if (model == NULL) {
+               model = _SC_hw_model(FALSE);
+               SCPreferencesSetValue(prefs, MODEL, model);
+       }
+
     done :
 
        if (!ok && (set != NULL)) {
@@ -920,7 +1016,6 @@ _SCNetworkSetCreateDefault(SCPreferencesRef prefs)
                CFRelease(set);
                set = NULL;
        }
-       if (setName != NULL) CFRelease(setName);
        return set;
 }
 
@@ -942,7 +1037,6 @@ SCNetworkSetGetSetID(SCNetworkSetRef set)
 CFStringRef
 SCNetworkSetGetName(SCNetworkSetRef set)
 {
-       CFBundleRef             bundle;
        CFDictionaryRef         entity;
        CFStringRef             path;
        SCNetworkSetPrivateRef  setPrivate      = (SCNetworkSetPrivateRef)set;
@@ -969,33 +1063,20 @@ SCNetworkSetGetName(SCNetworkSetRef set)
                }
        }
 
-       bundle = _SC_CFBundleGet();
-       if (bundle != NULL) {
-               if (setPrivate->name != NULL) {
-                       CFStringRef     non_localized;
-
-                       non_localized = _SC_CFBundleCopyNonLocalizedString(bundle,
-                                                                          CFSTR("DEFAULT_SET_NAME"),
-                                                                          CFSTR("Automatic"),
-                                                                          NULL);
-                       if (non_localized != NULL) {
-                               if (CFEqual(setPrivate->name, non_localized)) {
-                                       CFStringRef     localized;
-
-                                       // if "Automatic", return localized name
-                                       localized = CFBundleCopyLocalizedString(bundle,
-                                                                               CFSTR("DEFAULT_SET_NAME"),
-                                                                               CFSTR("Automatic"),
-                                                                               NULL);
-                                       if (localized != NULL) {
-                                               CFRelease(setPrivate->name);
-                                               setPrivate->name = localized;
-                                       }
-                               }
+       if (setPrivate->name != NULL) {
+               CFStringRef     non_localized;
 
-                               CFRelease(non_localized);
-                       }
+               non_localized = copy_default_set_name(FALSE);
+               if (CFEqual(setPrivate->name, non_localized)) {
+                       CFStringRef     localized;
+
+                       // if "Automatic", return localized name
+                       localized = copy_default_set_name(TRUE);
+                       CFRelease(setPrivate->name);
+                       setPrivate->name = localized;
                }
+
+               CFRelease(non_localized);
        }
 
        return setPrivate->name;
@@ -1041,6 +1122,24 @@ SCNetworkSetGetTypeID(void)
 }
 
 
+#if    TARGET_OS_IPHONE
+static Boolean
+isDefaultSet(SCNetworkSetRef set)
+{
+       CFStringRef     defaultName;
+       Boolean         isDefault       = FALSE;
+       CFStringRef     setName;
+
+       defaultName = copy_default_set_name(TRUE);
+       setName = SCNetworkSetGetName(set);
+       isDefault = _SC_CFEqual(setName, defaultName);
+       CFRelease(defaultName);
+
+       return isDefault;
+}
+#endif // TARGET_OS_IPHONE
+
+
 Boolean
 SCNetworkSetRemove(SCNetworkSetRef set)
 {
@@ -1054,6 +1153,21 @@ SCNetworkSetRemove(SCNetworkSetRef set)
                return FALSE;
        }
 
+       if (!__SCNetworkSetExists(set)) {
+               SC_log(LOG_ERR, "SCNetworkSetRemove() w/removed set\n  set = %@", set);
+               _SC_crash_once("SCNetworkSetRemove() w/removed set", NULL, NULL);
+               _SCErrorSet(kSCStatusInvalidArgument);
+       }
+
+#if    TARGET_OS_IPHONE
+       if (isDefaultSet(set) && (geteuid() != 0)) {
+               SC_log(LOG_ERR, "SCNetworkSetRemove() failed, cannot remove set : %@", set);
+               _SC_crash("The \"Automatic\" network set cannot be removed", NULL, NULL);
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return FALSE;
+       }
+#endif // TARGET_OS_IPHONE
+
        currentPath = SCPreferencesGetValue(setPrivate->prefs, kSCPrefCurrentSet);
        path = SCPreferencesPathKeyCreateSet(NULL, setPrivate->setID);
        if (!isA_CFString(currentPath) || !CFEqual(currentPath, path)) {
@@ -1093,6 +1207,23 @@ SCNetworkSetRemoveService(SCNetworkSetRef set, SCNetworkServiceRef service)
                return FALSE;
        }
 
+       if (!__SCNetworkSetExists(set)) {
+               SC_log(LOG_ERR, "SCNetworkSetRemoveService() w/removed set\n  set = %@\n  service = %@",
+                      set,
+                      service);
+               _SC_crash_once("SCNetworkSetRemoveService() w/removed set", NULL, NULL);
+               _SCErrorSet(kSCStatusInvalidArgument);
+       }
+
+       if (!__SCNetworkServiceExists(service)) {
+               SC_log(LOG_ERR, "SCNetworkSetRemoveService() w/removed service\n  set = %@\n  service = %@",
+                      set,
+                      service);
+               _SC_crash_once("SCNetworkSetRemoveService() w/removed service", NULL, NULL);
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return FALSE;
+       }
+
        // remove service from ServiceOrder
        _serviceOrder_remove(set, service);
 
@@ -1145,6 +1276,13 @@ SCNetworkSetSetCurrent(SCNetworkSetRef set)
                return FALSE;
        }
 
+       if (!__SCNetworkSetExists(set)) {
+               SC_log(LOG_ERR, "SCNetworkSetSetCurrent() w/removed set\n  set = %@", set);
+               _SC_crash_once("SCNetworkSetSetCurrent() w/removed set", NULL, NULL);
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return FALSE;
+       }
+
        path = SCPreferencesPathKeyCreateSet(NULL, setPrivate->setID);
        ok = SCPreferencesSetValue(setPrivate->prefs, kSCPrefCurrentSet, path);
        CFRelease(path);
@@ -1160,8 +1298,10 @@ SCNetworkSetSetCurrent(SCNetworkSetRef set)
 Boolean
 SCNetworkSetSetName(SCNetworkSetRef set, CFStringRef name)
 {
-       CFBundleRef             bundle          = NULL;
        CFDictionaryRef         entity;
+#if    TARGET_OS_IPHONE
+       Boolean                 isDefaultName   = FALSE;
+#endif // TARGET_OS_IPHONE
        CFStringRef             localized       = NULL;
        CFStringRef             non_localized   = NULL;
        Boolean                 ok              = FALSE;
@@ -1173,6 +1313,15 @@ SCNetworkSetSetName(SCNetworkSetRef set, CFStringRef name)
                return FALSE;
        }
 
+       if (!__SCNetworkSetExists(set)) {
+               SC_log(LOG_ERR, "SCNetworkSetSetName() w/removed set\n  set = %@\n  name = %@",
+                      set,
+                      name != NULL ? name : CFSTR("<NULL>"));
+               _SC_crash_once("SCNetworkSetSetName() w/removed set", NULL, NULL);
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return FALSE;
+       }
+
        if ((name != NULL) && !isA_CFString(name)) {
                _SCErrorSet(kSCStatusInvalidArgument);
                return FALSE;
@@ -1181,28 +1330,42 @@ SCNetworkSetSetName(SCNetworkSetRef set, CFStringRef name)
        // if known, compare against localized name
 
        if (name != NULL) {
-               bundle = _SC_CFBundleGet();
-               if (bundle != NULL) {
-                       non_localized = _SC_CFBundleCopyNonLocalizedString(bundle,
-                                                                          CFSTR("DEFAULT_SET_NAME"),
-                                                                          CFSTR("Automatic"),
-                                                                          NULL);
-                       if (non_localized != NULL) {
-                               if (CFEqual(name, non_localized)) {
-                                       localized = CFBundleCopyLocalizedString(bundle,
-                                                                               CFSTR("DEFAULT_SET_NAME"),
-                                                                               CFSTR("Automatic"),
-                                                                               NULL);
-                                       if (localized != NULL) {
-                                               name = localized;
-                                       }
-                               }
-                       }
+               non_localized = copy_default_set_name(FALSE);
+               if (CFEqual(name, non_localized)) {
+                       localized = copy_default_set_name(TRUE);
+                       name = localized;
+#if    TARGET_OS_IPHONE
+                       isDefaultName = TRUE;
+#endif // TARGET_OS_IPHONE
+               }
+#if    TARGET_OS_IPHONE
+               else {
+                       localized = copy_default_set_name(TRUE);
+                       isDefaultName = CFEqual(name, non_localized);
                }
+#endif // TARGET_OS_IPHONE
        }
 
-#define PREVENT_DUPLICATE_SET_NAMES
-#ifdef  PREVENT_DUPLICATE_SET_NAMES
+#if    TARGET_OS_IPHONE
+       if (!isDefaultName && isDefaultSet(set) && (geteuid() != 0)) {
+               // if we are trying to change the name of the "Automatic" set
+               SC_log(LOG_ERR, "SCNetworkSetSetName() failed, cannot rename : %@", set);
+               _SC_crash("The \"Automatic\" network set cannot be renamed", NULL, NULL);
+               _SCErrorSet(kSCStatusInvalidArgument);
+               goto done;
+       }
+#endif // TARGET_OS_IPHONE
+
+#define        PREVENT_DUPLICATE_SET_NAMES
+#ifdef PREVENT_DUPLICATE_SET_NAMES
+
+#if    TARGET_OS_IPHONE
+       if (!isDefaultName) {
+               // On iOS, only block naming multiple sets with the name
+               // "Automatic".  Others names are OK.
+       } else
+#endif // TARGET_OS_IPHONE
+
        if (name != NULL) {
                CFArrayRef      sets;
 
@@ -1239,18 +1402,12 @@ SCNetworkSetSetName(SCNetworkSetRef set, CFStringRef name)
 
        // if known, store non-localized name
 
-       if ((name != NULL) && (bundle != NULL) && (non_localized != NULL)) {
+       if ((name != NULL) && (non_localized != NULL)) {
                if (localized == NULL) {
-                       localized = CFBundleCopyLocalizedString(bundle,
-                                                               CFSTR("DEFAULT_SET_NAME"),
-                                                               CFSTR("Automatic"),
-                                                               NULL);
+                       localized = copy_default_set_name(TRUE);
                }
-
-               if (localized != NULL) {
-                       if (CFEqual(name, localized)) {
-                               name = non_localized;
-                       }
+               if (CFEqual(name, localized)) {
+                       name = non_localized;
                }
        }
 
@@ -1295,7 +1452,10 @@ SCNetworkSetSetName(SCNetworkSetRef set, CFStringRef name)
 Boolean
 SCNetworkSetSetServiceOrder(SCNetworkSetRef set, CFArrayRef newOrder)
 {
+       CFMutableArrayRef       cleanOrder;
        CFDictionaryRef         dict;
+       CFIndex                 i;
+       CFIndex                 n;
        CFMutableDictionaryRef  newDict;
        Boolean                 ok;
        CFStringRef             path;
@@ -1306,10 +1466,15 @@ SCNetworkSetSetServiceOrder(SCNetworkSetRef set, CFArrayRef newOrder)
                return FALSE;
        }
 
-       if (isA_CFArray(newOrder)) {
-               CFIndex i;
-               CFIndex n       = CFArrayGetCount(newOrder);
+       if (!__SCNetworkSetExists(set)) {
+               SC_log(LOG_ERR, "SCNetworkSetSetServiceOrder() w/removed set\n  set = %@", set);
+               _SC_crash_once("SCNetworkSetSetServiceOrder() w/removed set", NULL, NULL);
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return FALSE;
+       }
 
+       if (isA_CFArray(newOrder)) {
+               n = CFArrayGetCount(newOrder);
                for (i = 0; i < n; i++) {
                        CFStringRef     serviceID;
 
@@ -1339,7 +1504,24 @@ SCNetworkSetSetServiceOrder(SCNetworkSetRef set, CFArrayRef newOrder)
                                                    &kCFTypeDictionaryValueCallBacks);
        }
 
-       CFDictionarySetValue(newDict, kSCPropNetServiceOrder, newOrder);
+       cleanOrder = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+       n = CFArrayGetCount(newOrder);
+       for (i = 0; i < n; i++) {
+               CFIndex         nClean          = CFArrayGetCount(cleanOrder);
+               CFStringRef     serviceID       = CFArrayGetValueAtIndex(newOrder, i);
+
+               if ((nClean == 0) ||
+                   !CFArrayContainsValue(cleanOrder, CFRangeMake(0, nClean), serviceID)) {
+                       // if first reference to this serviceID
+                       CFArrayAppendValue(cleanOrder, serviceID);
+               } else {
+                       // skip duplicate serviceID
+                       SC_log(LOG_ERR, "SCNetworkSetSetServiceOrder() found duplicate serviceID: removed %@\n", serviceID);
+               }
+       }
+       CFDictionarySetValue(newDict, kSCPropNetServiceOrder, cleanOrder);
+       CFRelease(cleanOrder);
+
        ok = SCPreferencesPathSetValue(setPrivate->prefs, path, newDict);
        CFRelease(newDict);
        CFRelease(path);
@@ -1352,6 +1534,31 @@ SCNetworkSetSetServiceOrder(SCNetworkSetRef set, CFArrayRef newOrder)
 #pragma mark SCNetworkSet SPIs
 
 
+__private_extern__
+Boolean
+__SCNetworkSetExists(SCNetworkSetRef set)
+{
+       CFDictionaryRef                 entity;
+       CFStringRef                     path;
+       SCNetworkSetPrivateRef          setPrivate      = (SCNetworkSetPrivateRef)set;
+
+       if (setPrivate->prefs == NULL) {
+               return FALSE;
+       }
+
+       path = SCPreferencesPathKeyCreateSet(NULL, setPrivate->setID);
+       entity = SCPreferencesPathGetValue(setPrivate->prefs, path);
+       CFRelease(path);
+
+       if (!isA_CFDictionary(entity)) {
+               // if no "set"
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+
 static void
 add_supported_interfaces(CFMutableArrayRef interface_list, SCNetworkInterfaceRef interface)
 {
@@ -1487,7 +1694,7 @@ copyServices(SCNetworkSetRef set)
 
 
 #if    !TARGET_OS_IPHONE
-static CFArrayRef
+static CF_RETURNS_RETAINED CFArrayRef
 updateServices(CFArrayRef services, SCNetworkInterfaceRef interface)
 {
        CFStringRef             bsdName;
@@ -1551,10 +1758,42 @@ skipInterface(SCNetworkInterfaceRef interface)
 }
 
 
+CFComparisonResult
+_SCNetworkSetCompare(const void *val1, const void *val2, void *context)
+{
+#pragma unused(context)
+       CFStringRef     id1;
+       CFStringRef     id2;
+       CFStringRef     name1;
+       CFStringRef     name2;
+       SCNetworkSetRef s1      = (SCNetworkSetRef)val1;
+       SCNetworkSetRef s2      = (SCNetworkSetRef)val2;
+
+       name1 = SCNetworkSetGetName(s1);
+       name2 = SCNetworkSetGetName(s2);
+
+       if (name1 != NULL) {
+               if (name2 != NULL) {
+                       return CFStringCompare(name1, name2, 0);
+               } else {
+                       return kCFCompareLessThan;
+               }
+       }
+
+       if (name2 != NULL) {
+               return kCFCompareGreaterThan;
+       }
+
+       id1 = SCNetworkSetGetSetID(s1);
+       id2 = SCNetworkSetGetSetID(s2);
+       return CFStringCompare(id1, id2, 0);
+}
+
+
 static Boolean
 __SCNetworkSetEstablishDefaultConfigurationForInterfaces(SCNetworkSetRef set, CFArrayRef interfaces, Boolean excludeHidden)
 {
-       CFSetRef                excluded        = NULL;
+       CFSetRef                excluded;
        CFIndex                 i;
        CFIndex                 n               = 0;
        Boolean                 ok              = TRUE;
@@ -1598,7 +1837,7 @@ __SCNetworkSetEstablishDefaultConfigurationForInterfaces(SCNetworkSetRef set, CF
 #if    !TARGET_OS_IPHONE
        // look for interfaces that should auto-magically be added
        // to an Ethernet bridge
-       n = (interfaces != NULL) ? CFArrayGetCount(interfaces) : 0;
+       n = ((services != NULL) && (interfaces != NULL)) ? CFArrayGetCount(interfaces) : 0;
        for (i = 0; i < n; i++) {
                SCBridgeInterfaceRef    bridge          = NULL;
                SCNetworkInterfaceRef   interface;
@@ -1610,8 +1849,7 @@ __SCNetworkSetEstablishDefaultConfigurationForInterfaces(SCNetworkSetRef set, CF
                        continue;
                }
 
-               if ((excluded != NULL)
-                   && CFSetContainsValue(excluded, interface)) {
+               if (CFSetContainsValue(excluded, interface)) {
                        // if this interface is a member of a Bond or Bridge
                        continue;
                }
@@ -1691,7 +1929,7 @@ __SCNetworkSetEstablishDefaultConfigurationForInterfaces(SCNetworkSetRef set, CF
        }
 #endif // !TARGET_OS_IPHONE
 
-       n = (interfaces != NULL) ? CFArrayGetCount(interfaces) : 0;
+       n = ((services != NULL) && (interfaces != NULL)) ? CFArrayGetCount(interfaces) : 0;
        for (i = 0; i < n; i++) {
                SCNetworkInterfaceRef   interface;
                CFMutableArrayRef       interface_list;
@@ -1703,8 +1941,7 @@ __SCNetworkSetEstablishDefaultConfigurationForInterfaces(SCNetworkSetRef set, CF
                        continue;
                }
 
-               if ((excluded != NULL)
-                   && CFSetContainsValue(excluded, interface)) {
+               if (CFSetContainsValue(excluded, interface)) {
                        // if this interface is a member of a Bond or Bridge
                        continue;
                }
@@ -1728,7 +1965,7 @@ __SCNetworkSetEstablishDefaultConfigurationForInterfaces(SCNetworkSetRef set, CF
 
                                service = SCNetworkServiceCreate(setPrivate->prefs, interface);
                                if (service == NULL) {
-                                       SC_log(LOG_INFO, "could not create service for \"%@\": %s",
+                                       SC_log(LOG_ERR, "could not create service for \"%@\": %s",
                                               SCNetworkInterfaceGetLocalizedDisplayName(interface),
                                               SCErrorString(SCError()));
                                        ok = FALSE;
@@ -1737,7 +1974,7 @@ __SCNetworkSetEstablishDefaultConfigurationForInterfaces(SCNetworkSetRef set, CF
 
                                ok = SCNetworkServiceEstablishDefaultConfiguration(service);
                                if (!ok) {
-                                       SC_log(LOG_INFO, "could not estabish default configuration for \"%@\": %s",
+                                       SC_log(LOG_ERR, "could not estabish default configuration for \"%@\": %s",
                                               SCNetworkInterfaceGetLocalizedDisplayName(interface),
                                               SCErrorString(SCError()));
                                        SCNetworkServiceRemove(service);
@@ -1747,7 +1984,7 @@ __SCNetworkSetEstablishDefaultConfigurationForInterfaces(SCNetworkSetRef set, CF
 
                                ok = SCNetworkSetAddService(set, service);
                                if (!ok) {
-                                       SC_log(LOG_INFO, "could not add service for \"%@\": %s",
+                                       SC_log(LOG_ERR, "could not add service for \"%@\": %s",
                                               SCNetworkInterfaceGetLocalizedDisplayName(interface),
                                               SCErrorString(SCError()));
                                        SCNetworkServiceRemove(service);
@@ -1768,10 +2005,12 @@ __SCNetworkSetEstablishDefaultConfigurationForInterfaces(SCNetworkSetRef set, CF
                CFRelease(interface_list);
        }
 #if    !TARGET_OS_IPHONE
-       if (updatedIFs)         CFRelease(interfaces);
+       if (updatedIFs && (interfaces != NULL)) {
+               CFRelease(interfaces);
+       }
 #endif // !TARGET_OS_IPHONE
        if (services != NULL)   CFRelease(services);
-       if (excluded != NULL)   CFRelease(excluded);
+       CFRelease(excluded);
 
 #if    TARGET_OS_IPHONE
        if (orphans != NULL) {
@@ -1796,9 +2035,19 @@ __SCNetworkSetEstablishDefaultConfigurationForInterfaces(SCNetworkSetRef set, CF
        }
 #endif // TARGET_OS_IPHONE
 
-       if (ok && !updated) {
-               // if no changes were made
-               _SCErrorSet(kSCStatusOK);
+       if (ok) {
+               if (updated) {
+                       CFStringRef     model;
+
+                       model = SCPreferencesGetValue(setPrivate->prefs, MODEL);
+                       if (model == NULL) {
+                               model = _SC_hw_model(FALSE);
+                               SCPreferencesSetValue(setPrivate->prefs, MODEL, model);
+                       }
+               } else {
+                       // if no changes were made
+                       _SCErrorSet(kSCStatusOK);
+               }
        }
 
        return updated;
@@ -2021,6 +2270,15 @@ _SCNetworkSetSetSetID(SCNetworkSetRef set, CFStringRef newSetID)
                return FALSE;
        }
 
+       if (!__SCNetworkSetExists(set)) {
+               SC_log(LOG_ERR, "_SCNetworkSetSetSetID() w/removed set\n  set = %@\n  setID = %@",
+                      set,
+                      newSetID);
+               _SC_crash_once("_SCNetworkSetSetSetID() w/removed set", NULL, NULL);
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return FALSE;
+       }
+
        // If newSetID is equal to current setID, our work is done
        if (CFEqual(newSetID, setPrivate->setID)) {
                return TRUE;