+/* ---------- helper functions ---------- */
+
+
+static CFIndex
+findConfiguration(CFStringRef interface_type)
+{
+ CFIndex i;
+
+ for (i = 0; i < sizeof(configurations)/sizeof(configurations[0]); i++) {
+ if (CFEqual(interface_type, *configurations[i].interface_type)) {
+ return i;
+ }
+ }
+
+ return kCFNotFound;
+}
+
+
+static CFArrayRef
+copyConfigurationPaths(SCNetworkInterfacePrivateRef interfacePrivate)
+{
+ CFMutableArrayRef array = NULL;
+ CFIndex interfaceIndex;
+ CFStringRef path;
+ SCNetworkServicePrivateRef servicePrivate;
+
+ servicePrivate = (SCNetworkServicePrivateRef)interfacePrivate->service;
+ if (servicePrivate == NULL) {
+ // if not associated with a service (yet)
+ return NULL;
+ }
+
+ array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ interfaceIndex = findConfiguration(interfacePrivate->interface_type);
+ if (interfaceIndex == kCFNotFound) {
+ // unknown interface type, use per-service configuration preferences
+ path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
+ servicePrivate->serviceID, // service
+ interfacePrivate->interface_type); // entity
+ CFArrayAppendValue(array, path);
+ CFRelease(path);
+ goto done;
+ }
+
+ if (configurations[interfaceIndex].entity_hardware == NULL) {
+ // if no configuration information can be associated with this interface type
+ CFRelease(array);
+ array = NULL;
+ goto done;
+ }
+
+ if (configurations[interfaceIndex].per_interface_config) {
+ CFIndex i;
+ CFIndex n;
+ CFArrayRef sets;
+
+ // known interface type, per-interface configuration preferences
+ //
+ // 1. look for all sets which contain the associated service
+ // 2. add a per-set path for the interface configuration for
+ // each set.
+
+ sets = SCNetworkSetCopyAll(servicePrivate->prefs);
+ n = (sets != NULL) ? CFArrayGetCount(sets) : 0;
+
+ for (i = 0; i < n; i++) {
+ CFArrayRef services;
+ SCNetworkSetRef set;
+
+ set = CFArrayGetValueAtIndex(sets, i);
+ services = SCNetworkSetCopyServices(set);
+ if (CFArrayContainsValue(services,
+ CFRangeMake(0, CFArrayGetCount(services)),
+ interfacePrivate->service)) {
+ path = SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL, // allocator
+ SCNetworkSetGetSetID(set), // set
+ interfacePrivate->entity_device, // service
+ *configurations[interfaceIndex].entity_hardware); // entity
+ CFArrayAppendValue(array, path);
+ CFRelease(path);
+ }
+ CFRelease(services);
+ }
+
+ if (CFArrayGetCount(array) == 0) {
+ CFRelease(array);
+ array = NULL;
+ }
+
+ if (sets != NULL) CFRelease(sets);
+ } else {
+ // known interface type, per-service configuration preferences
+ path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
+ servicePrivate->serviceID, // service
+ *configurations[interfaceIndex].entity_hardware); // entity
+ CFArrayAppendValue(array, path);
+ CFRelease(path);
+ }
+
+ done :
+
+ return array;
+}
+
+
+/* ---------- preferences entity for interface ---------- */
+
+
+__private_extern__ CFDictionaryRef
+__SCNetworkInterfaceCopyInterfaceEntity(SCNetworkInterfaceRef interface)
+{
+ CFMutableDictionaryRef entity;
+ CFIndex interfaceIndex;
+ SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
+
+ entity = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ if (interfacePrivate->entity_type != NULL) {
+ CFDictionarySetValue(entity,
+ kSCPropNetInterfaceType,
+ interfacePrivate->entity_type);
+ }
+ if (interfacePrivate->entity_subtype != NULL) {
+ CFDictionarySetValue(entity,
+ kSCPropNetInterfaceSubType,
+ interfacePrivate->entity_subtype);
+ }
+ if (interfacePrivate->entity_device != NULL) {
+ CFDictionarySetValue(entity,
+ kSCPropNetInterfaceDeviceName,
+ interfacePrivate->entity_device);
+ }
+
+ // match the "hardware" with the lowest layer
+ while (TRUE) {
+ SCNetworkInterfaceRef nextInterface;
+
+ nextInterface = SCNetworkInterfaceGetInterface(interface);
+ if (nextInterface == NULL) {
+ break;
+ }
+
+ interface = nextInterface;
+ }
+ interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
+
+ interfaceIndex = findConfiguration(interfacePrivate->interface_type);
+ if (interfaceIndex != kCFNotFound) {
+ if (configurations[interfaceIndex].entity_hardware != NULL) {
+ CFDictionarySetValue(entity,
+ kSCPropNetInterfaceHardware,
+ *configurations[interfaceIndex].entity_hardware);
+ }
+ } else {
+ CFDictionarySetValue(entity,
+ kSCPropNetInterfaceHardware,
+ interfacePrivate->interface_type);
+ }
+
+ if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeModem) &&
+ interfacePrivate->modemIsV92) {
+ int one = 1;
+ CFNumberRef num;
+
+ num = CFNumberCreate(NULL, kCFNumberIntType, &one);
+ CFDictionarySetValue(entity,
+ kSCPropNetInterfaceSupportsModemOnHold,
+ num);
+ CFRelease(num);
+ }
+
+ return entity;
+}
+
+
+/* ---------- interface from preferences entity ---------- */