From d0784775d19430caad8c7b59c630e71eeeedda72 Mon Sep 17 00:00:00 2001 From: Apple Date: Mon, 29 Mar 2010 18:37:04 +0000 Subject: [PATCH] configd-293.4.tar.gz --- Plugins/ATconfig/Info.plist | 4 +- Plugins/IPMonitor/Info.plist | 4 +- Plugins/InterfaceNamer/Info.plist | 4 +- Plugins/InterfaceNamer/ifnamer.c | 353 +++++++++++++++--- Plugins/KernelEventMonitor/Info.plist | 4 +- Plugins/Kicker/Info.plist | 4 +- Plugins/LinkConfiguration/Info.plist | 4 +- Plugins/Logger/Info-Embedded.plist | 4 +- Plugins/Logger/Info.plist | 4 +- Plugins/NetworkIdentification/Info.plist | 4 +- Plugins/PreferencesMonitor/Info.plist | 4 +- SCMonitor/Info.plist | 4 +- SystemConfiguration.fproj/Info-Embedded.plist | 6 +- SystemConfiguration.fproj/Info.plist | 6 +- .../SCDNotifierInformViaCallback.c | 50 ++- .../SCNetworkConfigurationInternal.h | 5 + .../SCNetworkConfigurationPrivate.h | 9 + .../SCNetworkConnection.c | 42 +-- .../SCNetworkInterface.c | 150 +++++++- .../SCNetworkReachability.c | 73 ++-- scutil.tproj/notifications.c | 35 +- scutil.tproj/scutil.c | 8 +- scutil.tproj/scutil.h | 3 +- scutil.tproj/tests.c | 18 +- 24 files changed, 591 insertions(+), 211 deletions(-) diff --git a/Plugins/ATconfig/Info.plist b/Plugins/ATconfig/Info.plist index 0dd645a..666fd91 100644 --- a/Plugins/ATconfig/Info.plist +++ b/Plugins/ATconfig/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.10.1 + 1.10.2 CFBundleSignature ???? CFBundleVersion - 1.10.1 + 1.10.2 Builtin Requires diff --git a/Plugins/IPMonitor/Info.plist b/Plugins/IPMonitor/Info.plist index 3af5857..0f99e3e 100644 --- a/Plugins/IPMonitor/Info.plist +++ b/Plugins/IPMonitor/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.10.1 + 1.10.2 CFBundleSignature ???? CFBundleVersion - 1.10.1 + 1.10.2 Requires com.apple.SystemConfiguration.IPConfiguration diff --git a/Plugins/InterfaceNamer/Info.plist b/Plugins/InterfaceNamer/Info.plist index c856a4d..509fb22 100644 --- a/Plugins/InterfaceNamer/Info.plist +++ b/Plugins/InterfaceNamer/Info.plist @@ -17,10 +17,10 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.10.1 + 1.10.2 CFBundleSignature ???? CFBundleVersion - 1.10.1 + 1.10.2 diff --git a/Plugins/InterfaceNamer/ifnamer.c b/Plugins/InterfaceNamer/ifnamer.c index 1637c7a..f28450a 100644 --- a/Plugins/InterfaceNamer/ifnamer.c +++ b/Plugins/InterfaceNamer/ifnamer.c @@ -58,11 +58,14 @@ #include #include #include +#include +#include #include #include #include #include #include +#include #include #include @@ -73,18 +76,17 @@ #include #include +#include #include #include #include #include - -#ifndef kIOBuiltin -#define kIOBuiltin "IOBuiltin" -#endif +#include #define kIONetworkStackUserCommand "IONetworkStackUserCommand" #define kRegisterInterface 1 +#define kSCNetworkInterfaceInfo "SCNetworkInterfaceInfo" #define kSCNetworkInterfaceType "SCNetworkInterfaceType" #define kSCNetworkInterfaceActive "Active" @@ -537,6 +539,12 @@ createInterfaceDict(SCNetworkInterfaceRef interface) &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + val = _SCNetworkInterfaceCopyInterfaceInfo(interface); + if (val != NULL) { + CFDictionarySetValue(new_if, CFSTR(kSCNetworkInterfaceInfo), val); + CFRelease(val); + } + val = _SCNetworkInterfaceGetIOPath(interface); if (val != NULL) { CFDictionarySetValue(new_if, CFSTR(kIOPathMatchKey), val); @@ -652,42 +660,252 @@ lookupInterfaceByUnit(CFArrayRef db_list, SCNetworkInterfaceRef interface, CFInd return (NULL); } +typedef struct { + CFDictionaryRef match_info; + CFStringRef match_type; + CFBooleanRef match_builtin; + CFMutableArrayRef matches; +} matchContext, *matchContextRef; + static CFDictionaryRef -lookupAirPortInterface(CFArrayRef db_list, CFIndex * where) +thinInterfaceInfo(CFDictionaryRef info) { - CFIndex i; - CFIndex n; + CFNumberRef num; + int vid; - if (db_list == NULL) { - return (NULL); + if (CFDictionaryGetValueIfPresent(info, CFSTR(kUSBVendorID), (const void **)&num) + && isA_CFNumber(num) + && CFNumberGetValue(num, kCFNumberIntType, &vid) + && (vid == kIOUSBVendorIDAppleComputer)) { + CFMutableDictionaryRef thin; + + // if this is an Apple USB device than we trust that + // the non-localized name will be correct. + thin = CFDictionaryCreateMutableCopy(NULL, 0, info); + CFDictionaryRemoveValue(thin, CFSTR(kUSBProductString)); + CFDictionaryRemoveValue(thin, CFSTR(kUSBVendorID)); + CFDictionaryRemoveValue(thin, CFSTR(kUSBProductID)); + return thin; + } + + return CFRetain(info); +} + +static Boolean +matchInterfaceInfo(CFDictionaryRef known_info, CFDictionaryRef match_info) +{ + Boolean match; + + match = _SC_CFEqual(known_info, match_info); + if (!match && + isA_CFDictionary(known_info) && + isA_CFDictionary(match_info)) { + + // if not an exact match, try thinning + known_info = thinInterfaceInfo(known_info); + match_info = thinInterfaceInfo(match_info); + match = _SC_CFEqual(known_info, match_info); + CFRelease(known_info); + CFRelease(match_info); + } + + return match; +} + +static void +matchKnown(const void *value, void *context) +{ + CFDictionaryRef known_dict = (CFDictionaryRef)value; + matchContextRef match_context = (matchContextRef)context; + + // match interface type + { + CFStringRef known_type; + + known_type = CFDictionaryGetValue(known_dict, CFSTR(kSCNetworkInterfaceType)); + if (!_SC_CFEqual(known_type, match_context->match_type)) { + return; + } + } + + // match SCNetworkInterfaceInfo + { + CFDictionaryRef known_info; + + known_info = CFDictionaryGetValue(known_dict, CFSTR(kSCNetworkInterfaceInfo)); + if (!matchInterfaceInfo(known_info, match_context->match_info)) { + return; + } + } + + // if requested, match [non-]builtin + if (match_context->match_builtin != NULL) { + CFBooleanRef known_builtin; + + known_builtin = CFDictionaryGetValue(known_dict, CFSTR(kIOBuiltin)); + if (!isA_CFBoolean(known_builtin)) { + known_builtin = kCFBooleanFalse; + } + if (!_SC_CFEqual(known_builtin, match_context->match_builtin)) { + return; + } + } + + // if we have a match + if (match_context->matches == NULL) { + match_context->matches = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + } + CFArrayAppendValue(match_context->matches, known_dict); + + return; +} + +static void +matchUnnamed(const void *value, void *context) +{ + SCNetworkInterfaceRef known_if = (SCNetworkInterfaceRef)value; + matchContextRef match_context = (matchContextRef)context; + + if (match_context->matches == NULL) { + return; + } + + // match interface type + { + CFStringRef known_type; + + known_type = SCNetworkInterfaceGetInterfaceType(known_if); + if (!_SC_CFEqual(known_type, match_context->match_type)) { + return; + } } - n = CFArrayGetCount(db_list); - for (i = 0; i < n; i++) { - CFDictionaryRef dict; - CFStringRef if_type; - - dict = CFArrayGetValueAtIndex(db_list, i); - if_type = CFDictionaryGetValue(dict, CFSTR(kSCNetworkInterfaceType)); - if (if_type != NULL) { - if (CFEqual(if_type, kSCNetworkInterfaceTypeIEEE80211)) { - if (where) - *where = i; - return (dict); - } - } else { - CFStringRef path; - path = CFDictionaryGetValue(dict, CFSTR(kIOPathMatchKey)); - if ((CFStringFind(path, CFSTR("IO80211Interface") , 0).location != kCFNotFound) || - (CFStringFind(path, CFSTR("AirPort") , 0).location != kCFNotFound) || - (CFStringFind(path, CFSTR("AppleWireless80211"), 0).location != kCFNotFound)) { - if (where) - *where = i; - return (dict); + // match SCNetworkInterfaceInfo + { + CFDictionaryRef known_info; + Boolean match; + + known_info = _SCNetworkInterfaceCopyInterfaceInfo(known_if); + match = matchInterfaceInfo(known_info, match_context->match_info); + if (known_info != NULL) CFRelease(known_info); + if (!match) { + return; + } + } + + // if requested, match [non-]builtin + if (match_context->match_builtin != NULL) { + CFBooleanRef known_builtin; + + known_builtin = _SCNetworkInterfaceIsBuiltin(known_if) ? kCFBooleanTrue + : kCFBooleanFalse; + if (!_SC_CFEqual(known_builtin, match_context->match_builtin)) { + return; + } + } + + // if we have a match + CFRelease(match_context->matches); + match_context->matches = NULL; + + return; +} + +/* + * lookupMatchingInterface + * + * Looks at the interfaces that have already been [or need to be] named with + * the goal of allowing a system using a single network interface/adaptor of + * a given type (vendor, model, ...) to not care about the specific adaptor + * that is used (i.e. swapping dongle's is OK). Once a system has had more + * than one interface/adaptor connected at the same time than we assume that + * the network configuration is being setup for multi-homing that should be + * maintained. + * + * If no matches are found or if more than one match is found, return NULL. + * If a single match is found, return the match. + */ +static CFDictionaryRef +lookupMatchingInterface(SCNetworkInterfaceRef interface, + CFArrayRef db_list, // already named + CFArrayRef if_list, // to be named + CFIndex if_list_index, + CFBooleanRef builtin) +{ + CFStringRef if_type; + CFDictionaryRef match = NULL; + matchContext match_context; + + if_type = SCNetworkInterfaceGetInterfaceType(interface); + if (if_type == NULL) { + return NULL; + } + + match_context.match_type = if_type; + match_context.match_info = _SCNetworkInterfaceCopyInterfaceInfo(interface); + match_context.match_builtin = builtin; + match_context.matches = NULL; + + // check for matches to already named interfaces + // ... and appends each match that we find to match_context.matches + if (db_list != NULL) { + CFArrayApplyFunction(db_list, + CFRangeMake(0, CFArrayGetCount(db_list)), + matchKnown, + &match_context); + } + + // check for matches to to be named interfaces + // ... and CFReleases match_context.matches if we find another network + // interface of the same type that also needs to be named + if (if_list != NULL) { + CFIndex if_list_count; + + if_list_count = CFArrayGetCount(if_list); + if (if_list_index < if_list_count) { + CFArrayApplyFunction(if_list, + CFRangeMake(if_list_index, if_list_count - if_list_index), + matchUnnamed, + &match_context); + } + } + + // check if we have a single match + if (match_context.matches != NULL) { + if (CFArrayGetCount(match_context.matches) == 1) { + match = CFArrayGetValueAtIndex(match_context.matches, 0); + } + CFRelease(match_context.matches); + } + + if (match != NULL) { + Boolean active = TRUE; + CFStringRef name; + + name = CFDictionaryGetValue(match, CFSTR(kIOBSDNameKey)); + if (isA_CFString(name)) { + int sock; + + sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock != -1) { + struct ifreq ifr; + + (void)_SC_cfstring_to_cstring(name, ifr.ifr_name, sizeof(ifr.ifr_name), kCFStringEncodingASCII); + if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) { + // if interface name not currently in-use + active = FALSE; + } + close(sock); } } + + if (active) { + match = NULL; + } } - return (NULL); + + if (match_context.match_info != NULL) CFRelease(match_context.match_info); + return match; } static void @@ -947,6 +1165,7 @@ nameInterfaces(CFMutableArrayRef if_list) } } else { CFDictionaryRef dbdict; + boolean_t is_builtin; kern_return_t kr; dbdict = lookupInterfaceByAddress(S_dblist, interface, NULL); @@ -957,21 +1176,29 @@ nameInterfaces(CFMutableArrayRef if_list) SCLog(S_debug, LOG_INFO, CFSTR(MY_PLUGIN_NAME ": Interface assigned unit %@ (from database)"), unit); - } else { - CFStringRef if_type; + } + + if ((dbdict == NULL) && !isQuiet()) { + // if new interface, wait until quiet before naming + addTimestamp(S_state, path); + continue; + } - if_type = SCNetworkInterfaceGetInterfaceType(interface); - if ((if_type != NULL) && - CFEqual(if_type, kSCNetworkInterfaceTypeIEEE80211)) { - dbdict = lookupAirPortInterface(S_dblist, NULL); - if (dbdict != NULL) { - unit = CFDictionaryGetValue(dbdict, CFSTR(kIOInterfaceUnit)); - CFRetain(unit); + is_builtin = _SCNetworkInterfaceIsBuiltin(interface); - SCLog(S_debug, LOG_INFO, - CFSTR(MY_PLUGIN_NAME ": Interface assigned unit %@ (updating database)"), - unit); - } + if (dbdict == NULL) { + dbdict = lookupMatchingInterface(interface, + S_dblist, + if_list, + i + 1, + is_builtin ? kCFBooleanTrue : kCFBooleanFalse); + if (dbdict != NULL) { + unit = CFDictionaryGetValue(dbdict, CFSTR(kIOInterfaceUnit)); + CFRetain(unit); + + SCLog(S_debug, LOG_INFO, + CFSTR(MY_PLUGIN_NAME ": Interface assigned unit %@ (updating database)"), + unit); } } @@ -986,17 +1213,8 @@ nameInterfaces(CFMutableArrayRef if_list) } if (dbdict == NULL) { - boolean_t is_builtin; int next_unit = 0; - if (!isQuiet()) { - // if new interface, wait until quiet before naming - addTimestamp(S_state, path); - continue; - } - - is_builtin = _SCNetworkInterfaceIsBuiltin(interface); - next_unit = 0; if (is_builtin) { // built-in interface, use the reserved slots next_unit = builtinCount(if_list, i, type); @@ -1025,8 +1243,12 @@ nameInterfaces(CFMutableArrayRef if_list) kr = registerInterface(S_connect, path, unit); if (kr != KERN_SUCCESS) { SCLog(TRUE, LOG_ERR, - CFSTR(MY_PLUGIN_NAME ": failed to name the interface, kr=0x%x"), - kr); + CFSTR(MY_PLUGIN_NAME ": failed to name the interface, kr=0x%x\n" + MY_PLUGIN_NAME ": path = %@\n" + MY_PLUGIN_NAME ": unit = %@"), + kr, + path, + unit); if (S_debug) { displayInterface(interface); } @@ -1053,6 +1275,17 @@ nameInterfaces(CFMutableArrayRef if_list) CFArraySetValueAtIndex(if_list, i, new_interface); CFRelease(new_interface); interface = new_interface; // if_list holds the reference + + if (is_builtin && (S_prev_active_list != NULL)) { + CFIndex where; + + // update the list of [built-in] interfaces that were previously named + if (lookupInterfaceByUnit(S_prev_active_list, interface, &where) != NULL) { + SCLog(S_debug, LOG_INFO, + CFSTR(MY_PLUGIN_NAME ": and updated database (new address)")); + CFArrayRemoveValueAtIndex(S_prev_active_list, where); + } + } } } @@ -1109,9 +1342,11 @@ updateInterfaces() CFIndex n; n = CFArrayGetCount(S_prev_active_list); - SCLog(TRUE, LOG_INFO, - CFSTR(MY_PLUGIN_NAME ": Interface%s not [yet] active"), - (n > 0) ? "s" : ""); + if (n > 0) { + SCLog(TRUE, LOG_INFO, + CFSTR(MY_PLUGIN_NAME ": Interface%s not [yet] active"), + (n > 1) ? "s" : ""); + } for (i = 0; i < n; i++) { CFDictionaryRef if_dict; CFStringRef name; diff --git a/Plugins/KernelEventMonitor/Info.plist b/Plugins/KernelEventMonitor/Info.plist index 8c5c594..c3bedc5 100644 --- a/Plugins/KernelEventMonitor/Info.plist +++ b/Plugins/KernelEventMonitor/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.10.1 + 1.10.2 CFBundleSignature ???? CFBundleVersion - 1.10.1 + 1.10.2 Requires com.apple.SystemConfiguration.InterfaceNamer diff --git a/Plugins/Kicker/Info.plist b/Plugins/Kicker/Info.plist index bdbd2be..9265031 100644 --- a/Plugins/Kicker/Info.plist +++ b/Plugins/Kicker/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.10.1 + 1.10.2 CFBundleSignature ???? CFBundleVersion - 1.10.1 + 1.10.2 Requires com.apple.SystemConfiguration.ATconfig diff --git a/Plugins/LinkConfiguration/Info.plist b/Plugins/LinkConfiguration/Info.plist index 35c4f29..1a4ab83 100644 --- a/Plugins/LinkConfiguration/Info.plist +++ b/Plugins/LinkConfiguration/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.10.1 + 1.10.2 CFBundleSignature ???? CFBundleVersion - 1.10.1 + 1.10.2 Requires com.apple.SystemConfiguration.InterfaceNamer diff --git a/Plugins/Logger/Info-Embedded.plist b/Plugins/Logger/Info-Embedded.plist index f9f67de..36851c8 100644 --- a/Plugins/Logger/Info-Embedded.plist +++ b/Plugins/Logger/Info-Embedded.plist @@ -15,11 +15,11 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.10 + 1.10.2 CFBundleSignature ???? CFBundleVersion - 1.10 + 1.10.2 Enabled Verbose diff --git a/Plugins/Logger/Info.plist b/Plugins/Logger/Info.plist index 6187ec8..4dcca2b 100644 --- a/Plugins/Logger/Info.plist +++ b/Plugins/Logger/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.10.1 + 1.10.2 CFBundleSignature ???? CFBundleVersion - 1.10.1 + 1.10.2 Enabled Verbose diff --git a/Plugins/NetworkIdentification/Info.plist b/Plugins/NetworkIdentification/Info.plist index 2c86bd5..f812733 100644 --- a/Plugins/NetworkIdentification/Info.plist +++ b/Plugins/NetworkIdentification/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.10.1 + 1.10.2 CFBundleSignature ???? CFBundleVersion - 1.10.1 + 1.10.2 Builtin diff --git a/Plugins/PreferencesMonitor/Info.plist b/Plugins/PreferencesMonitor/Info.plist index 20944c8..005b738 100644 --- a/Plugins/PreferencesMonitor/Info.plist +++ b/Plugins/PreferencesMonitor/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.10.1 + 1.10.2 CFBundleSignature ???? CFBundleVersion - 1.10.1 + 1.10.2 Builtin Requires diff --git a/SCMonitor/Info.plist b/SCMonitor/Info.plist index 4e173ba..f502002 100644 --- a/SCMonitor/Info.plist +++ b/SCMonitor/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.10.1 + 1.10.2 CFBundleSignature ???? CFBundleVersion - 1.10.1 + 1.10.2 CFPlugInDynamicRegistration NO CFPlugInFactories diff --git a/SystemConfiguration.fproj/Info-Embedded.plist b/SystemConfiguration.fproj/Info-Embedded.plist index 8714e9f..c8bbf8b 100644 --- a/SystemConfiguration.fproj/Info-Embedded.plist +++ b/SystemConfiguration.fproj/Info-Embedded.plist @@ -7,7 +7,7 @@ CFBundleExecutable SystemConfiguration CFBundleGetInfoString - 1.10 + 1.10.2 CFBundleIdentifier com.apple.SystemConfiguration CFBundleInfoDictionaryVersion @@ -17,10 +17,10 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.10 + 1.10.2 CFBundleSignature ???? CFBundleVersion - 1.10 + 1.10.2 diff --git a/SystemConfiguration.fproj/Info.plist b/SystemConfiguration.fproj/Info.plist index c1ff999..c8bbf8b 100644 --- a/SystemConfiguration.fproj/Info.plist +++ b/SystemConfiguration.fproj/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable SystemConfiguration CFBundleGetInfoString - 1.10.1 + 1.10.2 CFBundleIdentifier com.apple.SystemConfiguration CFBundleInfoDictionaryVersion @@ -17,10 +17,10 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.10.1 + 1.10.2 CFBundleSignature ???? CFBundleVersion - 1.10.1 + 1.10.2 diff --git a/SystemConfiguration.fproj/SCDNotifierInformViaCallback.c b/SystemConfiguration.fproj/SCDNotifierInformViaCallback.c index 3e22cc4..f88afec 100644 --- a/SystemConfiguration.fproj/SCDNotifierInformViaCallback.c +++ b/SystemConfiguration.fproj/SCDNotifierInformViaCallback.c @@ -702,9 +702,7 @@ SCDynamicStoreSetDispatchQueue(SCDynamicStoreRef store, dispatch_queue_t queue) } if (queue != NULL) { - dispatch_queue_attr_t attr; - mach_port_t mp; - long res; + mach_port_t mp; if ((storePrivate->dispatchQueue != NULL) || (storePrivate->rls != NULL)) { _SCErrorSet(kSCStatusInvalidArgument); @@ -728,25 +726,10 @@ SCDynamicStoreSetDispatchQueue(SCDynamicStoreRef store, dispatch_queue_t queue) dispatch_retain(storePrivate->dispatchQueue); /* - * create a queue for the mig source, we'll use this queue's context - * to carry the store pointer for the callback code. + * create a dispatch queue for the mach notifications source, we'll use + * this queue's context to carry the store pointer for the callback code. */ - attr = dispatch_queue_attr_create(); - res = dispatch_queue_attr_set_finalizer(attr, - ^(dispatch_queue_t dq) { - SCDynamicStoreRef store; - - store = (SCDynamicStoreRef)dispatch_get_context(dq); - CFRelease(store); - }); - if (res != 0) { - SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStore dispatch_queue_attr_set_finalizer() failed")); - dispatch_release(attr); - _SCErrorSet(kSCStatusFailed); - goto cleanup; - } - storePrivate->callbackQueue = dispatch_queue_create("com.apple.SCDynamicStore.notifications", attr); - dispatch_release(attr); + storePrivate->callbackQueue = dispatch_queue_create("com.apple.SCDynamicStore.notifications", NULL); if (storePrivate->callbackQueue == NULL){ SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStore dispatch_queue_create() failed")); _SCErrorSet(kSCStatusFailed); @@ -754,16 +737,27 @@ SCDynamicStoreSetDispatchQueue(SCDynamicStoreRef store, dispatch_queue_t queue) } CFRetain(store); // Note: will be released when the dispatch queue is released dispatch_set_context(storePrivate->callbackQueue, (void *)store); + dispatch_set_finalizer_f(storePrivate->callbackQueue, (dispatch_function_t)CFRelease); - dispatch_suspend(storePrivate->callbackQueue); + /* + * create a dispatch source for the mach notifications + */ mp = CFMachPortGetPort(storePrivate->callbackPort); - storePrivate->callbackSource = dispatch_source_mig_create(mp, sizeof(mach_msg_header_t), NULL, storePrivate->callbackQueue, SCDynamicStoreNotifyMIGCallback); + storePrivate->callbackSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, + mp, + 0, + storePrivate->callbackQueue); if (storePrivate->callbackSource == NULL) { - SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStore dispatch_source_mig_create() failed")); + SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStore dispatch_source_create() failed")); _SCErrorSet(kSCStatusFailed); goto cleanup; } - dispatch_resume(storePrivate->callbackQueue); + dispatch_source_set_event_handler(storePrivate->callbackSource, ^{ + dispatch_mig_server(storePrivate->callbackSource, + sizeof(mach_msg_header_t), + SCDynamicStoreNotifyMIGCallback); + }); + dispatch_resume(storePrivate->callbackSource); ok = TRUE; goto done; @@ -779,7 +773,11 @@ SCDynamicStoreSetDispatchQueue(SCDynamicStoreRef store, dispatch_queue_t queue) cleanup : if (storePrivate->callbackSource != NULL) { - dispatch_cancel(storePrivate->callbackSource); + dispatch_source_cancel(storePrivate->callbackSource); + if (storePrivate->callbackQueue != dispatch_get_current_queue()) { + // ensure the cancellation has completed + dispatch_sync(storePrivate->callbackQueue, ^{}); + } dispatch_release(storePrivate->callbackSource); storePrivate->callbackSource = NULL; } diff --git a/SystemConfiguration.fproj/SCNetworkConfigurationInternal.h b/SystemConfiguration.fproj/SCNetworkConfigurationInternal.h index 55305ed..13ff626 100644 --- a/SystemConfiguration.fproj/SCNetworkConfigurationInternal.h +++ b/SystemConfiguration.fproj/SCNetworkConfigurationInternal.h @@ -139,6 +139,11 @@ typedef struct { Boolean modemIsV92; CFNumberRef type; CFNumberRef unit; + struct { + CFStringRef name; + CFNumberRef vid; + CFNumberRef pid; + } usb; // misc int sort_order; // sort order for this interface diff --git a/SystemConfiguration.fproj/SCNetworkConfigurationPrivate.h b/SystemConfiguration.fproj/SCNetworkConfigurationPrivate.h index ec41e4c..63ba880 100644 --- a/SystemConfiguration.fproj/SCNetworkConfigurationPrivate.h +++ b/SystemConfiguration.fproj/SCNetworkConfigurationPrivate.h @@ -167,6 +167,15 @@ _SCNetworkInterfaceCreateWithIONetworkInterfaceObject (io_object_t if_obj) __ #define kSCNetworkInterfaceConfigurationActionValuePrompt CFSTR("Prompt") #define kSCNetworkInterfaceConfigurationActionValueConfigure CFSTR("Configure") +/*! + @function _SCNetworkInterfaceCopyInterfaceInfo + @discussion Returns interface details + @param interface The network interface. + @result A dictionary with details about the network interface. + */ +CFDictionaryRef +_SCNetworkInterfaceCopyInterfaceInfo (SCNetworkInterfaceRef interface) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_3_0); + /*! @function _SCNetworkInterfaceGetConfigurationAction @discussion Returns a user-notification / auto-configuration action for the interface. diff --git a/SystemConfiguration.fproj/SCNetworkConnection.c b/SystemConfiguration.fproj/SCNetworkConnection.c index 2ec298f..01aeb22 100644 --- a/SystemConfiguration.fproj/SCNetworkConnection.c +++ b/SystemConfiguration.fproj/SCNetworkConnection.c @@ -1108,41 +1108,35 @@ __SCNetworkConnectionScheduleWithRunLoop(SCNetworkConnectionRef connection, #if !TARGET_OS_IPHONE if (queue != NULL) { - dispatch_queue_attr_t attr; - mach_port_t mp; - long res; + mach_port_t mp; connectionPrivate->dispatchQueue = queue; dispatch_retain(connectionPrivate->dispatchQueue); - attr = dispatch_queue_attr_create(); - res = dispatch_queue_attr_set_finalizer(attr, - ^(dispatch_queue_t dq) { - SCNetworkConnectionRef connection; - - connection = (SCNetworkConnectionRef)dispatch_get_context(dq); - CFRelease(connection); - }); - if (res != 0) { - SCLog(TRUE, LOG_ERR, CFSTR("SCNetworkConnection dispatch_queue_attr_set_finalizer() failed")); - dispatch_release(attr); - goto fail; - } - connectionPrivate->callbackQueue = dispatch_queue_create("com.apple.SCNetworkConnection.notifications", attr); - dispatch_release(attr); + connectionPrivate->callbackQueue = dispatch_queue_create("com.apple.SCNetworkConnection.notifications", NULL); if (connectionPrivate->callbackQueue == NULL){ SCLog(TRUE, LOG_ERR, CFSTR("SCNetworkConnection dispatch_queue_create() failed")); goto fail; } CFRetain(connection); // Note: will be released when the dispatch queue is released dispatch_set_context(connectionPrivate->callbackQueue, connectionPrivate); + dispatch_set_finalizer_f(connectionPrivate->callbackQueue, (dispatch_function_t)CFRelease); mp = CFMachPortGetPort(connectionPrivate->notify_port); - connectionPrivate->callbackSource = dispatch_source_mig_create(mp, sizeof(mach_msg_header_t), NULL, connectionPrivate->callbackQueue, SCNetworkConnectionNotifyMIGCallback); + connectionPrivate->callbackSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, + mp, + 0, + connectionPrivate->callbackQueue); if (connectionPrivate->callbackSource == NULL) { - SCLog(TRUE, LOG_ERR, CFSTR("SCNetworkConnection dispatch_source_mig_create() failed")); + SCLog(TRUE, LOG_ERR, CFSTR("SCNetworkConnection dispatch_source_create() failed")); goto fail; } + dispatch_source_set_event_handler(connectionPrivate->callbackSource, ^{ + dispatch_mig_server(connectionPrivate->callbackSource, + sizeof(mach_msg_header_t), + SCNetworkConnectionNotifyMIGCallback); + }); + dispatch_resume(connectionPrivate->callbackSource); } else #endif // !TARGET_OS_IPHONE { @@ -1163,7 +1157,7 @@ __SCNetworkConnectionScheduleWithRunLoop(SCNetworkConnectionRef connection, fail : if (connectionPrivate->callbackSource != NULL) { - dispatch_cancel(connectionPrivate->callbackSource); + dispatch_source_cancel(connectionPrivate->callbackSource); dispatch_release(connectionPrivate->callbackSource); connectionPrivate->callbackSource = NULL; } @@ -1219,7 +1213,11 @@ __SCNetworkConnectionUnscheduleFromRunLoop(SCNetworkConnectionRef connection, #if !TARGET_OS_IPHONE if (runLoop == NULL) { - dispatch_cancel(connectionPrivate->callbackSource); + dispatch_source_cancel(connectionPrivate->callbackSource); + if (connectionPrivate->callbackQueue != dispatch_get_current_queue()) { + // ensure the cancellation has completed + dispatch_sync(connectionPrivate->callbackQueue, ^{}); + } dispatch_release(connectionPrivate->callbackSource); connectionPrivate->callbackSource = NULL; dispatch_release(connectionPrivate->callbackQueue); diff --git a/SystemConfiguration.fproj/SCNetworkInterface.c b/SystemConfiguration.fproj/SCNetworkInterface.c index 3c687ba..ce21227 100644 --- a/SystemConfiguration.fproj/SCNetworkInterface.c +++ b/SystemConfiguration.fproj/SCNetworkInterface.c @@ -171,6 +171,7 @@ static SCNetworkInterfacePrivate __kSCNetworkInterfaceIPv4 = { FALSE, // modemIsV92 NULL, // type NULL, // unit + { NULL, 0, 0 }, // usb { name, vid, pid } kSortUnknown, // sort_order #if !TARGET_OS_IPHONE FALSE, // supportsBond @@ -324,14 +325,33 @@ __SCNetworkInterfaceCopyDescription(CFTypeRef cf) if (interfacePrivate->location != NULL) { CFStringAppendFormat(result, NULL, CFSTR(", location = %@"), interfacePrivate->location); } + if (interfacePrivate->path != NULL) { + CFStringAppendFormat(result, NULL, CFSTR(", path = %@"), interfacePrivate->path); + } if (interfacePrivate->type != NULL) { CFStringAppendFormat(result, NULL, CFSTR(", type = %@"), interfacePrivate->type); } if (interfacePrivate->unit != NULL) { CFStringAppendFormat(result, NULL, CFSTR(", unit = %@"), interfacePrivate->unit); } - if (interfacePrivate->path != NULL) { - CFStringAppendFormat(result, NULL, CFSTR(", path = %@"), interfacePrivate->path); + if ((interfacePrivate->usb.vid != NULL) || (interfacePrivate->usb.pid != NULL)) { + int pid; + int vid; + + if (!isA_CFNumber(interfacePrivate->usb.pid) || + !CFNumberGetValue(interfacePrivate->usb.vid, kCFNumberIntType, &pid)) { + pid = 0; + } + if (!isA_CFNumber(interfacePrivate->usb.vid) || + !CFNumberGetValue(interfacePrivate->usb.vid, kCFNumberIntType, &vid)) { + vid = 0; + } + + CFStringAppendFormat(result, NULL, CFSTR(", USB%s%@ vid/pid = 0x%0x/0x%0x"), + interfacePrivate->usb.name != NULL ? " name = " : "", + interfacePrivate->usb.name != NULL ? interfacePrivate->usb.name : CFSTR(""), + interfacePrivate->usb.vid, + interfacePrivate->usb.pid); } if (interfacePrivate->configurationAction != NULL) { CFStringAppendFormat(result, NULL, CFSTR(", action = %@"), interfacePrivate->configurationAction); @@ -462,6 +482,15 @@ __SCNetworkInterfaceDeallocate(CFTypeRef cf) if (interfacePrivate->unit != NULL) CFRelease(interfacePrivate->unit); + if (interfacePrivate->usb.name != NULL) + CFRelease(interfacePrivate->usb.name); + + if (interfacePrivate->usb.pid != NULL) + CFRelease(interfacePrivate->usb.pid); + + if (interfacePrivate->usb.vid != NULL) + CFRelease(interfacePrivate->usb.vid); + #if !TARGET_OS_IPHONE if (interfacePrivate->bond.interfaces != NULL) CFRelease(interfacePrivate->bond.interfaces); @@ -649,6 +678,9 @@ __SCNetworkInterfaceCreatePrivate(CFAllocatorRef allocator, interfacePrivate->modemIsV92 = FALSE; interfacePrivate->type = NULL; interfacePrivate->unit = NULL; + interfacePrivate->usb.name = NULL; + interfacePrivate->usb.vid = NULL; + interfacePrivate->usb.pid = NULL; interfacePrivate->sort_order = kSortUnknown; #if !TARGET_OS_IPHONE interfacePrivate->supportsBond = FALSE; @@ -1356,6 +1388,36 @@ isBluetoothBuiltin(Boolean *haveController) } +static void +processUSBInterface(SCNetworkInterfacePrivateRef interfacePrivate, + io_registry_entry_t interface, + CFDictionaryRef interface_dict, + io_registry_entry_t controller, + CFDictionaryRef controller_dict, + io_registry_entry_t bus, + CFDictionaryRef bus_dict) +{ + // capture USB info + interfacePrivate->usb.name = IORegistryEntrySearchCFProperty(interface, + kIOServicePlane, + CFSTR(kUSBProductString), + NULL, + kIORegistryIterateRecursively | kIORegistryIterateParents); + interfacePrivate->usb.vid = IORegistryEntrySearchCFProperty(interface, + kIOServicePlane, + CFSTR(kUSBVendorID), + NULL, + kIORegistryIterateRecursively | kIORegistryIterateParents); + interfacePrivate->usb.pid = IORegistryEntrySearchCFProperty(interface, + kIOServicePlane, + CFSTR(kUSBProductID), + NULL, + kIORegistryIterateRecursively | kIORegistryIterateParents); + + return; +} + + #pragma mark - #pragma mark Interface enumeration @@ -1409,6 +1471,14 @@ processNetworkInterface(SCNetworkInterfacePrivateRef interfacePrivate, interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet; interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet; interfacePrivate->sort_order = kSortBluetoothPAN; + } else if (IOObjectConformsTo(controller, "AppleUSBEthernetHost")) { + interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet; + interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet; + interfacePrivate->sort_order = kSortTethered; + } else if (IOObjectConformsTo(controller, "AppleUSBCDCECMData")) { + interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet; + interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet; + interfacePrivate->sort_order = kSortWWANEthernet; } else { str = IODictionaryCopyCFStringValue(bus_dict, CFSTR("name")); if ((str != NULL) && CFEqual(str, CFSTR("radio"))) { @@ -1429,13 +1499,6 @@ processNetworkInterface(SCNetworkInterfacePrivateRef interfacePrivate, if (str != NULL) CFRelease(str); } - // check if WWAN Ethernet - if (IOObjectConformsTo(controller, "AppleUSBEthernetHost")) { - interfacePrivate->sort_order = kSortTethered; - } else if (IOObjectConformsTo(controller, "AppleUSBCDCECMData")) { - interfacePrivate->sort_order = kSortWWANEthernet; - } - // built-in val = isA_CFBoolean(CFDictionaryGetValue(interface_dict, CFSTR(kIOBuiltin))); if (val == NULL) { @@ -1509,19 +1572,24 @@ processNetworkInterface(SCNetworkInterfacePrivateRef interfacePrivate, } } else if (CFEqual(provider, CFSTR("IOUSBDevice")) || CFEqual(provider, CFSTR("IOUSBInterface"))) { + + processUSBInterface(interfacePrivate, + interface, + interface_dict, + controller, + controller_dict, + bus, + bus_dict); + // check if a "Product Name" has been provided val = IORegistryEntrySearchCFProperty(interface, kIOServicePlane, CFSTR(kIOPropertyProductNameKey), NULL, kIORegistryIterateRecursively | kIORegistryIterateParents); - if (val == NULL) { - // check if a "USB Product Name" has been provided - val = IORegistryEntrySearchCFProperty(interface, - kIOServicePlane, - CFSTR(kUSBProductString), - NULL, - kIORegistryIterateRecursively | kIORegistryIterateParents); + if ((val == NULL) && (interfacePrivate->usb.name != NULL)) { + // else, use "USB Product Name" if available + val = CFRetain(interfacePrivate->usb.name); } if (val != NULL) { CFStringRef productName; @@ -5245,6 +5313,47 @@ SCNetworkInterfaceSetPassword(SCNetworkInterfaceRef interface, #pragma mark SCNetworkInterface [InterfaceNamer] SPIs +CFDictionaryRef +_SCNetworkInterfaceCopyInterfaceInfo(SCNetworkInterfaceRef interface) +{ + CFMutableDictionaryRef info; + SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; + CFStringRef name; + + info = CFDictionaryCreateMutable(NULL, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + // add non-localized interface name + name = __SCNetworkInterfaceGetNonLocalizedDisplayName(interface); + if (name != NULL) { + CFDictionaryAddValue(info, kSCPropUserDefinedName, name); + } + + // add USB info + if ((interfacePrivate->usb.vid != NULL) || (interfacePrivate->usb.pid != NULL)) { + if (interfacePrivate->usb.name != NULL) { + CFDictionaryAddValue(info, CFSTR(kUSBProductString), interfacePrivate->usb.name); + } + if (interfacePrivate->usb.vid != NULL) { + CFDictionaryAddValue(info, CFSTR(kUSBVendorID), interfacePrivate->usb.vid); + } + if (interfacePrivate->usb.pid != NULL) { + CFDictionaryAddValue(info, CFSTR(kUSBProductID), interfacePrivate->usb.pid); + } + } + + if (CFDictionaryGetCount(info) == 0) { + // do not return an empty dictionary + CFRelease(info); + info = NULL; + } + + return info; +} + + SCNetworkInterfaceRef _SCNetworkInterfaceCreateWithIONetworkInterfaceObject(io_object_t if_obj) { @@ -5523,6 +5632,15 @@ __SCNetworkInterfaceCreateCopy(CFAllocatorRef allocator, if (oldPrivate->unit != NULL) { newPrivate->unit = CFRetain(oldPrivate->unit); } + if (oldPrivate->usb.name != NULL) { + newPrivate->usb.name = CFRetain(oldPrivate->usb.name); + } + if (oldPrivate->usb.vid != NULL) { + newPrivate->usb.vid = CFRetain(oldPrivate->usb.vid); + } + if (oldPrivate->usb.pid != NULL) { + newPrivate->usb.pid = CFRetain(oldPrivate->usb.pid); + } newPrivate->sort_order = oldPrivate->sort_order; #if !TARGET_OS_IPHONE newPrivate->supportsBond = oldPrivate->supportsBond; diff --git a/SystemConfiguration.fproj/SCNetworkReachability.c b/SystemConfiguration.fproj/SCNetworkReachability.c index 658d9e4..9d8c41e 100644 --- a/SystemConfiguration.fproj/SCNetworkReachability.c +++ b/SystemConfiguration.fproj/SCNetworkReachability.c @@ -1910,39 +1910,29 @@ enqueueAsyncDNSQuery(SCNetworkReachabilityRef target, mach_port_t mp) NULL); #if !TARGET_OS_IPHONE if (targetPrivate->dispatchQueue != NULL) { - dispatch_queue_attr_t attr; - long res; - - attr = dispatch_queue_attr_create(); - res = dispatch_queue_attr_set_finalizer(attr, - ^(dispatch_queue_t dq) { - SCNetworkReachabilityRef target; - - target = (SCNetworkReachabilityRef)dispatch_get_context(dq); - CFRelease(target); - }); - if (res != 0) { - SCLog(TRUE, LOG_ERR, CFSTR("SCNetworkReachability dispatch_queue_attr_set_finalizer() failed")); - dispatch_release(attr); - goto fail; - } - targetPrivate->asyncDNSQueue = dispatch_queue_create("com.apple.SCNetworkReachabilty.async_DNS_query", attr); - dispatch_release(attr); + targetPrivate->asyncDNSQueue = dispatch_queue_create("com.apple.SCNetworkReachabilty.async_DNS_query", NULL); if (targetPrivate->asyncDNSQueue == NULL) { SCLog(TRUE, LOG_ERR, CFSTR("SCNetworkReachability dispatch_queue_create() failed")); goto fail; } CFRetain(target); // Note: will be released when the dispatch queue is released dispatch_set_context(targetPrivate->asyncDNSQueue, (void *)target); - targetPrivate->asyncDNSSource = dispatch_source_mig_create(mp, - sizeof(mach_msg_header_t), - NULL, - targetPrivate->asyncDNSQueue, - SCNetworkReachabilityNotifyMIGCallback); + dispatch_set_finalizer_f(targetPrivate->asyncDNSQueue, (dispatch_function_t)CFRelease); + + targetPrivate->asyncDNSSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, + mp, + 0, + targetPrivate->asyncDNSQueue); if (targetPrivate->asyncDNSSource == NULL) { - SCLog(TRUE, LOG_ERR, CFSTR("SCNetworkReachability dispatch_source_mig_create() failed")); + SCLog(TRUE, LOG_ERR, CFSTR("SCNetworkReachability dispatch_source_create() failed")); goto fail; } + dispatch_source_set_event_handler(targetPrivate->asyncDNSSource, ^{ + dispatch_mig_server(targetPrivate->asyncDNSSource, + sizeof(mach_msg_header_t), + SCNetworkReachabilityNotifyMIGCallback); + }); + dispatch_resume(targetPrivate->asyncDNSSource); } else #endif // !TARGET_OS_IPHONE if (targetPrivate->rls != NULL) { @@ -1966,7 +1956,7 @@ enqueueAsyncDNSQuery(SCNetworkReachabilityRef target, mach_port_t mp) fail : if (targetPrivate->asyncDNSSource != NULL) { - dispatch_cancel(targetPrivate->asyncDNSSource); + dispatch_source_cancel(targetPrivate->asyncDNSSource); dispatch_release(targetPrivate->asyncDNSSource); targetPrivate->asyncDNSSource = NULL; } @@ -1993,7 +1983,15 @@ dequeueAsyncDNSQuery(SCNetworkReachabilityRef target) #if !TARGET_OS_IPHONE if (targetPrivate->asyncDNSSource != NULL) { - dispatch_cancel(targetPrivate->asyncDNSSource); + dispatch_source_cancel(targetPrivate->asyncDNSSource); + if (targetPrivate->asyncDNSQueue != dispatch_get_current_queue()) { + // ensure the cancellation has completed + pthread_mutex_unlock(&targetPrivate->lock); + dispatch_sync(targetPrivate->asyncDNSQueue, ^{}); + pthread_mutex_lock(&targetPrivate->lock); + } + } + if (targetPrivate->asyncDNSSource != NULL) { dispatch_release(targetPrivate->asyncDNSSource); targetPrivate->asyncDNSSource = NULL; } @@ -3725,27 +3723,7 @@ __SCNetworkReachabilityScheduleWithRunLoop(SCNetworkReachabilityRef target, __SCNetworkReachabilityReachabilitySetNotifications(hn_store); #if !TARGET_OS_IPHONE - dispatch_queue_attr_t attr; - long res; - - attr = dispatch_queue_attr_create(); - res = dispatch_queue_attr_set_finalizer(attr, - ^(dispatch_queue_t dq) { - SCDynamicStoreRef hn_store; - - hn_store = (SCDynamicStoreRef)dispatch_get_context(dq); - CFRelease(hn_store); - }); - if (res != 0) { - SCLog(TRUE, LOG_ERR, CFSTR("__SCNetworkReachabilityScheduleWithRunLoop dispatch_queue_attr_set_finalizer() failed")); - dispatch_release(attr); - CFRelease(hn_store); - hn_store = NULL; - _SCErrorSet(kSCStatusFailed); - goto done; - } - hn_dispatchQueue = dispatch_queue_create("com.apple.SCNetworkReachabilty.network_changes", attr); - dispatch_release(attr); + hn_dispatchQueue = dispatch_queue_create("com.apple.SCNetworkReachabilty.network_changes", NULL); if (hn_dispatchQueue == NULL) { SCLog(TRUE, LOG_ERR, CFSTR("__SCNetworkReachabilityScheduleWithRunLoop dispatch_queue_create() failed")); _SCErrorSet(kSCStatusFailed); @@ -3755,6 +3733,7 @@ __SCNetworkReachabilityScheduleWithRunLoop(SCNetworkReachabilityRef target, } CFRetain(hn_store); // Note: will be released when the dispatch queue is released dispatch_set_context(hn_dispatchQueue, (void *)hn_store); + dispatch_set_finalizer_f(hn_dispatchQueue, (dispatch_function_t)CFRelease); ok = SCDynamicStoreSetDispatchQueue(hn_store, hn_dispatchQueue); if (!ok) { diff --git a/scutil.tproj/notifications.c b/scutil.tproj/notifications.c index 8bf91c2..ad195e6 100644 --- a/scutil.tproj/notifications.c +++ b/scutil.tproj/notifications.c @@ -249,12 +249,23 @@ _watcher(void *arg) return NULL; } - notifyRls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0); - if (!notifyRls) { - SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError())); - return NULL; +#if !TARGET_OS_IPHONE + if (doDispatch) { + if (!SCDynamicStoreSetDispatchQueue(store, dispatch_get_current_queue())) { + SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError())); + return NULL; + } + notifyRls = (CFRunLoopSourceRef)kCFNull; + } else +#endif // !TARGET_OS_IPHONE + { + notifyRls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0); + if (!notifyRls) { + SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError())); + return NULL; + } + CFRunLoopAddSource(notifyRl, notifyRls, kCFRunLoopDefaultMode); } - CFRunLoopAddSource(notifyRl, notifyRls, kCFRunLoopDefaultMode); CFRunLoopRun(); return NULL; @@ -479,8 +490,18 @@ void do_notify_cancel(int argc, char **argv) { if (notifyRls) { - CFRunLoopSourceInvalidate(notifyRls); - CFRelease(notifyRls); +#if !TARGET_OS_IPHONE + if (doDispatch) { + if (!SCDynamicStoreSetDispatchQueue(store, NULL)) { + SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError())); + return; + } + } else +#endif // !TARGET_OS_IPHONE + { + CFRunLoopSourceInvalidate(notifyRls); + CFRelease(notifyRls); + } notifyRls = NULL; } diff --git a/scutil.tproj/scutil.c b/scutil.tproj/scutil.c index 4e7f3a1..08703da 100644 --- a/scutil.tproj/scutil.c +++ b/scutil.tproj/scutil.c @@ -73,6 +73,7 @@ __private_extern__ AuthorizationRef authorization = NULL; __private_extern__ InputRef currentInput = NULL; +__private_extern__ Boolean doDispatch = FALSE; __private_extern__ int nesting = 0; __private_extern__ CFRunLoopRef notifyRl = NULL; __private_extern__ CFRunLoopSourceRef notifyRls = NULL; @@ -84,11 +85,13 @@ __private_extern__ CFMutableArrayRef watchedPatterns = NULL; static const struct option longopts[] = { // { "debug", no_argument, NULL, 'd' }, +// { "dispatch", no_argument, NULL, 'D' }, // { "verbose", no_argument, NULL, 'v' }, // { "SPI", no_argument, NULL, 'p' }, // { "check-reachability", required_argument, NULL, 'r' }, // { "timeout", required_argument, NULL, 't' }, // { "wait-key", required_argument, NULL, 'w' }, +// { "watch-reachability", no_argument, NULL, 'W' }, { "dns", no_argument, NULL, 0 }, { "get", required_argument, NULL, 0 }, { "help", no_argument, NULL, '?' }, @@ -312,12 +315,15 @@ main(int argc, char * const argv[]) /* process any arguments */ - while ((opt = getopt_long(argc, argv, "dvprt:w:W", longopts, &opti)) != -1) + while ((opt = getopt_long(argc, argv, "dDvprt:w:W", longopts, &opti)) != -1) switch(opt) { case 'd': _sc_debug = TRUE; _sc_log = FALSE; /* enable framework logging */ break; + case 'D': + doDispatch = TRUE; + break; case 'v': _sc_verbose = TRUE; _sc_log = FALSE; /* enable framework logging */ diff --git a/scutil.tproj/scutil.h b/scutil.tproj/scutil.h index 16699f1..75bd7f4 100644 --- a/scutil.tproj/scutil.h +++ b/scutil.tproj/scutil.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2005, 2009 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -51,6 +51,7 @@ typedef struct { extern AuthorizationRef authorization; extern InputRef currentInput; +extern Boolean doDispatch; extern int nesting; extern CFRunLoopRef notifyRl; extern CFRunLoopSourceRef notifyRls; diff --git a/scutil.tproj/tests.c b/scutil.tproj/tests.c index d9d316a..cc9f95f 100644 --- a/scutil.tproj/tests.c +++ b/scutil.tproj/tests.c @@ -378,14 +378,24 @@ do_watchReachability(int argc, char **argv) exit(1); } - if (!SCNetworkReachabilityScheduleWithRunLoop(target_async, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)) { - printf("SCNetworkReachabilityScheduleWithRunLoop() failed: %s\n", SCErrorString(SCError())); - exit(1); +#if !TARGET_OS_IPHONE + if (doDispatch) { + if (!SCNetworkReachabilitySetDispatchQueue(target_async, dispatch_get_current_queue())) { + printf("SCNetworkReachabilitySetDispatchQueue() failed: %s\n", SCErrorString(SCError())); + exit(1); + } + } else +#endif // !TARGET_OS_IPHONE + { + if (!SCNetworkReachabilityScheduleWithRunLoop(target_async, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)) { + printf("SCNetworkReachabilityScheduleWithRunLoop() failed: %s\n", SCErrorString(SCError())); + exit(1); + } } // Note: now that we are scheduled on a run loop we can call SCNetworkReachabilityGetFlags() // to get the current status. For "names", a DNS lookup has already been initiated. - SCPrint(TRUE, stdout, CFSTR(" 2: on runloop\n")); + SCPrint(TRUE, stdout, CFSTR(" 2: on %s\n"), doDispatch ? "dispatch queue" : "runloop"); SCPrint(TRUE, stdout, CFSTR(" %@\n"), target_async); _printReachability(target_async); SCPrint(TRUE, stdout, CFSTR("\n")); -- 2.45.2