<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
- <string>1.10.1</string>
+ <string>1.10.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>1.10.1</string>
+ <string>1.10.2</string>
<key>Builtin</key>
<true/>
<key>Requires</key>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
- <string>1.10.1</string>
+ <string>1.10.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>1.10.1</string>
+ <string>1.10.2</string>
<key>Requires</key>
<array>
<string>com.apple.SystemConfiguration.IPConfiguration</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
- <string>1.10.1</string>
+ <string>1.10.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>1.10.1</string>
+ <string>1.10.2</string>
</dict>
</plist>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <mach/mach.h>
#include <net/ethernet.h>
+#include <net/if.h>
#include <net/if_types.h>
#include <CoreFoundation/CoreFoundation.h>
#include <SystemConfiguration/SCValidation.h>
#include <IOKit/IOKitLib.h>
+#include <IOKit/IOKitLibPrivate.h>
#include <IOKit/IOBSD.h>
#include <IOKit/IOMessage.h>
#include <IOKit/network/IONetworkController.h>
#include <IOKit/network/IONetworkInterface.h>
-
-#ifndef kIOBuiltin
-#define kIOBuiltin "IOBuiltin"
-#endif
+#include <IOKit/usb/USB.h>
#define kIONetworkStackUserCommand "IONetworkStackUserCommand"
#define kRegisterInterface 1
+#define kSCNetworkInterfaceInfo "SCNetworkInterfaceInfo"
#define kSCNetworkInterfaceType "SCNetworkInterfaceType"
#define kSCNetworkInterfaceActive "Active"
&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);
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
}
} else {
CFDictionaryRef dbdict;
+ boolean_t is_builtin;
kern_return_t kr;
dbdict = lookupInterfaceByAddress(S_dblist, interface, NULL);
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);
}
}
}
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);
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);
}
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);
+ }
+ }
}
}
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;
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
- <string>1.10.1</string>
+ <string>1.10.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>1.10.1</string>
+ <string>1.10.2</string>
<key>Requires</key>
<array>
<string>com.apple.SystemConfiguration.InterfaceNamer</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
- <string>1.10.1</string>
+ <string>1.10.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>1.10.1</string>
+ <string>1.10.2</string>
<key>Requires</key>
<array>
<string>com.apple.SystemConfiguration.ATconfig</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
- <string>1.10.1</string>
+ <string>1.10.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>1.10.1</string>
+ <string>1.10.2</string>
<key>Requires</key>
<array>
<string>com.apple.SystemConfiguration.InterfaceNamer</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
- <string>1.10</string>
+ <string>1.10.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>1.10</string>
+ <string>1.10.2</string>
<key>Enabled</key>
<true/>
<key>Verbose</key>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
- <string>1.10.1</string>
+ <string>1.10.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>1.10.1</string>
+ <string>1.10.2</string>
<key>Enabled</key>
<false/>
<key>Verbose</key>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
- <string>1.10.1</string>
+ <string>1.10.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>1.10.1</string>
+ <string>1.10.2</string>
<key>Builtin</key>
<true/>
</dict>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
- <string>1.10.1</string>
+ <string>1.10.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>1.10.1</string>
+ <string>1.10.2</string>
<key>Builtin</key>
<true/>
<key>Requires</key>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
- <string>1.10.1</string>
+ <string>1.10.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>1.10.1</string>
+ <string>1.10.2</string>
<key>CFPlugInDynamicRegistration</key>
<string>NO</string>
<key>CFPlugInFactories</key>
<key>CFBundleExecutable</key>
<string>SystemConfiguration</string>
<key>CFBundleGetInfoString</key>
- <string>1.10</string>
+ <string>1.10.2</string>
<key>CFBundleIdentifier</key>
<string>com.apple.SystemConfiguration</string>
<key>CFBundleInfoDictionaryVersion</key>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
- <string>1.10</string>
+ <string>1.10.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>1.10</string>
+ <string>1.10.2</string>
</dict>
</plist>
<key>CFBundleExecutable</key>
<string>SystemConfiguration</string>
<key>CFBundleGetInfoString</key>
- <string>1.10.1</string>
+ <string>1.10.2</string>
<key>CFBundleIdentifier</key>
<string>com.apple.SystemConfiguration</string>
<key>CFBundleInfoDictionaryVersion</key>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
- <string>1.10.1</string>
+ <string>1.10.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>1.10.1</string>
+ <string>1.10.2</string>
</dict>
</plist>
}
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);
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);
}
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;
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;
}
Boolean modemIsV92;
CFNumberRef type;
CFNumberRef unit;
+ struct {
+ CFStringRef name;
+ CFNumberRef vid;
+ CFNumberRef pid;
+ } usb;
// misc
int sort_order; // sort order for this interface
#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.
#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
{
fail :
if (connectionPrivate->callbackSource != NULL) {
- dispatch_cancel(connectionPrivate->callbackSource);
+ dispatch_source_cancel(connectionPrivate->callbackSource);
dispatch_release(connectionPrivate->callbackSource);
connectionPrivate->callbackSource = NULL;
}
#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);
FALSE, // modemIsV92
NULL, // type
NULL, // unit
+ { NULL, 0, 0 }, // usb { name, vid, pid }
kSortUnknown, // sort_order
#if !TARGET_OS_IPHONE
FALSE, // supportsBond
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);
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);
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;
}
+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
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"))) {
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) {
}
} 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;
#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)
{
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;
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) {
fail :
if (targetPrivate->asyncDNSSource != NULL) {
- dispatch_cancel(targetPrivate->asyncDNSSource);
+ dispatch_source_cancel(targetPrivate->asyncDNSSource);
dispatch_release(targetPrivate->asyncDNSSource);
targetPrivate->asyncDNSSource = NULL;
}
#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;
}
__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);
}
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) {
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;
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;
}
__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;
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, '?' },
/* 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 */
/*
- * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2005, 2009 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
extern AuthorizationRef authorization;
extern InputRef currentInput;
+extern Boolean doDispatch;
extern int nesting;
extern CFRunLoopRef notifyRl;
extern CFRunLoopSourceRef notifyRls;
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"));