X-Git-Url: https://git.saurik.com/apple/configd.git/blobdiff_plain/78403150fdf95618c483be7dbe6bca9459b92a9f..d94708881e41bd90afd74b1a1dd0524d039ba3f7:/SystemConfiguration.fproj/SCNetworkSet.c diff --git a/SystemConfiguration.fproj/SCNetworkSet.c b/SystemConfiguration.fproj/SCNetworkSet.c index d9576f6..bfcf499 100644 --- a/SystemConfiguration.fproj/SCNetworkSet.c +++ b/SystemConfiguration.fproj/SCNetworkSet.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2004-2014 Apple Inc. All rights reserved. + * Copyright (c) 2004-2019 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -31,10 +31,7 @@ #include #include -#include #include "SCNetworkConfigurationInternal.h" -#include -#include #include @@ -69,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(" {"), cf, allocator); + CFStringAppendFormat(result, NULL, CFSTR(" {"), 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; @@ -157,10 +158,9 @@ __SCNetworkSetCreatePrivate(CFAllocatorRef allocator, return NULL; } + /* initialize non-zero/NULL members */ setPrivate->setID = CFStringCreateCopy(NULL, setID); setPrivate->prefs = CFRetain(prefs); - setPrivate->name = NULL; - setPrivate->established = FALSE; // "new" (not yet established) set return setPrivate; } @@ -183,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; @@ -202,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; @@ -241,9 +268,6 @@ _serviceOrder_add(SCNetworkSetRef set, SCNetworkServiceRef service) CFArrayInsertValueAtIndex(newOrder, slot, serviceID); (void) SCNetworkSetSetServiceOrder(set, newOrder); - - done : - CFRelease(newOrder); return; @@ -253,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; @@ -261,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); @@ -288,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) { @@ -361,8 +431,7 @@ ensure_unique_service_name(SCNetworkServiceRef service) } if (SCError() != kSCStatusKeyExists) { - SCLog(TRUE, LOG_DEBUG, - CFSTR("could not update service name for \"%@\": %s"), + SC_log(LOG_INFO, "could not update service name for \"%@\": %s", SCNetworkInterfaceGetLocalizedDisplayName(interface), SCErrorString(SCError())); break; @@ -370,8 +439,7 @@ ensure_unique_service_name(SCNetworkServiceRef service) newName = copy_next_name(name); if (newName == NULL) { - SCLog(TRUE, LOG_DEBUG, - CFSTR("could not create unique name for \"%@\": %s"), + SC_log(LOG_INFO, "could not create unique name for \"%@\": %s", SCNetworkInterfaceGetLocalizedDisplayName(interface), SCErrorString(SCError())); break; @@ -414,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); @@ -473,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" @@ -500,6 +590,10 @@ SCNetworkSetAddService(SCNetworkSetRef set, SCNetworkServiceRef service) done : + if (ok) { + SC_log(LOG_DEBUG, "SCNetworkSetAddService(): %@, %@", set, service); + } + if (interface_config != NULL) CFRelease(interface_config); return ok; } @@ -587,10 +681,7 @@ SCNetworkSetCopyAll(SCPreferencesRef prefs) SCNetworkSetPrivateRef setPrivate; if (!isA_CFDictionary(vals[i])) { - SCLog(TRUE, - LOG_INFO, - CFSTR("SCNetworkSetCopyAll(): error w/set \"%@\"\n"), - keys[i]); + SC_log(LOG_INFO, "error w/set \"%@\"", keys[i]); continue; } @@ -713,7 +804,7 @@ SCNetworkSetCopyCurrent(SCPreferencesRef prefs) // mark set as "old" (already established) setPrivate->established = TRUE; } else { - SCLog(TRUE, LOG_ERR, CFSTR("SCNetworkSetCopyCurrent(): preferences are non-conformant")); + SC_log(LOG_NOTICE, "SCNetworkSetCopyCurrent(): preferences are non-conformant"); } CFRelease(path); } @@ -767,11 +858,9 @@ SCNetworkSetCopyServices(SCNetworkSetRef set) link = SCPreferencesPathGetLink(setPrivate->prefs, path); CFRelease(path); if (link == NULL) { - SCLog(TRUE, - LOG_INFO, - CFSTR("SCNetworkSetCopyServices(): service \"%@\" for set \"%@\" is not a link\n"), - keys[i], - setPrivate->setID); + SC_log(LOG_INFO, "service \"%@\" for set \"%@\" is not a link", + keys[i], + setPrivate->setID); continue; // if the service is not a link } @@ -784,14 +873,31 @@ SCNetworkSetCopyServices(SCNetworkSetRef set) serviceID, // service NULL); // entity if (CFEqual(path, link)) { - SCNetworkServicePrivateRef servicePrivate; - - servicePrivate = __SCNetworkServiceCreatePrivate(NULL, - setPrivate->prefs, - serviceID, - NULL); - CFArrayAppendValue(array, (SCNetworkServiceRef)servicePrivate); - CFRelease(servicePrivate); + CFDictionaryRef entity; + CFStringRef interfacePath; + Boolean skip = FALSE; + + interfacePath = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator + serviceID, // service + kSCEntNetInterface); // entity + entity = SCPreferencesPathGetValue(setPrivate->prefs, interfacePath); + CFRelease(interfacePath); + + if (__SCNetworkInterfaceEntityIsPPTP(entity)) { + SC_log(LOG_INFO, "PPTP services are no longer supported"); + skip = TRUE; + } + + if (!skip) { + SCNetworkServicePrivateRef servicePrivate; + + servicePrivate = __SCNetworkServiceCreatePrivate(NULL, + setPrivate->prefs, + serviceID, + NULL); + CFArrayAppendValue(array, (SCNetworkServiceRef)servicePrivate); + CFRelease(servicePrivate); + } } CFRelease(path); } @@ -847,10 +953,73 @@ SCNetworkSetCreate(SCPreferencesRef prefs) setPrivate = NULL; } + if (setPrivate != NULL) { + SC_log(LOG_DEBUG, "SCNetworkSetCreate(): %@", setPrivate); + } + return (SCNetworkSetRef)setPrivate; } +SCNetworkSetRef +_SCNetworkSetCreateDefault(SCPreferencesRef prefs) +{ + CFStringRef model; + Boolean ok = TRUE; + SCNetworkSetRef set; + CFStringRef setName = NULL; + + set = SCNetworkSetCopyCurrent(prefs); + if (set != NULL) { + SC_log(LOG_NOTICE, "creating default set w/already existing set"); + CFRelease(set); + _SCErrorSet(kSCStatusKeyExists); + return NULL; + } + + // create a new ("Automatic") set + set = SCNetworkSetCreate(prefs); + if (set == NULL) { + SC_log(LOG_NOTICE, "could not create \"new\" set: %s", + SCErrorString(SCError())); + goto done; + } + + 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", + SCErrorString(SCError())); + goto done; + } + + ok = SCNetworkSetSetCurrent(set); + if (!ok) { + // if we could not make this the "current" set + SC_log(LOG_NOTICE, "could not establish new set as current: %s", + SCErrorString(SCError())); +// goto done; + } + + model = SCPreferencesGetValue(prefs, MODEL); + if (model == NULL) { + model = _SC_hw_model(FALSE); + SCPreferencesSetValue(prefs, MODEL, model); + } + + done : + + if (!ok && (set != NULL)) { + SCNetworkSetRemove(set); + CFRelease(set); + set = NULL; + } + return set; +} + + CFStringRef SCNetworkSetGetSetID(SCNetworkSetRef set) { @@ -868,7 +1037,6 @@ SCNetworkSetGetSetID(SCNetworkSetRef set) CFStringRef SCNetworkSetGetName(SCNetworkSetRef set) { - CFBundleRef bundle; CFDictionaryRef entity; CFStringRef path; SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set; @@ -895,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; @@ -967,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) { @@ -980,15 +1153,35 @@ 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)) { ok = SCPreferencesPathRemoveValue(setPrivate->prefs, path); } else { + SC_log(LOG_DEBUG, "SCNetworkSetRemove() failed, currently active: %@", setPrivate->setID); _SCErrorSet(kSCStatusInvalidArgument); } CFRelease(path); + if (ok) { + SC_log(LOG_DEBUG, "SCNetworkSetRemove(): %@", set); + } + return ok; } @@ -1014,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); @@ -1041,12 +1251,15 @@ SCNetworkSetRemoveService(SCNetworkSetRef set, SCNetworkServiceRef service) // push the [deep] interface configuration [back] into all sets which contain the service. if (interface_config != NULL) { __SCNetworkInterfaceSetDeepConfiguration(set, interface, interface_config); + CFRelease(interface_config); } - if (interface_config != NULL) CFRelease(interface_config); - if (!ok) { + if (ok) { + SC_log(LOG_DEBUG, "SCNetworkSetRemoveService(): %@, %@", set, service); + } else { _SCErrorSet(sc_status); } + return ok; } @@ -1063,9 +1276,21 @@ 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); + + if (ok) { + SC_log(LOG_DEBUG, "SCNetworkSetSetCurrent(): %@", set); + } + return ok; } @@ -1073,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; @@ -1086,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("")); + _SC_crash_once("SCNetworkSetSetName() w/removed set", NULL, NULL); + _SCErrorSet(kSCStatusInvalidArgument); + return FALSE; + } + if ((name != NULL) && !isA_CFString(name)) { _SCErrorSet(kSCStatusInvalidArgument); return FALSE; @@ -1094,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 + } + +#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 -#define PREVENT_DUPLICATE_SET_NAMES -#ifdef PREVENT_DUPLICATE_SET_NAMES if (name != NULL) { CFArrayRef sets; @@ -1152,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; } } @@ -1195,6 +1439,10 @@ SCNetworkSetSetName(SCNetworkSetRef set, CFStringRef name) done : + if (ok) { + SC_log(LOG_DEBUG, "SCNetworkSetSetName(): %@", set); + } + if (localized != NULL) CFRelease(localized); if (non_localized != NULL) CFRelease(non_localized); return ok; @@ -1204,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; @@ -1215,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; @@ -1248,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); @@ -1261,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) { @@ -1396,7 +1694,7 @@ copyServices(SCNetworkSetRef set) #if !TARGET_OS_IPHONE -static CFArrayRef +static CF_RETURNS_RETAINED CFArrayRef updateServices(CFArrayRef services, SCNetworkInterfaceRef interface) { CFStringRef bsdName; @@ -1460,17 +1758,51 @@ 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; CFArrayRef services; SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set; Boolean updated = FALSE; +#if !TARGET_OS_IPHONE Boolean updatedIFs = FALSE; +#endif // !TARGET_OS_IPHONE #if TARGET_OS_IPHONE CFArrayRef orphans = NULL; @@ -1505,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; @@ -1517,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; } @@ -1560,10 +1891,9 @@ __SCNetworkSetEstablishDefaultConfigurationForInterfaces(SCNetworkSetRef set, CF ok = SCBridgeInterfaceSetMemberInterfaces(bridge, newMembers); CFRelease(newMembers); if (!ok) { - SCLog(TRUE, LOG_DEBUG, - CFSTR("could not update bridge with \"%@\": %s\n"), - SCNetworkInterfaceGetLocalizedDisplayName(interface), - SCErrorString(SCError())); + SC_log(LOG_INFO, "could not update bridge with \"%@\": %s", + SCNetworkInterfaceGetLocalizedDisplayName(interface), + SCErrorString(SCError())); CFRelease(bridge); continue; } @@ -1599,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; @@ -1611,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; } @@ -1636,20 +1965,18 @@ __SCNetworkSetEstablishDefaultConfigurationForInterfaces(SCNetworkSetRef set, CF service = SCNetworkServiceCreate(setPrivate->prefs, interface); if (service == NULL) { - SCLog(TRUE, LOG_DEBUG, - CFSTR("could not create service for \"%@\": %s\n"), - SCNetworkInterfaceGetLocalizedDisplayName(interface), - SCErrorString(SCError())); + SC_log(LOG_ERR, "could not create service for \"%@\": %s", + SCNetworkInterfaceGetLocalizedDisplayName(interface), + SCErrorString(SCError())); ok = FALSE; goto nextInterface; } ok = SCNetworkServiceEstablishDefaultConfiguration(service); if (!ok) { - SCLog(TRUE, LOG_DEBUG, - CFSTR("could not estabish default configuration for \"%@\": %s\n"), - SCNetworkInterfaceGetLocalizedDisplayName(interface), - SCErrorString(SCError())); + SC_log(LOG_ERR, "could not estabish default configuration for \"%@\": %s", + SCNetworkInterfaceGetLocalizedDisplayName(interface), + SCErrorString(SCError())); SCNetworkServiceRemove(service); CFRelease(service); goto nextInterface; @@ -1657,10 +1984,9 @@ __SCNetworkSetEstablishDefaultConfigurationForInterfaces(SCNetworkSetRef set, CF ok = SCNetworkSetAddService(set, service); if (!ok) { - SCLog(TRUE, LOG_DEBUG, - CFSTR("could not add service for \"%@\": %s\n"), - SCNetworkInterfaceGetLocalizedDisplayName(interface), - SCErrorString(SCError())); + SC_log(LOG_ERR, "could not add service for \"%@\": %s", + SCNetworkInterfaceGetLocalizedDisplayName(interface), + SCErrorString(SCError())); SCNetworkServiceRemove(service); CFRelease(service); goto nextInterface; @@ -1678,9 +2004,13 @@ __SCNetworkSetEstablishDefaultConfigurationForInterfaces(SCNetworkSetRef set, CF } CFRelease(interface_list); } - if (updatedIFs) CFRelease(interfaces); +#if !TARGET_OS_IPHONE + 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) { @@ -1705,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; @@ -1930,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; @@ -1971,9 +2320,11 @@ _SCNetworkSetSetSetID(SCNetworkSetRef set, CFStringRef newSetID) CFRelease(currentSet); } + SC_log(LOG_DEBUG, "_SCNetworkSetSetID(): %@ --> %@", set, newSetID); + + // replace setID with new one CFRetain(newSetID); CFRelease(setPrivate->setID); - setPrivate->setID = newSetID; if (updateCurrentSet) {