+ // Update the BSD Name
+ if ((newBSDName == NULL) ||
+ (!__SCNetworkInterfaceUpdateBSDName(interface, oldBSDName, newBSDName))) {
+ SC_log(LOG_INFO, "BSD name update failed");
+ }
+
+ // Update the path
+ if (!__SCNetworkInterfaceUpdateIOPath(interface)) {
+ SC_log(LOG_INFO, "IOPath update failed");
+ }
+
+ CFRetain(unit);
+ if (interfacePrivate->unit != NULL) {
+ CFRelease(interfacePrivate->unit);
+ }
+ interfacePrivate->unit = unit;
+
+
+ if (newBSDName != NULL) {
+ CFRelease(newBSDName);
+ }
+ return;
+}
+
+
+__private_extern__
+CFDictionaryRef
+__SCNetworkInterfaceCopyStorageEntity(SCNetworkInterfaceRef interface)
+{
+ CFMutableDictionaryRef interface_entity = NULL;
+ SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
+ CFBooleanRef active = NULL;
+ CFStringRef bsdName = NULL;
+ CFBooleanRef builtin = NULL;
+ CFStringRef interfaceNamePrefix = NULL;
+ CFNumberRef interfaceType = NULL;
+ CFNumberRef interfaceUnit = NULL;
+ CFDataRef macAddress = NULL;
+ CFStringRef pathMatch = NULL;
+ CFDictionaryRef info = NULL;
+ CFStringRef type = NULL;
+
+ if (interfacePrivate->active) {
+ active = kCFBooleanTrue;
+ }
+
+ bsdName = SCNetworkInterfaceGetBSDName(interface);
+ if (!isA_CFString(bsdName)) {
+ goto done;
+ }
+
+ builtin = interfacePrivate->builtin ? kCFBooleanTrue : kCFBooleanFalse;
+ interfaceNamePrefix = _SCNetworkInterfaceGetIOInterfaceNamePrefix(interface);
+ if (!isA_CFString(interfaceNamePrefix)) {
+ goto done;
+ }
+
+ interfaceType = _SCNetworkInterfaceGetIOInterfaceType(interface);
+ if (!isA_CFNumber(interfaceType)) {
+ goto done;
+ }
+
+ interfaceUnit = _SCNetworkInterfaceGetIOInterfaceUnit(interface);
+ if (!isA_CFNumber(interfaceUnit)) {
+ goto done;
+ }
+
+ macAddress = _SCNetworkInterfaceGetHardwareAddress(interface);
+ if (!isA_CFData(macAddress)) {
+ goto done;
+ }
+
+ pathMatch = _SCNetworkInterfaceGetIOPath(interface);
+ if (!isA_CFString(pathMatch)) {
+ goto done;
+ }
+
+ info = _SCNetworkInterfaceCopyInterfaceInfo(interface);
+ if (!isA_CFDictionary(info)) {
+ goto done;
+ }
+
+ type = SCNetworkInterfaceGetInterfaceType(interface);
+ if (!isA_CFString(type)) {
+ goto done;
+ }
+
+ interface_entity = CFDictionaryCreateMutable(NULL, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+
+ if (isA_CFBoolean(active) != NULL) {
+ CFDictionaryAddValue(interface_entity, CFSTR(kSCNetworkInterfaceActive), active);
+ }
+
+ CFDictionaryAddValue(interface_entity, CFSTR(kSCNetworkInterfaceBSDName), bsdName);
+ CFDictionaryAddValue(interface_entity, CFSTR(kSCNetworkInterfaceIOBuiltin), builtin);
+ CFDictionaryAddValue(interface_entity, CFSTR(kSCNetworkInterfaceIOInterfaceNamePrefix), interfaceNamePrefix);
+ CFDictionaryAddValue(interface_entity, CFSTR(kSCNetworkInterfaceIOInterfaceType), interfaceType);
+ CFDictionaryAddValue(interface_entity, CFSTR(kSCNetworkInterfaceIOInterfaceUnit), interfaceUnit);
+ CFDictionaryAddValue(interface_entity, CFSTR(kSCNetworkInterfaceIOMACAddress), macAddress);
+ CFDictionaryAddValue(interface_entity, CFSTR(kSCNetworkInterfaceIOPathMatch), pathMatch);
+ CFDictionaryAddValue(interface_entity, CFSTR(kSCNetworkInterfaceInfo), info);
+ CFDictionaryAddValue(interface_entity, CFSTR(kSCNetworkInterfaceType), type);
+done:
+ if (info != NULL) {
+ CFRelease(info);
+ }
+ return interface_entity;
+}
+
+
+static void
+__SCNetworkInterfaceSetService(SCNetworkInterfaceRef interface,
+ SCNetworkServiceRef service)
+{
+ SCNetworkInterfacePrivateRef interfacePrivate;
+ SCNetworkServicePrivateRef servicePrivate;
+
+ interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
+ if (interfacePrivate->prefs != NULL) {
+ CFRelease(interfacePrivate->prefs);
+ interfacePrivate->prefs = NULL;
+ }
+ if (interfacePrivate->serviceID != NULL) {
+ CFRelease(interfacePrivate->serviceID);
+ interfacePrivate->serviceID = NULL;
+ }
+
+ servicePrivate = (SCNetworkServicePrivateRef)service;
+ if (servicePrivate->prefs != NULL) {
+ interfacePrivate->prefs = CFRetain(servicePrivate->prefs);
+ }
+ if (servicePrivate->serviceID != NULL) {
+ interfacePrivate->serviceID = CFRetain(servicePrivate->serviceID);
+ }
+
+ return;
+}
+
+
+__private_extern__
+Boolean
+__SCNetworkInterfaceMatchesName(CFStringRef name, CFStringRef key)
+{
+ Boolean match;
+ CFStringRef str;
+
+ if (bundle == NULL) {
+ SC_log(LOG_NOTICE, "no bundle information to compare interface names");
+ return FALSE;
+ }
+
+ if (!isA_CFString(name)) {
+ // if no interface "name"
+ return FALSE;
+ }
+
+ // check non-localized name for a match
+ str = copy_interface_string(bundle, key, FALSE);
+ if (str != NULL) {
+ match = CFEqual(name, str);
+ CFRelease(str);
+ if (match) {
+ return TRUE;
+ }
+ }
+
+ // check localized name for a match
+ str = copy_interface_string(bundle, key, TRUE);
+ if (str != NULL) {
+ match = CFEqual(name, str);
+ CFRelease(str);
+ if (match) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+#define kInterfaceTypeEthernetValue 6
+#define kInterfaceTypeFirewireValue 144
+
+
+static SCNetworkInterfaceRef
+__SCNetworkInterfaceCreateWithStorageEntity(CFAllocatorRef allocator,
+ CFDictionaryRef interface_entity)
+{
+#pragma unused(allocator)
+ SCNetworkInterfacePrivateRef interfacePrivate = NULL;
+ CFBooleanRef active = NULL;
+ CFStringRef bsdName = NULL;
+ CFBooleanRef ioBuiltin = NULL;
+ CFStringRef ioInterfaceNamePrefix = NULL;
+ CFNumberRef ioInterfaceType = NULL;
+ int ioInterfaceTypeNum;
+ CFNumberRef ioInterfaceUnit = NULL;
+ CFDataRef ioMACAddress = NULL;
+ CFStringRef ioPathMatch = NULL;
+ CFDictionaryRef SCNetworkInterfaceInfo = NULL;
+ CFStringRef userDefinedName = NULL;
+ CFStringRef usbProductName = NULL;
+ CFNumberRef idProduct = NULL;
+ CFNumberRef idVendor = NULL;
+ CFStringRef type = NULL;
+
+ /* initialize runtime */
+ pthread_once(&initialized, __SCNetworkInterfaceInitialize);
+
+ if (isA_CFDictionary(interface_entity) == NULL) {
+ SC_log(LOG_INFO, "No interface entity");
+ goto done;
+ }
+ active = CFDictionaryGetValue(interface_entity, CFSTR(kSCNetworkInterfaceActive));
+ if (isA_CFBoolean(active) == NULL) {
+ active = kCFBooleanFalse;
+ }
+ bsdName = CFDictionaryGetValue(interface_entity, CFSTR(kSCNetworkInterfaceBSDName));
+ if (isA_CFString(bsdName) == NULL) {
+ SC_log(LOG_INFO, "No BSD name");
+ goto done;
+ }
+ ioBuiltin = CFDictionaryGetValue(interface_entity, CFSTR(kSCNetworkInterfaceIOBuiltin));
+ if (isA_CFBoolean(ioBuiltin) == NULL) {
+ SC_log(LOG_INFO, "No IOBuiltin property");
+ goto done;
+ }
+ ioInterfaceNamePrefix = CFDictionaryGetValue(interface_entity, CFSTR(kSCNetworkInterfaceIOInterfaceNamePrefix));
+ if (isA_CFString(ioInterfaceNamePrefix) == NULL) {
+ ioInterfaceNamePrefix = _SCNetworkInterfaceCopyPrefixFromBSDName(bsdName);
+ if (ioInterfaceNamePrefix == NULL) {
+ SC_log(LOG_INFO, "No BSD interface name prefix");
+ goto done;
+ }
+ } else {
+ CFRetain(ioInterfaceNamePrefix);
+ }
+ ioInterfaceType = CFDictionaryGetValue(interface_entity, CFSTR(kSCNetworkInterfaceIOInterfaceType));
+ if (isA_CFNumber(ioInterfaceType) == NULL) {
+ SC_log(LOG_INFO, "No IOInterfaceType");
+ goto done;
+ }
+ if (!CFNumberGetValue(ioInterfaceType, kCFNumberIntType, &ioInterfaceTypeNum)) {
+ SC_log(LOG_NOTICE, "Count not extract value from ioInterfaceType");
+ }
+ ioInterfaceUnit = CFDictionaryGetValue(interface_entity, CFSTR(kSCNetworkInterfaceIOInterfaceUnit));
+ if (isA_CFNumber(ioInterfaceUnit) == NULL) {
+ SC_log(LOG_INFO, "No IOInterfaceUnit");
+
+ goto done;
+ }
+ ioMACAddress = CFDictionaryGetValue(interface_entity, CFSTR(kSCNetworkInterfaceIOMACAddress));
+ if (isA_CFData(ioMACAddress) == NULL) {
+ SC_log(LOG_INFO, "No IOMACAddress");
+ goto done;
+ }
+ ioPathMatch = CFDictionaryGetValue(interface_entity, CFSTR(kSCNetworkInterfaceIOPathMatch));
+ if (isA_CFString(ioPathMatch) == NULL) {
+ SC_log(LOG_INFO, "No IOPathMatch");
+ goto done;
+ } else {
+ // Check if Path contains the BSD Name in the end
+ }
+ SCNetworkInterfaceInfo = CFDictionaryGetValue(interface_entity, CFSTR(kSCNetworkInterfaceInfo));
+ if (isA_CFDictionary(SCNetworkInterfaceInfo) == NULL) {
+ SC_log(LOG_INFO, "No SCNetworkInterfaceInfo");
+ goto done;
+ }
+ userDefinedName = CFDictionaryGetValue(SCNetworkInterfaceInfo, kSCPropUserDefinedName);
+#if !TARGET_OS_SIMULATOR
+ usbProductName = CFDictionaryGetValue(SCNetworkInterfaceInfo, CFSTR(kUSBProductString));
+ idProduct = CFDictionaryGetValue(SCNetworkInterfaceInfo, CFSTR(kUSBProductID));
+ idVendor = CFDictionaryGetValue(SCNetworkInterfaceInfo, CFSTR(kUSBVendorID));
+#endif // !TARGET_OS_SIMULATOR
+
+ type = CFDictionaryGetValue(interface_entity, CFSTR(kSCNetworkInterfaceType));
+ if (isA_CFString(type) == NULL) {
+ SC_log(LOG_INFO, "No SCNetworkInterfaceType");
+ goto done;
+ }
+
+ interfacePrivate = __SCNetworkInterfaceCreatePrivate(NULL, NULL, NULL, NULL);
+ interfacePrivate->active = CFBooleanGetValue(active);
+ interfacePrivate->entity_device = CFRetain(bsdName);
+ interfacePrivate->builtin = CFBooleanGetValue(ioBuiltin);
+ interfacePrivate->prefix = CFRetain(ioInterfaceNamePrefix);
+ interfacePrivate->type = CFRetain(ioInterfaceType);
+ interfacePrivate->unit = CFRetain(ioInterfaceUnit);
+ interfacePrivate->address = CFRetain(ioMACAddress);
+ interfacePrivate->path = CFRetain(ioPathMatch);
+ interfacePrivate->name = ((userDefinedName != NULL) ? CFRetain(userDefinedName) : NULL);
+ interfacePrivate->localized_name = ((userDefinedName != NULL) ? CFRetain(userDefinedName) : NULL);
+ interfacePrivate->usb.name = ((usbProductName != NULL) ? CFRetain(usbProductName) : NULL);
+ interfacePrivate->usb.pid = ((idProduct != NULL) ? CFRetain(idProduct) : NULL);
+ interfacePrivate->usb.vid = ((idVendor != NULL) ? CFRetain(idVendor) : NULL);
+
+ // Handling interface types to be seen in NetworkInterfaces.plist
+ CFIndex interfaceIndex;
+
+ interfaceIndex = findConfiguration(type);
+ if (interfaceIndex != kCFNotFound) {
+ interfacePrivate->interface_type = *configurations[interfaceIndex].interface_type;
+ } else {
+ interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet;
+ }
+
+ // Extracting entity type from value of interface type
+ if (ioInterfaceTypeNum == kInterfaceTypeEthernetValue) {
+ interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet; // kSCNetworkInterfaceTypeEthernet;
+ } else if (ioInterfaceTypeNum == kInterfaceTypeFirewireValue) {
+ interfacePrivate->entity_type = kSCValNetInterfaceTypeFireWire;
+ }
+done:
+ if (ioInterfaceNamePrefix != NULL) {
+ CFRelease(ioInterfaceNamePrefix);
+ }
+
+ return (SCNetworkInterfaceRef)interfacePrivate;
+}
+
+
+__private_extern__
+void
+_SCNetworkInterfaceCacheOpen(void)
+{
+ if (!__SCNetworkInterfaceCacheIsOpen()) {
+ S_interface_cache = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ SC_log(LOG_DEBUG, "SCNetworkInterface cache (%p): open", S_interface_cache);
+ }
+}
+
+
+__private_extern__
+void
+_SCNetworkInterfaceCacheClose(void)
+{
+ if (__SCNetworkInterfaceCacheIsOpen()) {
+ SC_log(LOG_DEBUG, "SCNetworkInterface cache (%p): close", S_interface_cache);
+ CFRelease(S_interface_cache);
+ S_interface_cache = NULL;
+ }
+}
+
+
+static void
+__SCNetworkInterfaceCacheAdd(CFStringRef bsdName, CFArrayRef matchingInterfaces)
+{
+ if (__SCNetworkInterfaceCacheIsOpen() &&
+ bsdName != NULL &&
+ matchingInterfaces != NULL) {
+ SC_log(LOG_DEBUG, "SCNetworkInterface cache (%p): add %@", S_interface_cache, bsdName);
+ CFDictionaryAddValue(S_interface_cache, bsdName, matchingInterfaces);
+ }
+}
+
+
+static inline Boolean
+__SCNetworkInterfaceCacheIsOpen(void)
+{
+ return (S_interface_cache != NULL);
+}
+
+
+static CFArrayRef
+__SCNetworkInterfaceCacheCopy(CFStringRef bsdName)
+{
+ if (__SCNetworkInterfaceCacheIsOpen() &&
+ bsdName != NULL) {
+ CFArrayRef matchingInterfaces = CFDictionaryGetValue(S_interface_cache, bsdName);
+ if (matchingInterfaces) {
+ CFRetain(matchingInterfaces);
+ SC_log(LOG_DEBUG, "SCNetworkInterface cache (%p): copy w/ match for %@", S_interface_cache, bsdName);
+ } else {
+ SC_log(LOG_DEBUG, "SCNetworkInterface cache (%p): copy w/ no match for %@", S_interface_cache, bsdName);
+ }
+
+ return matchingInterfaces;
+ }
+
+ return NULL;
+}
+
+
+SCNetworkInterfaceRef
+_SCNetworkInterfaceCreateWithEntity(CFAllocatorRef allocator,
+ CFDictionaryRef interface_entity,
+ SCNetworkServiceRef service)
+{
+#pragma unused(allocator)
+ SCNetworkInterfacePrivateRef interfacePrivate = NULL;
+ CFStringRef ifDevice;
+ CFStringRef ifName = NULL;
+ CFStringRef ifSubType;
+ CFStringRef ifType;
+ CFStringRef ifUnique;
+ CFArrayRef matching_interfaces = NULL;
+ SCPreferencesRef servicePref = NULL;
+ Boolean useSystemInterfaces = TRUE;
+
+ /* initialize runtime (and kSCNetworkInterfaceIPv4) */
+ pthread_once(&initialized, __SCNetworkInterfaceInitialize);
+
+ if (service != NULL) {
+ servicePref = ((SCNetworkServicePrivateRef)service)->prefs;
+ useSystemInterfaces = ((__SCPreferencesUsingDefaultPrefs(servicePref)) &&
+ (!__SCPreferencesGetLimitSCNetworkConfiguration(servicePref)));
+ }
+
+ ifType = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceType);
+ if (ifType == NULL) {
+ /*
+ * The interface "Type" was not specified. We'll make an
+ * assumption that this is an "Ethernet" interface. If a
+ * real interface exists with the provided interface name
+ * then the actual type will be set accordingly. If not, we'll
+ * end up crafting an "Ethernet" SCNetworkInterface that
+ * will keep the rest of the configuration APIs happy.
+ */
+ ifType = kSCValNetInterfaceTypeEthernet;
+ }
+
+ if (!isA_CFString(ifType)) {
+ return NULL;
+ }
+
+ ifSubType = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceSubType);
+ if (CFEqual(ifType, kSCValNetInterfaceTypePPP) ||
+ CFEqual(ifType, kSCValNetInterfaceTypeVPN)) {
+ if (!isA_CFString(ifSubType)) {
+ return NULL;
+ }
+ }
+
+ ifDevice = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceDeviceName);
+ ifUnique = CFDictionaryGetValue(interface_entity, CFSTR("DeviceUniqueIdentifier"));
+
+ if (CFEqual(ifType, kSCValNetInterfaceTypeEthernet) ||