this repo has no description
at fixPythonPipStalling 8504 lines 248 kB view raw
1/* 2 * Copyright (c) 2004-2019 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24/* 25 * Modification History 26 * 27 * May 13, 2004 Allan Nathanson <ajn@apple.com> 28 * - initial revision 29 * which includes code originally authored by 30 * Robert Ulrich <rulrich@apple.com> 31 * Elizabeth Douglas <elizabeth@apple.com> 32 * Quinn <eskimo1@apple.com> 33 */ 34 35 36#include <TargetConditionals.h> 37#include <CoreFoundation/CoreFoundation.h> 38#include <CoreFoundation/CFRuntime.h> 39#include "SCNetworkConfigurationInternal.h" 40#include "SCPreferencesInternal.h" 41#include "SCHelper_client.h" 42#include "plugin_shared.h" 43 44#if !TARGET_OS_IPHONE 45#include <EAP8021X/EAPClientProperties.h> 46#else // !TARGET_OS_IPHONE 47#ifndef kEAPClientPropUserName 48#define kEAPClientPropUserName CFSTR("UserName") 49#endif 50#ifndef kEAPClientPropUserPasswordKeychainItemID 51#define kEAPClientPropUserPasswordKeychainItemID CFSTR("UserPasswordKeychainItemID") 52#endif 53#endif // !TARGET_OS_IPHONE 54 55#include <IOKit/IOKitLib.h> 56#include <IOKit/IOCFBundle.h> 57#include <IOKit/IOBSD.h> 58#include <IOKit/network/IONetworkController.h> 59#include <IOKit/network/IONetworkInterface.h> 60#include <IOKit/network/IOEthernetInterface.h> // for kIOEthernetInterfaceClass 61#include <IOKit/serial/IOSerialKeys.h> 62#include <IOKit/storage/IOStorageDeviceCharacteristics.h> 63#if !TARGET_OS_SIMULATOR 64#include <IOKit/usb/IOUSBLib.h> 65#endif // !TARGET_OS_SIMULATOR 66 67#include "dy_framework.h" 68 69#ifndef kPCIThunderboltString 70#define kPCIThunderboltString "PCI-Thunderbolt" 71#endif 72 73#if TARGET_OS_OSX 74#ifndef kUSBSupportsIPhoneOS 75#define kUSBSupportsIPhoneOS "SupportsIPhoneOS" 76#endif // !kUSBSupportsIPhoneOS 77#endif // TARGET_OS_OSX 78 79#ifndef kIOUserEthernetInterfaceRoleKey 80#define kIOUserEthernetInterfaceRoleKey "InterfaceRole" 81#endif 82 83#ifndef kIOUSBHostInterfaceClassName 84#define kIOUSBHostInterfaceClassName "IOUSBHostInterface" 85#endif 86 87#include <string.h> 88#include <sysdir.h> 89#include <mach/mach.h> 90#include <net/if.h> 91#include <net/if_types.h> 92#include <net/if_dl.h> 93#include <net/route.h> 94#include <sys/ioctl.h> 95#include <sys/param.h> 96#include <sys/types.h> 97#include <sys/socket.h> 98#include <sys/stat.h> 99#include <sys/sysctl.h> 100#include <pthread.h> 101#include <ifaddrs.h> 102 103/* CrashReporter "Application Specific Information" */ 104#include <CrashReporterClient.h> 105 106 107static CFStringRef copy_interface_string (CFBundleRef bundle, CFStringRef key, Boolean localized); 108static CFStringRef __SCNetworkInterfaceCopyDescription (CFTypeRef cf); 109static CFStringRef __SCNetworkInterfaceCopyFormattingDescription (CFTypeRef cf, CFDictionaryRef formatOptions); 110static void __SCNetworkInterfaceDeallocate (CFTypeRef cf); 111static Boolean __SCNetworkInterfaceEqual (CFTypeRef cf1, CFTypeRef cf2); 112static CFHashCode __SCNetworkInterfaceHash (CFTypeRef cf); 113static void __SCNetworkInterfaceCacheAdd (CFStringRef bsdName, CFArrayRef matchingInterfaces); 114static Boolean __SCNetworkInterfaceCacheIsOpen (void); 115static CFArrayRef __SCNetworkInterfaceCacheCopy (CFStringRef bsdName); 116 117 118enum { 119 kSortInternalModem = 0, 120 kSortUSBModem, 121 kSortModem, 122 kSortBluetooth, 123 kSortIrDA, 124 kSortSerialPort, 125 kSortWWAN, 126 kSortEthernetPPP, 127 kSortAirportPPP, 128 kSortEthernet, 129 kSortFireWire, 130 kSortAirPort, 131 kSortOtherWireless, 132 kSortTethered, 133 kSortWWANEthernet, 134 kSortBluetoothPAN_GN, 135 kSortBluetoothPAN_NAP, 136 kSortBluetoothPAN_U, 137 kSortThunderbolt, 138 kSortCarPlay, 139 kSortBond, 140 kSortBridge, 141 kSortVLAN, 142 kSortUnknown 143}; 144 145 146static const char *sortOrderName[] = { 147 "InternalModem", 148 "USBModem", 149 "Modem", 150 "Bluetooth", 151 "IrDA", 152 "SerialPort", 153 "WWAN", 154 "EthernetPPP", 155 "AirportPPP", 156 "Ethernet", 157 "FireWire", 158 "AirPort", 159 "OtherWireless", 160 "Tethered", 161 "WWANEthernet", 162 "BluetoothPAN_GN", 163 "BluetoothPAN_NAP", 164 "BluetoothPAN_U", 165 "Thunderbolt", 166 "CarPlay", 167 "Bond", 168 "Bridge", 169 "VLAN", 170 "Unknown" 171}; 172 173 174const CFStringRef kSCNetworkInterfaceType6to4 = CFSTR("6to4"); 175const CFStringRef kSCNetworkInterfaceTypeBluetooth = CFSTR("Bluetooth"); 176const CFStringRef kSCNetworkInterfaceTypeBond = CFSTR("Bond"); 177const CFStringRef kSCNetworkInterfaceTypeBridge = CFSTR("Bridge"); 178const CFStringRef kSCNetworkInterfaceTypeEthernet = CFSTR("Ethernet"); 179const CFStringRef kSCNetworkInterfaceTypeFireWire = CFSTR("FireWire"); 180const CFStringRef kSCNetworkInterfaceTypeIEEE80211 = CFSTR("IEEE80211"); // IEEE 802.11, AirPort 181const CFStringRef kSCNetworkInterfaceTypeIPSec = CFSTR("IPSec"); 182const CFStringRef kSCNetworkInterfaceTypeIrDA = CFSTR("IrDA"); 183const CFStringRef kSCNetworkInterfaceTypeL2TP = CFSTR("L2TP"); 184const CFStringRef kSCNetworkInterfaceTypeLoopback = CFSTR("Loopback"); 185const CFStringRef kSCNetworkInterfaceTypeModem = CFSTR("Modem"); 186const CFStringRef kSCNetworkInterfaceTypePPP = CFSTR("PPP"); 187const CFStringRef kSCNetworkInterfaceTypePPTP = CFSTR("PPTP"); 188const CFStringRef kSCNetworkInterfaceTypeSerial = CFSTR("Serial"); 189const CFStringRef kSCNetworkInterfaceTypeVLAN = CFSTR("VLAN"); 190const CFStringRef kSCNetworkInterfaceTypeVPN = CFSTR("VPN"); 191const CFStringRef kSCNetworkInterfaceTypeWWAN = CFSTR("WWAN"); 192 193const CFStringRef kSCNetworkInterfaceTypeIPv4 = CFSTR("IPv4"); 194 195static SCNetworkInterfacePrivate __kSCNetworkInterfaceIPv4 = { 196 .cfBase = INIT_CFRUNTIME_BASE(), // cfBase 197 .sort_order = kSortUnknown, // sort_order 198}; 199 200const SCNetworkInterfaceRef kSCNetworkInterfaceIPv4 = (SCNetworkInterfaceRef)&__kSCNetworkInterfaceIPv4; 201 202static SCNetworkInterfacePrivate __kSCNetworkInterfaceLoopback = { 203 .cfBase = INIT_CFRUNTIME_BASE(), // cfBase 204 .sort_order = kSortUnknown, // sort_order 205}; 206 207const SCNetworkInterfaceRef kSCNetworkInterfaceLoopback = (SCNetworkInterfaceRef)&__kSCNetworkInterfaceLoopback; 208 209static CFMutableSetRef vendor_interface_types = NULL; 210 211// A thread-specific convenience cache of all interfaces matching a bsd name 212// Key: CFStringRef (BSD name) 213// Value: CFArrayRef (matching interfaces) 214static __thread CFMutableDictionaryRef S_interface_cache = NULL; 215 216#pragma mark - 217#pragma mark SCNetworkInterface configuration details 218 219#define doNone 0 220 221#define do6to4 1<<0 222#define doL2TP 1<<1 223#define doPPP 1<<2 224#define doPPTP 1<<3 225#define doIPSec 1<<4 226#define doOverIP do6to4|doL2TP|doPPTP|doIPSec 227 228#define doDNS 1<<1 229#define doIPv4 1<<2 230#define doIPv6 1<<3 231#define doProxies 1<<4 232#if !TARGET_OS_IPHONE 233#define doSMB 1<<5 234#else // !TARGET_OS_IPHONE 235#define doSMB 0 236#endif // !TARGET_OS_IPHONE 237 238static const struct { 239 const CFStringRef *interface_type; 240 const CFStringRef *entity_hardware; 241 Boolean per_interface_config; 242 uint32_t supported_interfaces; 243 const CFStringRef *ppp_subtype; 244 uint32_t supported_protocols; 245} configurations[] = { 246 // interface type entity_hardware if config? interface types PPP sub-type interface protocols 247 // ===================================== ==================== ========== =============== ======================================= ========================================= 248 { &kSCNetworkInterfaceType6to4 , &kSCEntNet6to4 , FALSE, doNone, NULL, doIPv6 }, 249 { &kSCNetworkInterfaceTypeBluetooth , &kSCEntNetModem , FALSE, doPPP, &kSCValNetInterfaceSubTypePPPSerial, doNone }, 250 { &kSCNetworkInterfaceTypeBond , &kSCEntNetEthernet , TRUE , doNone, NULL, doDNS|doIPv4|doIPv6|doProxies|doSMB }, 251 { &kSCNetworkInterfaceTypeBridge , &kSCEntNetEthernet , TRUE , doNone, NULL, doDNS|doIPv4|doIPv6|doProxies|doSMB }, 252 { &kSCNetworkInterfaceTypeEthernet , &kSCEntNetEthernet , TRUE , doPPP, &kSCValNetInterfaceSubTypePPPoE, doDNS|doIPv4|doIPv6|doProxies|doSMB }, 253 { &kSCNetworkInterfaceTypeFireWire , &kSCEntNetFireWire , TRUE , doNone, NULL, doDNS|doIPv4|doIPv6|doProxies|doSMB }, 254 { &kSCNetworkInterfaceTypeIEEE80211 , &kSCEntNetAirPort , TRUE , doPPP, &kSCValNetInterfaceSubTypePPPoE, doDNS|doIPv4|doIPv6|doProxies|doSMB }, 255 { &kSCNetworkInterfaceTypeIPSec , &kSCEntNetIPSec , FALSE, doNone, NULL, doDNS|doIPv4|doIPv6|doProxies|doSMB }, 256 { &kSCNetworkInterfaceTypeIrDA , &kSCEntNetModem , FALSE, doPPP, &kSCValNetInterfaceSubTypePPPSerial, doNone }, 257 { &kSCNetworkInterfaceTypeL2TP , NULL , FALSE, doPPP, &kSCValNetInterfaceSubTypeL2TP, doNone }, 258 { &kSCNetworkInterfaceTypeModem , &kSCEntNetModem , FALSE, doPPP, &kSCValNetInterfaceSubTypePPPSerial, doNone }, 259 { &kSCNetworkInterfaceTypePPP , &kSCEntNetPPP , FALSE, doNone, NULL, doDNS|doIPv4|doIPv6|doProxies|doSMB }, 260#pragma GCC diagnostic push 261#pragma GCC diagnostic ignored "-Wdeprecated" 262 { &kSCNetworkInterfaceTypePPTP , NULL , FALSE, doPPP, &kSCValNetInterfaceSubTypePPTP, doNone }, 263#pragma GCC diagnostic pop 264 { &kSCNetworkInterfaceTypeSerial , &kSCEntNetModem , FALSE, doPPP, &kSCValNetInterfaceSubTypePPPSerial, doNone }, 265 { &kSCNetworkInterfaceTypeVLAN , &kSCEntNetEthernet , TRUE , doNone, &kSCValNetInterfaceSubTypePPPoE, doDNS|doIPv4|doIPv6|doProxies|doSMB }, 266 { &kSCNetworkInterfaceTypeVPN , &kSCEntNetVPN , FALSE, doNone, NULL, doDNS|doIPv4|doIPv6|doProxies|doSMB }, 267 { &kSCNetworkInterfaceTypeWWAN , &kSCEntNetModem , FALSE, doPPP, &kSCValNetInterfaceSubTypePPPSerial, doNone }, 268 // ===================================== =================== ========== =============== ======================================= ========================================= 269 { &kSCNetworkInterfaceTypeLoopback , NULL , TRUE , doNone, NULL, doIPv4|doIPv6 }, 270 // ===================================== =================== ========== =============== ======================================= ========================================= 271 { &kSCNetworkInterfaceTypeIPv4 , NULL , FALSE, doOverIP, NULL, doNone } 272}; 273 274 275#define kSCNetworkInterfaceActive "Active" 276#define kSCNetworkInterfaceInfo "SCNetworkInterfaceInfo" 277#define kSCNetworkInterfaceType "SCNetworkInterfaceType" 278#define kSCNetworkInterfaceBSDName kIOBSDNameKey 279#define kSCNetworkInterfaceIOBuiltin kIOBuiltin 280#define kSCNetworkInterfaceIOInterfaceNamePrefix kIOInterfaceNamePrefix 281#define kSCNetworkInterfaceIOInterfaceType kIOInterfaceType 282#define kSCNetworkInterfaceIOInterfaceUnit kIOInterfaceUnit 283#define kSCNetworkInterfaceIOMACAddress kIOMACAddress 284#define kSCNetworkInterfaceIOPathMatch kIOPathMatchKey 285 286 287#define NETWORKINTERFACE_LOCALIZATIONS CFSTR("NetworkInterface") 288static CFBundleRef bundle = NULL; 289 290 291static CFTypeID __kSCNetworkInterfaceTypeID = _kCFRuntimeNotATypeID; 292 293 294static const CFRuntimeClass __SCNetworkInterfaceClass = { 295 0, // version 296 "SCNetworkInterface", // className 297 NULL, // init 298 NULL, // copy 299 __SCNetworkInterfaceDeallocate, // dealloc 300 __SCNetworkInterfaceEqual, // equal 301 __SCNetworkInterfaceHash, // hash 302 __SCNetworkInterfaceCopyFormattingDescription, // copyFormattingDesc 303 __SCNetworkInterfaceCopyDescription // copyDebugDesc 304}; 305 306 307static pthread_once_t initialized = PTHREAD_ONCE_INIT; 308static pthread_once_t iokit_quiet = PTHREAD_ONCE_INIT; 309static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; 310 311 312static mach_port_t masterPort = MACH_PORT_NULL; 313 314static CFStringRef 315__SCNetworkInterfaceCopyDescription(CFTypeRef cf) 316{ 317 return __SCNetworkInterfaceCopyFormattingDescription(cf, NULL); 318} 319 320static CFStringRef 321__SCNetworkInterfaceCopyFormattingDescription(CFTypeRef cf, CFDictionaryRef formatOptions) 322{ 323 CFAllocatorRef allocator = CFGetAllocator(cf); 324 CFMutableStringRef result; 325 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)cf; 326 327 result = CFStringCreateMutable(allocator, 0); 328 CFStringAppendFormat(result, NULL, CFSTR("<SCNetworkInterface %p [%p]> {"), cf, allocator); 329 CFStringAppendFormat(result, NULL, CFSTR("type = %@"), interfacePrivate->interface_type); 330 CFStringAppendFormat(result, NULL, CFSTR(", entity_device = %@"), interfacePrivate->entity_device); 331 if (interfacePrivate->entity_device_unique != NULL) { 332 CFStringAppendFormat(result, NULL, CFSTR("+%@"), interfacePrivate->entity_device_unique); 333 } 334 CFStringAppendFormat(result, NULL, CFSTR(", entity_type = %@"), interfacePrivate->entity_type); 335 if (interfacePrivate->entity_subtype != NULL) { 336 CFStringAppendFormat(result, NULL, CFSTR(" / %@"), interfacePrivate->entity_subtype); 337 } 338 if (interfacePrivate->name != NULL) { 339 CFStringAppendFormat(result, NULL, CFSTR(", name = %@"), interfacePrivate->name); 340 } 341 if (interfacePrivate->localized_name != NULL) { 342 CFStringAppendFormat(result, NULL, CFSTR(", name(l) = %@"), interfacePrivate->localized_name); 343 } else { 344 if (interfacePrivate->localized_key != NULL) { 345 CFStringAppendFormat(result, NULL, CFSTR(", name(k) = \"%@\""), interfacePrivate->localized_key); 346 if (interfacePrivate->localized_arg1 != NULL) { 347 CFStringAppendFormat(result, NULL, CFSTR("+\"%@\""), interfacePrivate->localized_arg1); 348 } 349 if (interfacePrivate->localized_arg2 != NULL) { 350 CFStringAppendFormat(result, NULL, CFSTR("+\"%@\""), interfacePrivate->localized_arg2); 351 } 352 } 353 } 354 if (interfacePrivate->address != NULL) { 355 const uint8_t *data; 356 CFIndex dataLen; 357 CFIndex i; 358 359 CFStringAppendFormat(result, NULL, CFSTR(", address = ")); 360 361 data = CFDataGetBytePtr(interfacePrivate->address); 362 dataLen = CFDataGetLength(interfacePrivate->address); 363 for (i = 0; i < dataLen; i++) { 364 CFStringAppendFormat(result, NULL, CFSTR("%s%02x"), 365 (i > 0) ? ":" : "", 366 data[i]); 367 } 368 } 369 CFStringAppendFormat(result, NULL, CFSTR(", builtin = %s"), interfacePrivate->builtin ? "TRUE" : "FALSE"); 370 if (interfacePrivate->hidden) { 371 CFStringAppendFormat(result, NULL, CFSTR(", hidden = TRUE")); 372 } 373#if TARGET_OS_IPHONE 374 if (interfacePrivate->trustRequired) { 375 CFStringAppendFormat(result, NULL, CFSTR(", trust required = TRUE")); 376 } 377#endif // TARGET_OS_IPHONE 378 if (interfacePrivate->location != NULL) { 379 CFStringAppendFormat(result, NULL, CFSTR(", location = %@"), interfacePrivate->location); 380 } 381 if (interfacePrivate->path != NULL) { 382 CFStringAppendFormat(result, NULL, CFSTR(", path = %@"), interfacePrivate->path); 383 } 384 if (interfacePrivate->entryID != 0) { 385 CFStringAppendFormat(result, NULL, CFSTR(", entryID = 0x%llx"), interfacePrivate->entryID); 386 } 387 if (interfacePrivate->type != NULL) { 388 CFStringAppendFormat(result, NULL, CFSTR(", type = %@"), interfacePrivate->type); 389 } 390 if (interfacePrivate->unit != NULL) { 391 CFStringAppendFormat(result, NULL, CFSTR(", unit = %@"), interfacePrivate->unit); 392 } 393 if (interfacePrivate->family != NULL) { 394 CFStringAppendFormat(result, NULL, CFSTR(", family = %@"), interfacePrivate->family); 395 } 396 if (interfacePrivate->subfamily != NULL) { 397 CFStringAppendFormat(result, NULL, CFSTR(", subfamily = %@"), interfacePrivate->subfamily); 398 } 399 if ((interfacePrivate->usb.vid != NULL) || (interfacePrivate->usb.pid != NULL)) { 400 int pid = 0; 401 int vid = 0; 402 403 if (!isA_CFNumber(interfacePrivate->usb.pid) || 404 !CFNumberGetValue(interfacePrivate->usb.pid, kCFNumberIntType, &pid)) { 405 pid = 0; 406 } 407 if (!isA_CFNumber(interfacePrivate->usb.vid) || 408 !CFNumberGetValue(interfacePrivate->usb.vid, kCFNumberIntType, &vid)) { 409 vid = 0; 410 } 411 412 if (interfacePrivate->usb.name != NULL) { 413 CFStringAppendFormat(result, NULL, CFSTR(", USB name = %@"), 414 interfacePrivate->usb.name); 415 } 416 417 CFStringAppendFormat(result, NULL, CFSTR(", USB vid/pid = 0x%0x/0x%0x"), 418 vid, 419 pid); 420 } 421 if (interfacePrivate->configurationAction != NULL) { 422 CFStringAppendFormat(result, NULL, CFSTR(", action = %@"), interfacePrivate->configurationAction); 423 } 424 if (interfacePrivate->overrides != NULL) { 425 CFStringRef str; 426 427 str = _SCCopyDescription(interfacePrivate->overrides, formatOptions); 428 CFStringAppendFormat(result, formatOptions, CFSTR(", overrides = %@"), str); 429 CFRelease(str); 430 } 431 CFStringAppendFormat(result, NULL, CFSTR(", order = %d (%s)"), 432 interfacePrivate->sort_order, 433 interfacePrivate->sort_order <= kSortUnknown ? sortOrderName[interfacePrivate->sort_order] : "?"); 434 if (interfacePrivate->prefs != NULL) { 435 CFStringAppendFormat(result, NULL, CFSTR(", prefs = %p"), interfacePrivate->prefs); 436 } 437 if (interfacePrivate->serviceID != NULL) { 438 CFStringAppendFormat(result, NULL, CFSTR(", service = %@"), interfacePrivate->serviceID); 439 } 440 if (interfacePrivate->interface != NULL) { 441 CFStringAppendFormat(result, NULL, CFSTR(", interface = %@"), interfacePrivate->interface); 442 } 443 if (interfacePrivate->unsaved != NULL) { 444 CFStringAppendFormat(result, formatOptions, CFSTR(", unsaved = %@"), interfacePrivate->unsaved); 445 } 446 447 if (interfacePrivate->bond.interfaces != NULL) { 448 CFIndex i; 449 CFIndex n; 450 451 n = CFArrayGetCount(interfacePrivate->bond.interfaces); 452 for (i = 0; i < n; i++) { 453 SCNetworkInterfaceRef member; 454 455 member = CFArrayGetValueAtIndex(interfacePrivate->bond.interfaces, i); 456 CFStringAppendFormat(result, NULL, 457 CFSTR("%s%@"), 458 (i == 0) ? ", interfaces = " : ",", 459 SCNetworkInterfaceGetBSDName(member)); 460 } 461 } 462 if (interfacePrivate->bond.mode != NULL) { 463 CFStringAppendFormat(result, NULL, CFSTR(", mode = %@"), interfacePrivate->bond.mode); 464 } 465 if (interfacePrivate->bond.options != NULL) { 466 CFStringRef str; 467 468 str = _SCCopyDescription(interfacePrivate->bond.options, formatOptions); 469 CFStringAppendFormat(result, formatOptions, CFSTR(", options = %@"), str); 470 CFRelease(str); 471 } 472 473 if (interfacePrivate->bridge.interfaces != NULL) { 474 CFIndex i; 475 CFIndex n; 476 477 n = CFArrayGetCount(interfacePrivate->bridge.interfaces); 478 for (i = 0; i < n; i++) { 479 SCNetworkInterfaceRef member; 480 481 member = CFArrayGetValueAtIndex(interfacePrivate->bridge.interfaces, i); 482 CFStringAppendFormat(result, NULL, 483 CFSTR("%s%@"), 484 (i == 0) ? ", interfaces = " : ",", 485 SCNetworkInterfaceGetBSDName(member)); 486 } 487 } 488 if (interfacePrivate->bridge.options != NULL) { 489 CFStringRef str; 490 491 str = _SCCopyDescription(interfacePrivate->bridge.options, formatOptions); 492 CFStringAppendFormat(result, formatOptions, CFSTR(", options = %@"), str); 493 CFRelease(str); 494 } 495 496 if (interfacePrivate->vlan.interface != NULL) { 497 CFStringAppendFormat(result, NULL, 498 CFSTR(", interface = %@"), 499 SCNetworkInterfaceGetBSDName(interfacePrivate->vlan.interface)); 500 } 501 if (interfacePrivate->vlan.tag != NULL) { 502 CFStringAppendFormat(result, NULL, CFSTR(", tag = %@"), interfacePrivate->vlan.tag); 503 } 504 if (interfacePrivate->vlan.options != NULL) { 505 CFStringRef str; 506 507 str = _SCCopyDescription(interfacePrivate->vlan.options, formatOptions); 508 CFStringAppendFormat(result, formatOptions, CFSTR(", options = %@"), str); 509 CFRelease(str); 510 } 511 512 CFStringAppendFormat(result, NULL, CFSTR("}")); 513 514 return result; 515} 516 517 518static void 519__SCNetworkInterfaceDeallocate(CFTypeRef cf) 520{ 521 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)cf; 522 523 /* release resources */ 524 525 if (interfacePrivate->name != NULL) 526 CFRelease(interfacePrivate->name); 527 528 if (interfacePrivate->localized_name != NULL) 529 CFRelease(interfacePrivate->localized_name); 530 531 if (interfacePrivate->localized_arg1 != NULL) 532 CFRelease(interfacePrivate->localized_arg1); 533 534 if (interfacePrivate->localized_arg2 != NULL) 535 CFRelease(interfacePrivate->localized_arg2); 536 537 if (interfacePrivate->interface != NULL) 538 CFRelease(interfacePrivate->interface); 539 540 if (interfacePrivate->prefs != NULL) 541 CFRelease(interfacePrivate->prefs); 542 543 if (interfacePrivate->store != NULL) 544 CFRelease(interfacePrivate->store); 545 546 if (interfacePrivate->serviceID != NULL) 547 CFRelease(interfacePrivate->serviceID); 548 549 if (interfacePrivate->unsaved != NULL) 550 CFRelease(interfacePrivate->unsaved); 551 552 if (interfacePrivate->entity_device != NULL) 553 CFRelease(interfacePrivate->entity_device); 554 555 if (interfacePrivate->entity_device_unique != NULL) 556 CFRelease(interfacePrivate->entity_device_unique); 557 558 if (interfacePrivate->supported_interface_types != NULL) 559 CFRelease(interfacePrivate->supported_interface_types); 560 561 if (interfacePrivate->supported_protocol_types != NULL) 562 CFRelease(interfacePrivate->supported_protocol_types); 563 564 if (interfacePrivate->address != NULL) 565 CFRelease(interfacePrivate->address); 566 567 if (interfacePrivate->addressString != NULL) 568 CFRelease(interfacePrivate->addressString); 569 570 if (interfacePrivate->configurationAction != NULL) 571 CFRelease(interfacePrivate->configurationAction); 572 573 if (interfacePrivate->location != NULL) 574 CFRelease(interfacePrivate->location); 575 576 if (interfacePrivate->path != NULL) 577 CFRelease(interfacePrivate->path); 578 579 if (interfacePrivate->overrides != NULL) 580 CFRelease(interfacePrivate->overrides); 581 582 if (interfacePrivate->prefix != NULL) 583 CFRelease(interfacePrivate->prefix); 584 585 if (interfacePrivate->type != NULL) 586 CFRelease(interfacePrivate->type); 587 588 if (interfacePrivate->unit != NULL) 589 CFRelease(interfacePrivate->unit); 590 591 if (interfacePrivate->family != NULL) 592 CFRelease(interfacePrivate->family); 593 594 if (interfacePrivate->subfamily != NULL) 595 CFRelease(interfacePrivate->subfamily); 596 597 if (interfacePrivate->usb.name != NULL) 598 CFRelease(interfacePrivate->usb.name); 599 600 if (interfacePrivate->usb.pid != NULL) 601 CFRelease(interfacePrivate->usb.pid); 602 603 if (interfacePrivate->usb.vid != NULL) 604 CFRelease(interfacePrivate->usb.vid); 605 606 if (interfacePrivate->bond.interfaces != NULL) 607 CFRelease(interfacePrivate->bond.interfaces); 608 609 if (interfacePrivate->bond.mode != NULL) 610 CFRelease(interfacePrivate->bond.mode); 611 612 if (interfacePrivate->bond.options != NULL) 613 CFRelease(interfacePrivate->bond.options); 614 615 if (interfacePrivate->bridge.interfaces != NULL) 616 CFRelease(interfacePrivate->bridge.interfaces); 617 618 if (interfacePrivate->bridge.options != NULL) 619 CFRelease(interfacePrivate->bridge.options); 620 621 if (interfacePrivate->vlan.interface != NULL) 622 CFRelease(interfacePrivate->vlan.interface); 623 624 if (interfacePrivate->vlan.tag != NULL) 625 CFRelease(interfacePrivate->vlan.tag); 626 627 if (interfacePrivate->vlan.options != NULL) 628 CFRelease(interfacePrivate->vlan.options); 629#if !TARGET_OS_SIMULATOR 630 if (interfacePrivate->IPMonitorControl != NULL) 631 CFRelease(interfacePrivate->IPMonitorControl); 632#endif // !TARGET_OS_SIMULATOR 633 return; 634} 635 636 637static Boolean 638__SCNetworkInterfaceEqual(CFTypeRef cf1, CFTypeRef cf2) 639{ 640 SCNetworkInterfacePrivateRef if1 = (SCNetworkInterfacePrivateRef)cf1; 641 SCNetworkInterfacePrivateRef if2 = (SCNetworkInterfacePrivateRef)cf2; 642 643 if (if1 == if2) 644 return TRUE; 645 646 if (!CFEqual(if1->interface_type, if2->interface_type)) { 647 return FALSE; // if not the same interface type 648 } 649 650 if (!_SC_CFEqual(if1->entity_device, if2->entity_device)) { 651 return FALSE; // if not the same device 652 } 653 654 if ((if1->entity_device_unique != NULL) && (if2->entity_device_unique != NULL)) { 655 if (!_SC_CFEqual(if1->entity_device_unique, if2->entity_device_unique)) { 656 return FALSE; // if not the same device unique identifier 657 } 658 } else if ((if1->entity_device_unique != NULL) || (if2->entity_device_unique != NULL)) { 659 CFStringRef name1; 660 CFStringRef name2; 661 662 name1 = __SCNetworkInterfaceGetNonLocalizedDisplayName((SCNetworkInterfaceRef)if1); 663 name2 = __SCNetworkInterfaceGetNonLocalizedDisplayName((SCNetworkInterfaceRef)if2); 664 if ((name1 != NULL) && (name2 != NULL) && !_SC_CFEqual(name1, name2)) { 665 return FALSE; // if same device but not the same display name 666 } 667 } 668 669 if (CFEqual(if1->interface_type, kSCNetworkInterfaceTypeBond)) { 670 if (!_SC_CFEqual(if1->bond.interfaces, if2->bond.interfaces)) { 671 return FALSE; // if not the same interfaces 672 } 673 if (!_SC_CFEqual(if1->bond.mode, if2->bond.mode)) { 674 return FALSE; // if not the same mode 675 } 676 } 677 678 if (CFEqual(if1->interface_type, kSCNetworkInterfaceTypeBridge)) { 679 if (!_SC_CFEqual(if1->bridge.interfaces, if2->bridge.interfaces)) { 680 return FALSE; // if not the same interfaces 681 } 682 } 683 684 if (CFEqual(if1->interface_type, kSCNetworkInterfaceTypeVLAN)) { 685 if (!_SC_CFEqual(if1->vlan.interface, if2->vlan.interface)) { 686 return FALSE; // if not the same physical interface 687 } 688 if (!_SC_CFEqual(if1->vlan.tag, if2->vlan.tag)) { 689 return FALSE; // if not the same tag 690 } 691 } 692 693 if (!_SC_CFEqual(if1->interface, if2->interface)) { 694 return FALSE; // if not the same layering 695 } 696 697 return TRUE; 698} 699 700 701static CFHashCode 702__SCNetworkInterfaceHash(CFTypeRef cf) 703{ 704 CFHashCode hash = 0; 705 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)cf; 706 707 if (interfacePrivate->entity_device != NULL) { 708 if (interfacePrivate->entity_device_unique == NULL) { 709 hash = CFHash(interfacePrivate->entity_device); 710 } else { 711 CFStringRef str; 712 713 str = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@+%@"), 714 interfacePrivate->entity_device, 715 interfacePrivate->entity_device_unique); 716 hash = CFHash(str); 717 CFRelease(str); 718 } 719 } 720 721 return hash; 722} 723 724 725static void 726__SCNetworkInterfaceInitialize(void) 727{ 728 kern_return_t kr; 729 730 // register w/CF 731 __kSCNetworkInterfaceTypeID = _CFRuntimeRegisterClass(&__SCNetworkInterfaceClass); 732 733 // initialize __kSCNetworkInterfaceIPv4 734 _CFRuntimeInitStaticInstance(&__kSCNetworkInterfaceIPv4, __kSCNetworkInterfaceTypeID); 735 __kSCNetworkInterfaceIPv4.interface_type = kSCNetworkInterfaceTypeIPv4; 736 __kSCNetworkInterfaceIPv4.localized_key = CFSTR("ipv4"); 737 738 // initialize __kSCNetworkInterfaceLoopback 739 _CFRuntimeInitStaticInstance(&__kSCNetworkInterfaceLoopback, __kSCNetworkInterfaceTypeID); 740 __kSCNetworkInterfaceLoopback.interface_type = kSCNetworkInterfaceTypeLoopback; 741 __kSCNetworkInterfaceLoopback.localized_key = CFSTR("loopback"); 742 __kSCNetworkInterfaceLoopback.entity_device = CFRetain(CFSTR("lo0")); 743 __kSCNetworkInterfaceLoopback.entity_type = kSCValNetInterfaceTypeLoopback; 744 745 // get CFBundleRef for SystemConfiguration.framework 746 bundle = _SC_CFBundleGet(); 747 748 // get mach port used to communication with IOKit 749 kr = IOMasterPort(MACH_PORT_NULL, &masterPort); 750 if (kr != kIOReturnSuccess) { 751 SC_log(LOG_NOTICE, "could not get IOMasterPort, kr = 0x%x", kr); 752 } 753 754 return; 755} 756 757 758__private_extern__ 759SCNetworkInterfacePrivateRef 760__SCNetworkInterfaceCreatePrivate(CFAllocatorRef allocator, 761 SCNetworkInterfaceRef interface, 762 SCPreferencesRef prefs, 763 CFStringRef serviceID) 764{ 765 SCNetworkInterfacePrivateRef interfacePrivate; 766 uint32_t size; 767 768 /* initialize runtime */ 769 pthread_once(&initialized, __SCNetworkInterfaceInitialize); 770 771 /* allocate target */ 772 size = sizeof(SCNetworkInterfacePrivate) - sizeof(CFRuntimeBase); 773 interfacePrivate = (SCNetworkInterfacePrivateRef)_CFRuntimeCreateInstance(allocator, 774 __kSCNetworkInterfaceTypeID, 775 size, 776 NULL); 777 if (interfacePrivate == NULL) { 778 return NULL; 779 } 780 781 /* initialize non-zero/NULL members */ 782 interfacePrivate->interface = (interface != NULL) ? CFRetain(interface) : NULL; 783 interfacePrivate->prefs = (prefs != NULL) ? CFRetain(prefs) : NULL; 784 interfacePrivate->serviceID = (serviceID != NULL) ? CFRetain(serviceID) : NULL; 785 interfacePrivate->sort_order = kSortUnknown; 786 787 return interfacePrivate; 788} 789 790 791__private_extern__ 792Boolean 793__SCNetworkInterfaceSupportsVLAN(CFStringRef bsd_if) 794{ 795 char * buf = NULL; 796 size_t buf_len = 0; 797 struct if_msghdr * ifm; 798 char * if_name = NULL; 799 unsigned int if_index; 800 int mib[6]; 801 Boolean vlanOK = FALSE; 802 803 // get the interface index 804 if_name = _SC_cfstring_to_cstring(bsd_if, NULL, 0, kCFStringEncodingASCII); 805 if (if_name == NULL) { 806 return FALSE; // if conversion error 807 } 808 if_index = if_nametoindex(if_name); 809 if (if_index == 0) { 810 goto done; // if unknown interface 811 } 812 813 // get information for the specified interface 814 mib[0] = CTL_NET; 815 mib[1] = PF_ROUTE; 816 mib[2] = 0; 817 mib[3] = AF_LINK; 818 mib[4] = NET_RT_IFLIST; 819 mib[5] = if_index; /* ask for exactly one interface */ 820 821 if (sysctl(mib, 6, NULL, &buf_len, NULL, 0) == -1) { 822 SC_log(LOG_NOTICE, "sysctl() size failed: %s", strerror(errno)); 823 goto done; 824 } 825 buf = CFAllocatorAllocate(NULL, buf_len, 0); 826 if (sysctl(mib, 6, buf, &buf_len, NULL, 0) == -1) { 827 SC_log(LOG_NOTICE, "sysctl() failed: %s", strerror(errno)); 828 goto done; 829 } 830 831 // check the link type and hwassist flags 832 // ALIGN: buf is aligned 833 ifm = (struct if_msghdr *)(void *)buf; 834 switch (ifm->ifm_type) { 835 case RTM_IFINFO : { 836#if defined(IF_HWASSIST_VLAN_TAGGING) && defined(IF_HWASSIST_VLAN_MTU) 837 struct if_data *if_data = &ifm->ifm_data; 838 839 if (if_data->ifi_hwassist & (IF_HWASSIST_VLAN_TAGGING | IF_HWASSIST_VLAN_MTU)) { 840 vlanOK = TRUE; 841 } 842#endif 843 break; 844 } 845 } 846 847 done : 848 849 if (if_name != NULL) CFAllocatorDeallocate(NULL, if_name); 850 if (buf != NULL) CFAllocatorDeallocate(NULL, buf); 851 852 return vlanOK; 853} 854 855 856static CFDataRef 857__SCCopyMacAddress(CFStringRef ifname) 858{ 859 struct ifaddrs *ifap; 860 char ifname_c[IFNAMSIZ]; 861 struct ifaddrs *ifp; 862 CFDataRef macAddress = NULL; 863 864 if(_SC_cfstring_to_cstring(ifname, 865 ifname_c, 866 sizeof(ifname_c), 867 kCFStringEncodingUTF8) == NULL) { 868 return NULL; 869 } 870 871 if (getifaddrs(&ifap) == -1) { 872 _SCErrorSet(errno); 873 SC_log(LOG_NOTICE, "getifaddrs() failed: %s", strerror(errno)); 874 return NULL; 875 } 876 877 for (ifp = ifap; ifp != NULL; ifp = ifp->ifa_next) { 878 struct sockaddr_dl *sdl; 879 880 if(strcmp(ifname_c, ifp->ifa_name) != 0) { 881 continue; 882 } 883 884 /* ALIGN: cast ok, this should be aligned (getifaddrs). */ 885 sdl = (struct sockaddr_dl *)(void *)ifp->ifa_addr; 886 if (sdl->sdl_family != AF_LINK) { 887 continue; 888 } 889 890 macAddress = CFDataCreate(NULL, (UInt8 *)LLADDR(sdl), sdl->sdl_alen); 891 break; 892 } 893 freeifaddrs(ifap); 894 return macAddress; 895} 896 897 898__private_extern__ 899SCNetworkInterfacePrivateRef 900_SCBondInterfaceCreatePrivate(CFAllocatorRef allocator, 901 CFStringRef bond_if) 902{ 903 SCNetworkInterfacePrivateRef interfacePrivate; 904 905 interfacePrivate = __SCNetworkInterfaceCreatePrivate(allocator, NULL, NULL, NULL); 906 if (interfacePrivate == NULL) { 907 return NULL; 908 } 909 910 interfacePrivate->interface_type = kSCNetworkInterfaceTypeBond; 911 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet; 912 interfacePrivate->entity_device = CFStringCreateCopy(allocator, bond_if); 913 interfacePrivate->address = __SCCopyMacAddress(interfacePrivate->entity_device); 914 interfacePrivate->builtin = TRUE; 915 interfacePrivate->supportsVLAN = __SCNetworkInterfaceSupportsVLAN(bond_if); 916 interfacePrivate->sort_order = kSortBond; 917 918 interfacePrivate->localized_key = CFSTR("bond"); 919 interfacePrivate->localized_arg1 = CFRetain(interfacePrivate->entity_device); 920 921 interfacePrivate->bond.interfaces = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks); 922// interfacePrivate->bond.mode = NULL; 923// interfacePrivate->bond.options = NULL; 924 925 return interfacePrivate; 926} 927 928 929__private_extern__ 930SCNetworkInterfacePrivateRef 931_SCBridgeInterfaceCreatePrivate(CFAllocatorRef allocator, 932 CFStringRef bridge_if) 933{ 934 SCNetworkInterfacePrivateRef interfacePrivate; 935 936 interfacePrivate = __SCNetworkInterfaceCreatePrivate(allocator, NULL, NULL, NULL); 937 if (interfacePrivate == NULL) { 938 return NULL; 939 } 940 941 interfacePrivate->interface_type = kSCNetworkInterfaceTypeBridge; 942 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet; 943 interfacePrivate->entity_device = CFStringCreateCopy(allocator, bridge_if); 944 interfacePrivate->address = __SCCopyMacAddress(interfacePrivate->entity_device); 945 interfacePrivate->builtin = TRUE; 946 interfacePrivate->supportsVLAN = __SCNetworkInterfaceSupportsVLAN(bridge_if); 947 interfacePrivate->sort_order = kSortBridge; 948 949 interfacePrivate->localized_key = CFSTR("bridge"); 950 interfacePrivate->localized_arg1 = CFRetain(interfacePrivate->entity_device); 951 952 interfacePrivate->bridge.interfaces = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks); 953// interfacePrivate->bridge.options = NULL; 954 955 return interfacePrivate; 956} 957 958 959__private_extern__ 960SCNetworkInterfacePrivateRef 961_SCVLANInterfaceCreatePrivate(CFAllocatorRef allocator, 962 CFStringRef vlan_if) 963{ 964 SCNetworkInterfacePrivateRef interfacePrivate; 965 966 interfacePrivate = __SCNetworkInterfaceCreatePrivate(allocator, NULL, NULL, NULL); 967 if (interfacePrivate == NULL) { 968 return NULL; 969 } 970 971 interfacePrivate->interface_type = kSCNetworkInterfaceTypeVLAN; 972 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet; 973 interfacePrivate->entity_device = CFStringCreateCopy(allocator, vlan_if); 974 interfacePrivate->address = __SCCopyMacAddress(interfacePrivate->entity_device); 975 interfacePrivate->builtin = TRUE; 976 interfacePrivate->sort_order = kSortVLAN; 977 978 interfacePrivate->localized_key = CFSTR("vlan"); 979 interfacePrivate->localized_arg1 = CFRetain(interfacePrivate->entity_device); 980 981// interfacePrivate->vlan.interface = NULL; 982// interfacePrivate->vlan.tag = NULL; 983// interfacePrivate->vlan.options = NULL; 984 985 return interfacePrivate; 986} 987 988 989#pragma mark - 990#pragma mark Interface ordering 991 992 993static CF_RETURNS_RETAINED CFArrayRef 994split_path(CFStringRef path) 995{ 996 CFArrayRef components; 997 CFMutableStringRef nPath; 998 999 // turn '@'s into '/'s 1000 nPath = CFStringCreateMutableCopy(NULL, 0, path); 1001 (void) CFStringFindAndReplace(nPath, 1002 CFSTR("@"), 1003 CFSTR("/"), 1004 CFRangeMake(0, CFStringGetLength(nPath)), 1005 0); 1006 1007 // split path into components to be compared 1008 components = CFStringCreateArrayBySeparatingStrings(NULL, nPath, CFSTR("/")); 1009 CFRelease(nPath); 1010 1011 return components; 1012} 1013 1014 1015CFComparisonResult 1016_SCNetworkInterfaceCompare(const void *val1, const void *val2, void *context) 1017{ 1018#pragma unused(context) 1019 SCNetworkInterfacePrivateRef dev1 = (SCNetworkInterfacePrivateRef)val1; 1020 SCNetworkInterfacePrivateRef dev2 = (SCNetworkInterfacePrivateRef)val2; 1021 CFComparisonResult res = kCFCompareEqualTo; 1022 1023 /* sort by interface type */ 1024 if (dev1->sort_order != dev2->sort_order) { 1025 if (dev1->sort_order < dev2->sort_order) { 1026 res = kCFCompareLessThan; 1027 } else { 1028 res = kCFCompareGreaterThan; 1029 } 1030 return (res); 1031 } 1032 1033 /* built-in interfaces sort first */ 1034 if (dev1->builtin != dev2->builtin) { 1035 if (dev1->builtin) { 1036 res = kCFCompareLessThan; 1037 } else { 1038 res = kCFCompareGreaterThan; 1039 } 1040 return (res); 1041 } 1042 1043 /* ... and then, sort built-in interfaces by "location" */ 1044 if (dev1->builtin) { 1045 if (dev1->location != dev2->location) { 1046 if (isA_CFString(dev1->location)) { 1047 if (isA_CFString(dev2->location)) { 1048 res = CFStringCompare(dev1->location, dev2->location, 0); 1049 } else { 1050 res = kCFCompareLessThan; 1051 } 1052 } else { 1053 res = kCFCompareGreaterThan; 1054 } 1055 1056 if (res != kCFCompareEqualTo) { 1057 return (res); 1058 } 1059 } 1060 } 1061 1062 /* ... and, then sort by IOPathMatch */ 1063 if ((dev1->path != NULL) && (dev2->path != NULL)) { 1064 CFArrayRef elements1; 1065 CFArrayRef elements2; 1066 CFIndex i; 1067 CFIndex n; 1068 CFIndex n1; 1069 CFIndex n2; 1070 1071 elements1 = split_path(dev1->path); 1072 n1 = CFArrayGetCount(elements1); 1073 1074 elements2 = split_path(dev2->path); 1075 n2 = CFArrayGetCount(elements2); 1076 1077 n = (n1 <= n2) ? n1 : n2; 1078 for (i = 0; i < n; i++) { 1079 CFStringRef e1; 1080 CFStringRef e2; 1081 char *end; 1082 quad_t q1; 1083 quad_t q2; 1084 char *str; 1085 Boolean isNum; 1086 1087 e1 = CFArrayGetValueAtIndex(elements1, i); 1088 e2 = CFArrayGetValueAtIndex(elements2, i); 1089 1090 str = _SC_cfstring_to_cstring(e1, NULL, 0, kCFStringEncodingUTF8); 1091 errno = 0; 1092 q1 = strtoq(str, &end, 16); 1093 isNum = ((*str != '\0') && (*end == '\0') && (errno == 0)); 1094 CFAllocatorDeallocate(NULL, str); 1095 1096 if (isNum) { 1097 // if e1 is a valid numeric string 1098 str = _SC_cfstring_to_cstring(e2, NULL, 0, kCFStringEncodingUTF8); 1099 errno = 0; 1100 q2 = strtoq(str, &end, 16); 1101 isNum = ((*str != '\0') && (*end == '\0') && (errno == 0)); 1102 CFAllocatorDeallocate(NULL, str); 1103 1104 if (isNum) { 1105 // if e2 is also a valid numeric string 1106 1107 if (q1 == q2) { 1108 res = kCFCompareEqualTo; 1109 continue; 1110 } else if (q1 < q2) { 1111 res = kCFCompareLessThan; 1112 } else { 1113 res = kCFCompareGreaterThan; 1114 } 1115 break; 1116 } 1117 } 1118 1119 res = CFStringCompare(e1, e2, 0); 1120 if (res != kCFCompareEqualTo) { 1121 break; 1122 } 1123 } 1124 1125 if (res == kCFCompareEqualTo) { 1126 if (n1 < n2) { 1127 res = kCFCompareLessThan; 1128 } else if (n1 < n2) { 1129 res = kCFCompareGreaterThan; 1130 } 1131 } 1132 1133 CFRelease(elements1); 1134 CFRelease(elements2); 1135 1136 if (res != kCFCompareEqualTo) { 1137 return (res); 1138 } 1139 } 1140 1141 /* ... and, then sort by BSD interface name */ 1142 if ((dev1->entity_device != NULL) && (dev2->entity_device != NULL)) { 1143 res = CFStringCompare(dev1->entity_device, dev2->entity_device, 0); 1144 if (res != kCFCompareEqualTo) { 1145 return (res); 1146 } 1147 } 1148 1149 /* ... and lastly, sort by BSD interface unique identifier */ 1150 if ((dev1->entity_device_unique != NULL) && (dev2->entity_device_unique != NULL)) { 1151 res = CFStringCompare(dev1->entity_device_unique, dev2->entity_device_unique, 0); 1152// if (res != kCFCompareEqualTo) { 1153// return (res); 1154// } 1155 } 1156 1157 return res; 1158} 1159 1160 1161static void 1162sort_interfaces(CFMutableArrayRef all_interfaces) 1163{ 1164 CFIndex n; 1165 1166 n = CFArrayGetCount(all_interfaces); 1167 if (n < 2) { 1168 return; 1169 } 1170 1171 CFArraySortValues(all_interfaces, CFRangeMake(0, n), _SCNetworkInterfaceCompare, NULL); 1172 return; 1173} 1174 1175 1176__private_extern__ 1177int 1178__SCNetworkInterfaceOrder(SCNetworkInterfaceRef interface) 1179{ 1180 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 1181 1182 return interfacePrivate->sort_order; 1183} 1184 1185 1186#pragma mark - 1187#pragma mark Interface details 1188 1189 1190static CFStringRef 1191IOCopyCFStringValue(CFTypeRef ioVal) 1192{ 1193 if (isA_CFString(ioVal)) { 1194 return CFStringCreateCopy(NULL, ioVal); 1195 } 1196 1197 if (isA_CFData(ioVal)) { 1198 return CFStringCreateWithCString(NULL, 1199 (const char *)CFDataGetBytePtr(ioVal), 1200 kCFStringEncodingUTF8); 1201 } 1202 1203 return NULL; 1204} 1205 1206 1207static CFStringRef 1208IODictionaryCopyBSDName(CFDictionaryRef io_dict) 1209{ 1210 CFStringRef if_bsdName; 1211 CFStringRef if_prefix; 1212 CFNumberRef if_unit; 1213 1214 if_bsdName = CFDictionaryGetValue(io_dict, CFSTR(kIOBSDNameKey)); 1215 if (if_bsdName != NULL) { 1216 return IOCopyCFStringValue(if_bsdName); 1217 } 1218 1219 // no BSD name, get interface prefix and unit 1220 if_prefix = CFDictionaryGetValue(io_dict, CFSTR(kIOInterfaceNamePrefix)); 1221 if_unit = CFDictionaryGetValue(io_dict, CFSTR(kIOInterfaceUnit)); 1222 if (isA_CFString(if_prefix) && isA_CFNumber(if_unit)) { 1223 // if both prefix and unit available, construct BSD name 1224 if_bsdName = CFStringCreateWithFormat(NULL, 1225 NULL, 1226 CFSTR("%@%@"), 1227 if_prefix, 1228 if_unit); 1229 } 1230 1231 return if_bsdName; 1232}; 1233 1234 1235static CFStringRef 1236IODictionaryCopyCFStringValue(CFDictionaryRef io_dict, CFStringRef io_key) 1237{ 1238 CFTypeRef ioVal; 1239 1240 ioVal = CFDictionaryGetValue(io_dict, io_key); 1241 return IOCopyCFStringValue(ioVal); 1242} 1243 1244 1245static Boolean 1246IOStringValueHasPrefix(CFTypeRef ioVal, CFStringRef prefix) 1247{ 1248 Boolean match = FALSE; 1249 CFIndex prefixLen = CFStringGetLength(prefix); 1250 CFStringRef str = NULL; 1251 1252 if (!isA_CFString(ioVal)) { 1253 if (isA_CFData(ioVal)) { 1254 str = CFStringCreateWithCStringNoCopy(NULL, 1255 (const char *)CFDataGetBytePtr(ioVal), 1256 kCFStringEncodingUTF8, 1257 kCFAllocatorNull); 1258 ioVal = str; 1259 } else { 1260 return FALSE; 1261 } 1262 } 1263 1264 if ((ioVal != NULL) && 1265 (CFStringGetLength(ioVal) >= prefixLen) && 1266 (CFStringCompareWithOptions(ioVal, 1267 prefix, 1268 CFRangeMake(0, prefixLen), 1269 kCFCompareCaseInsensitive) == kCFCompareEqualTo)) { 1270 match = TRUE; 1271 } 1272 1273 if (str != NULL) CFRelease(str); 1274 return match; 1275} 1276 1277 1278static const struct { 1279 const CFStringRef name; 1280 const CFStringRef slot; 1281} slot_mappings[] = { 1282 // Beige G3 1283 { CFSTR("A1") , CFSTR("1") }, 1284 { CFSTR("B1") , CFSTR("2") }, 1285 { CFSTR("C1") , CFSTR("3") }, 1286 1287 // Blue&White G3, Yikes G4 1288 { CFSTR("J12"), CFSTR("1") }, 1289 { CFSTR("J11"), CFSTR("2") }, 1290 { CFSTR("J10"), CFSTR("3") }, 1291 { CFSTR("J9"), CFSTR("4") }, 1292 1293 // AGP G4 1294 { CFSTR("A") , CFSTR("1") }, 1295 { CFSTR("B") , CFSTR("2") }, 1296 { CFSTR("C") , CFSTR("3") }, 1297 { CFSTR("D") , CFSTR("4") }, 1298 1299 // Digital Audio G4 (and later models) 1300 { CFSTR("1") , CFSTR("1") }, 1301 { CFSTR("2") , CFSTR("2") }, 1302 { CFSTR("3") , CFSTR("3") }, 1303 { CFSTR("4") , CFSTR("4") }, 1304 { CFSTR("5") , CFSTR("5") } 1305}; 1306 1307 1308static const CFStringRef slot_prefixes[] = { 1309 CFSTR("thunderbolt slot "), 1310 CFSTR("pci slot "), 1311 CFSTR("slot-"), 1312}; 1313 1314 1315static CF_RETURNS_RETAINED CFStringRef 1316pci_slot(io_registry_entry_t interface, CFTypeRef *pci_slot_name) 1317{ 1318 kern_return_t kr; 1319 io_registry_entry_t parent; 1320 CFMutableStringRef slot; 1321 CFTypeRef slot_name; 1322 1323 slot = NULL; 1324 if (pci_slot_name != NULL) *pci_slot_name = NULL; 1325 1326 slot_name = IORegistryEntryCreateCFProperty(interface, CFSTR("AAPL,slot-name"), NULL, 0); 1327 if (slot_name != NULL) { 1328 slot = CFStringCreateMutable(NULL, 0); 1329 if (isA_CFString(slot_name)) { 1330 if (pci_slot_name != NULL) *pci_slot_name = CFStringCreateCopy(NULL, slot_name); 1331 CFStringAppend(slot, slot_name); 1332 } else if (isA_CFData(slot_name)) { 1333 if (pci_slot_name != NULL) *pci_slot_name = CFDataCreateCopy(NULL, slot_name); 1334 CFStringAppendCString(slot, 1335 (const char *)CFDataGetBytePtr(slot_name), 1336 kCFStringEncodingUTF8); 1337 } 1338 1339 for (size_t i = 0; i < sizeof(slot_prefixes)/sizeof(slot_prefixes[0]); i++) { 1340 CFIndex len; 1341 1342 len = CFStringGetLength(slot_prefixes[i]); 1343 if (CFStringGetLength(slot) > len) { 1344 (void) CFStringFindAndReplace(slot, 1345 slot_prefixes[i], 1346 CFSTR(""), 1347 CFRangeMake(0, len), 1348 kCFCompareCaseInsensitive|kCFCompareAnchored); 1349 } 1350 } 1351 1352 for (size_t i = 0; i < sizeof(slot_mappings)/sizeof(slot_mappings[0]); i++) { 1353 if (CFStringCompare(slot, 1354 slot_mappings[i].name, 1355 kCFCompareCaseInsensitive) == kCFCompareEqualTo) { 1356 CFRelease(slot); 1357 slot = (CFMutableStringRef)CFRetain(slot_mappings[i].slot); 1358 break; 1359 } 1360 } 1361 1362 CFRelease(slot_name); 1363 } 1364 1365 kr = IORegistryEntryGetParentEntry(interface, kIOServicePlane, &parent); 1366 switch (kr) { 1367 case kIOReturnSuccess : { 1368 CFTypeRef parent_pci_slot_name = NULL; 1369 CFStringRef parent_slot; 1370 1371 parent_slot = pci_slot(parent, &parent_pci_slot_name); 1372 if (parent_slot != NULL) { 1373 if (slot != NULL) CFRelease(slot); 1374 slot = (CFMutableStringRef)parent_slot; 1375 1376 if (pci_slot_name != NULL) { 1377 if (*pci_slot_name != NULL) CFRelease(*pci_slot_name); 1378 *pci_slot_name = parent_pci_slot_name; 1379 } else { 1380 if (parent_pci_slot_name != NULL) CFRelease(parent_pci_slot_name); 1381 } 1382 } 1383 1384 IOObjectRelease(parent); 1385 break; 1386 } 1387 case kIOReturnNoDevice : 1388 // if we have hit the root node 1389 break; 1390 default : 1391 SC_log(LOG_INFO, "IORegistryEntryGetParentEntry() failed, kr = 0x%x", kr); 1392 break; 1393 } 1394 1395 return slot; 1396} 1397 1398 1399static CFComparisonResult 1400compare_bsdNames(const void *val1, const void *val2, void *context) 1401{ 1402#pragma unused(context) 1403 CFStringRef bsd1 = (CFStringRef)val1; 1404 CFStringRef bsd2 = (CFStringRef)val2; 1405 1406 return CFStringCompare(bsd1, bsd2, 0); 1407} 1408 1409 1410static CF_RETURNS_RETAINED CFStringRef 1411pci_port(CFTypeRef slot_name, int ift, CFStringRef bsdName) 1412{ 1413 CFIndex n; 1414 CFStringRef port_name = NULL; 1415 CFMutableArrayRef port_names; 1416 1417 kern_return_t kr; 1418 CFStringRef match_keys[2]; 1419 CFTypeRef match_vals[2]; 1420 CFDictionaryRef match_dict; 1421 CFDictionaryRef matching; 1422 io_registry_entry_t slot; 1423 io_iterator_t slot_iterator = MACH_PORT_NULL; 1424 1425 match_keys[0] = CFSTR("AAPL,slot-name"); 1426 match_vals[0] = slot_name; 1427 1428 match_dict = CFDictionaryCreate(NULL, 1429 (const void **)match_keys, 1430 (const void **)match_vals, 1431 1, 1432 &kCFTypeDictionaryKeyCallBacks, 1433 &kCFTypeDictionaryValueCallBacks); 1434 1435 match_keys[0] = CFSTR(kIOProviderClassKey); 1436 match_vals[0] = CFSTR("IOPCIDevice"); 1437 1438 match_keys[1] = CFSTR(kIOPropertyMatchKey); 1439 match_vals[1] = match_dict; 1440 1441 // note: the "matching" dictionary will be consumed by the following 1442 matching = CFDictionaryCreate(NULL, 1443 (const void **)match_keys, 1444 (const void **)match_vals, 1445 sizeof(match_keys)/sizeof(match_keys[0]), 1446 &kCFTypeDictionaryKeyCallBacks, 1447 &kCFTypeDictionaryValueCallBacks); 1448 CFRelease(match_dict); 1449 1450 kr = IOServiceGetMatchingServices(masterPort, matching, &slot_iterator); 1451 if (kr != kIOReturnSuccess) { 1452 SC_log(LOG_INFO, "IOServiceGetMatchingServices() failed, kr = 0x%x", kr); 1453 return MACH_PORT_NULL; 1454 } 1455 1456 port_names = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 1457 1458 while ((slot = IOIteratorNext(slot_iterator)) != MACH_PORT_NULL) { 1459 io_registry_entry_t child; 1460 io_iterator_t child_iterator = MACH_PORT_NULL; 1461 1462 kr = IORegistryEntryCreateIterator(slot, 1463 kIOServicePlane, 1464 kIORegistryIterateRecursively, 1465 &child_iterator); 1466 if (kr != kIOReturnSuccess) { 1467 SC_log(LOG_INFO, "IORegistryEntryCreateIterator() failed, kr = 0x%x", kr); 1468 CFRelease(port_names); 1469 return MACH_PORT_NULL; 1470 } 1471 1472 while ((child = IOIteratorNext(child_iterator)) != MACH_PORT_NULL) { 1473 if (IOObjectConformsTo(child, kIONetworkInterfaceClass)) { 1474 CFMutableDictionaryRef interface_dict = NULL; 1475 1476 (void) IORegistryEntryCreateCFProperties(child, &interface_dict, NULL, kNilOptions); 1477 if (interface_dict != NULL) { 1478 CFNumberRef child_if_type; 1479 int child_ift = ift; 1480 1481 child_if_type = CFDictionaryGetValue(interface_dict, CFSTR(kIOInterfaceType)); 1482 if (child_if_type != NULL) { 1483 if (!isA_CFNumber(child_if_type) || 1484 !CFNumberGetValue(child_if_type, kCFNumberIntType, &child_ift)) { 1485 // assume that it's a match 1486 child_ift = ift; 1487 } 1488 } 1489 1490 if (ift == child_ift) { 1491 CFStringRef if_bsdName; 1492 1493 if_bsdName = IODictionaryCopyBSDName(interface_dict); 1494 if (if_bsdName != NULL) { 1495 CFArrayAppendValue(port_names, if_bsdName); 1496 CFRelease(if_bsdName); 1497 } 1498 } 1499 1500 CFRelease(interface_dict); 1501 } 1502 } 1503 IOObjectRelease(child); 1504 } 1505 IOObjectRelease(child_iterator); 1506 IOObjectRelease(slot); 1507 } 1508 IOObjectRelease(slot_iterator); 1509 1510 n = CFArrayGetCount(port_names); 1511 if (n > 1) { 1512 CFArraySortValues(port_names, CFRangeMake(0, n), compare_bsdNames, NULL); 1513 n = CFArrayGetFirstIndexOfValue(port_names, CFRangeMake(0, n), bsdName); 1514 if (n != kCFNotFound) { 1515 port_name = CFStringCreateWithFormat(NULL, NULL, CFSTR("%ld"), n + 1); 1516 } 1517 } 1518 1519 CFRelease(port_names); 1520 return port_name; 1521} 1522 1523 1524static Boolean 1525pci_slot_info(io_registry_entry_t interface, int ift, CFStringRef *slot_name, CFStringRef *port_name) 1526{ 1527 CFStringRef bsd_name = NULL; 1528 CFMutableDictionaryRef interface_dict = NULL; 1529 Boolean ok = FALSE; 1530 CFTypeRef pci_slot_name; 1531 1532 *slot_name = NULL; 1533 *port_name = NULL; 1534 1535 (void) IORegistryEntryCreateCFProperties(interface, &interface_dict, NULL, kNilOptions); 1536 if (interface_dict != NULL) { 1537 bsd_name = IODictionaryCopyBSDName(interface_dict); 1538 CFRelease(interface_dict); 1539 } 1540 1541 if (bsd_name == NULL) { 1542 return FALSE; 1543 } 1544 1545 *slot_name = pci_slot(interface, &pci_slot_name); 1546 if (*slot_name != NULL) { 1547 if (pci_slot_name != NULL) { 1548 *port_name = pci_port(pci_slot_name, ift, bsd_name); 1549 CFRelease(pci_slot_name); 1550 } 1551 ok = TRUE; 1552 } 1553 1554 CFRelease(bsd_name); 1555 return ok; 1556} 1557 1558 1559static Boolean 1560isBuiltin(io_registry_entry_t interface) 1561{ 1562 CFStringRef slot; 1563 1564 slot = pci_slot(interface, NULL); 1565 if (slot != NULL) { 1566 // interfaces which have a "slot" are not built-in 1567 CFRelease(slot); 1568 return FALSE; 1569 } 1570 1571 return TRUE; 1572} 1573 1574 1575static Boolean 1576isBluetoothBuiltin(Boolean *haveController) 1577{ 1578 Boolean builtin = FALSE; 1579 io_object_t hciController; 1580 io_iterator_t iter = MACH_PORT_NULL; 1581 kern_return_t kr; 1582 1583 kr = IOServiceGetMatchingServices(masterPort, 1584 IOServiceMatching("IOBluetoothHCIController"), 1585 &iter); 1586 if ((kr != kIOReturnSuccess) || (iter == MACH_PORT_NULL)) { 1587 if (kr != kIOReturnSuccess) { 1588 SC_log(LOG_INFO, "IOServiceGetMatchingServices() failed, kr = 0x%x", kr); 1589 } 1590 *haveController = FALSE; 1591 return FALSE; 1592 } 1593 *haveController = TRUE; 1594 1595 hciController = IOIteratorNext(iter); 1596 IOObjectRelease(iter); 1597 if(hciController != MACH_PORT_NULL) { 1598#if !TARGET_OS_SIMULATOR 1599 CFNumberRef idVendor; 1600 1601 idVendor = IORegistryEntryCreateCFProperty(hciController, CFSTR(kUSBVendorID), NULL, 0); 1602 if (idVendor != NULL) { 1603 int idVendorVal; 1604 1605 if (isA_CFNumber(idVendor) && 1606 CFNumberGetValue(idVendor, kCFNumberIntType, &idVendorVal) && 1607 (idVendorVal == kIOUSBVendorIDAppleComputer)) { 1608 builtin = TRUE; 1609 } 1610 1611 CFRelease(idVendor); 1612 } 1613#endif // !TARGET_OS_SIMULATOR 1614 1615 IOObjectRelease(hciController); 1616 } 1617 1618 return builtin; 1619} 1620 1621 1622static Boolean 1623isThunderbolt(io_registry_entry_t interface) 1624{ 1625 CFTypeRef val; 1626 1627 val = IORegistryEntrySearchCFProperty(interface, 1628 kIOServicePlane, 1629 CFSTR(kPCIThunderboltString), 1630 NULL, 1631 kIORegistryIterateRecursively | kIORegistryIterateParents); 1632 if (val != NULL) { 1633 CFRelease(val); 1634 return TRUE; 1635 } 1636 1637 return FALSE; 1638} 1639 1640 1641static void 1642processUSBInterface(SCNetworkInterfacePrivateRef interfacePrivate, 1643 io_registry_entry_t interface, 1644 CFDictionaryRef interface_dict, 1645 io_registry_entry_t controller, 1646 CFDictionaryRef controller_dict, 1647 io_registry_entry_t bus, 1648 CFDictionaryRef bus_dict) 1649{ 1650#if TARGET_OS_SIMULATOR 1651#pragma unused(interfacePrivate) 1652#pragma unused(interface) 1653#endif // TARGET_OS_SIMULATOR 1654#pragma unused(interface_dict) 1655#pragma unused(controller) 1656#pragma unused(controller_dict) 1657#pragma unused(bus) 1658#pragma unused(bus_dict) 1659#if !TARGET_OS_SIMULATOR 1660 // capture USB info 1661 if (interfacePrivate->usb.name == NULL) { 1662 interfacePrivate->usb.name = IORegistryEntrySearchCFProperty(interface, 1663 kIOServicePlane, 1664 CFSTR(kUSBProductString), 1665 NULL, 1666 kIORegistryIterateRecursively | kIORegistryIterateParents); 1667 } 1668 if (interfacePrivate->usb.vid == NULL) { 1669 interfacePrivate->usb.vid = IORegistryEntrySearchCFProperty(interface, 1670 kIOServicePlane, 1671 CFSTR(kUSBVendorID), 1672 NULL, 1673 kIORegistryIterateRecursively | kIORegistryIterateParents); 1674 } 1675 if (interfacePrivate->usb.pid == NULL) { 1676 interfacePrivate->usb.pid = IORegistryEntrySearchCFProperty(interface, 1677 kIOServicePlane, 1678 CFSTR(kUSBProductID), 1679 NULL, 1680 kIORegistryIterateRecursively | kIORegistryIterateParents); 1681 } 1682#endif // !TARGET_OS_SIMULATOR 1683 1684 return; 1685} 1686 1687 1688static Boolean 1689update_interface_name(SCNetworkInterfacePrivateRef interfacePrivate, 1690 io_registry_entry_t interface, 1691 Boolean useUSBInfo) 1692{ 1693 Boolean updated = FALSE; 1694 CFTypeRef val; 1695 1696 // check if a "Product Name" has been provided 1697 val = IORegistryEntrySearchCFProperty(interface, 1698 kIOServicePlane, 1699 CFSTR(kIOPropertyProductNameKey), 1700 NULL, 1701 kIORegistryIterateRecursively | kIORegistryIterateParents); 1702 if ((val == NULL) && useUSBInfo && (interfacePrivate->usb.name != NULL)) { 1703 // else, use "USB Product Name" if available 1704 val = CFRetain(interfacePrivate->usb.name); 1705 } 1706 if (val != NULL) { 1707 CFStringRef productName; 1708 1709 productName = IOCopyCFStringValue(val); 1710 CFRelease(val); 1711 1712 if (productName != NULL) { 1713 if (CFStringGetLength(productName) > 0) { 1714 // if we have a [somewhat reasonable?] product name 1715 if (interfacePrivate->name != NULL) { 1716 CFRelease(interfacePrivate->name); 1717 } 1718 interfacePrivate->name = CFRetain(productName); 1719 if (interfacePrivate->localized_name != NULL) { 1720 CFRelease(interfacePrivate->localized_name); 1721 interfacePrivate->localized_name = NULL; 1722 } 1723 if (bundle != NULL) { 1724 interfacePrivate->localized_name = copy_interface_string(bundle, productName, TRUE); 1725 } 1726 1727 updated = TRUE; 1728 } 1729 1730 CFRelease(productName); 1731 } 1732 } 1733 1734 return updated; 1735} 1736 1737 1738#pragma mark - 1739#pragma mark Interface enumeration 1740 1741 1742typedef Boolean (*processInterface)(SCNetworkInterfacePrivateRef interfacePrivate, 1743 io_registry_entry_t interface, 1744 CFDictionaryRef interface_dict, 1745 io_registry_entry_t controller, 1746 CFDictionaryRef controller_dict, 1747 io_registry_entry_t bus, 1748 CFDictionaryRef bus_dict); 1749 1750 1751static void 1752merge_override(SCNetworkInterfacePrivateRef interfacePrivate, 1753 io_registry_entry_t interface, 1754 CFStringRef override) 1755{ 1756 CFStringRef key; 1757 CFTypeRef val; 1758 1759 key = CFStringCreateWithFormat(NULL, NULL, CFSTR("Device%@Overrides"), override); 1760 val = IORegistryEntrySearchCFProperty(interface, 1761 kIOServicePlane, 1762 key, 1763 NULL, 1764 kIORegistryIterateRecursively | kIORegistryIterateParents); 1765 CFRelease(key); 1766 if (val != NULL) { 1767 if (isA_CFDictionary(val)) { 1768 if (interfacePrivate->overrides == NULL) { 1769 interfacePrivate->overrides = CFDictionaryCreateMutable(NULL, 1770 0, 1771 &kCFTypeDictionaryKeyCallBacks, 1772 &kCFTypeDictionaryValueCallBacks); 1773 } 1774 CFDictionarySetValue(interfacePrivate->overrides, override, val); 1775 } 1776 CFRelease(val); 1777 } 1778 1779 return; 1780} 1781 1782 1783static Boolean 1784processNetworkInterface(SCNetworkInterfacePrivateRef interfacePrivate, 1785 io_registry_entry_t interface, 1786 CFDictionaryRef interface_dict, 1787 io_registry_entry_t controller, 1788 CFDictionaryRef controller_dict, 1789 io_registry_entry_t bus, 1790 CFDictionaryRef bus_dict) 1791{ 1792 CFDataRef data; 1793 int ift = -1; 1794 int iVal; 1795 CFNumberRef num; 1796 CFStringRef str; 1797 CFBooleanRef val; 1798 1799 // interface type 1800 num = CFDictionaryGetValue(interface_dict, CFSTR(kIOInterfaceType)); 1801 if (isA_CFNumber(num) && 1802 CFNumberGetValue(num, kCFNumberIntType, &ift)) { 1803 interfacePrivate->type = CFRetain(num); 1804 } else { 1805 SC_log(LOG_INFO, "no interface type: %@", interface_dict); 1806 return FALSE; 1807 } 1808 1809 switch (ift) { 1810 case IFT_ETHER : 1811 // Type, Hardware 1812 1813 if (IOObjectConformsTo(controller, "IO80211Controller") || 1814 IOObjectConformsTo(controller, "AirPortPCI" ) || 1815 IOObjectConformsTo(controller, "AirPortDriver" )) { 1816 interfacePrivate->interface_type = kSCNetworkInterfaceTypeIEEE80211; 1817 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet; 1818 interfacePrivate->sort_order = kSortAirPort; 1819 } else if (IOObjectConformsTo(controller, "AppleThunderboltIPPort")) { 1820 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet; 1821 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet; 1822 interfacePrivate->sort_order = kSortThunderbolt; 1823 } else if (IOObjectConformsTo(controller, "IOBluetoothBNEPDriver")) { 1824 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet; 1825 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet; 1826 interfacePrivate->sort_order = kSortBluetoothPAN_GN; 1827 } else if (IOObjectConformsTo(controller, "AppleUSBEthernetHost")) { 1828 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet; 1829 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet; 1830 interfacePrivate->sort_order = kSortTethered; 1831 } else if (IOObjectConformsTo(controller, "AppleUSBCDCECMData")) { 1832 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet; 1833 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet; 1834 interfacePrivate->sort_order = kSortWWANEthernet; 1835 } 1836 1837 if (interfacePrivate->interface_type == NULL) { 1838 val = IORegistryEntrySearchCFProperty(interface, 1839 kIOServicePlane, 1840 CFSTR(kIOUserEthernetInterfaceRoleKey), 1841 NULL, 1842 kIORegistryIterateRecursively | kIORegistryIterateParents); 1843 if (val != NULL) { 1844 if (isA_CFString(val)) { 1845 if (CFEqual(val, CFSTR(BT_PAN_NAME))) { 1846 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet; 1847 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet; 1848 interfacePrivate->sort_order = kSortBluetoothPAN_GN; 1849 } else if (CFEqual(val, CFSTR("Bluetooth PAN-NAP"))) { 1850 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet; 1851 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet; 1852 interfacePrivate->sort_order = kSortBluetoothPAN_NAP; 1853 } else if (CFEqual(val, CFSTR("Bluetooth P2P"))) { 1854 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet; 1855 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet; 1856 interfacePrivate->sort_order = kSortBluetoothPAN_U; 1857 } else if (CFEqual(val, CFSTR("CarPlay"))) { 1858 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet; 1859 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet; 1860 interfacePrivate->sort_order = kSortCarPlay; 1861 } 1862 } 1863 1864 CFRelease(val); 1865 } 1866 } 1867 1868#if TARGET_OS_OSX 1869 if (interfacePrivate->interface_type == NULL) { 1870 val = IORegistryEntrySearchCFProperty(interface, 1871 kIOServicePlane, 1872 CFSTR(kUSBSupportsIPhoneOS), 1873 NULL, 1874 kIORegistryIterateRecursively | kIORegistryIterateParents); 1875 if (val != NULL) { 1876 if (isA_CFBoolean(val) && CFBooleanGetValue(val)) { 1877 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet; 1878 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet; 1879 interfacePrivate->sort_order = kSortTethered; 1880 } 1881 1882 CFRelease(val); 1883 } 1884 } 1885#endif // TARGET_OS_OSX 1886 1887 if (interfacePrivate->interface_type == NULL) { 1888 str = IODictionaryCopyCFStringValue(bus_dict, CFSTR("name")); 1889 if (str != NULL) { 1890 if (CFEqual(str, CFSTR("radio"))) { 1891 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet; // ?? 1892 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet; 1893 interfacePrivate->sort_order = kSortOtherWireless; 1894 } 1895 1896 CFRelease(str); 1897 } 1898 } 1899 1900 if (interfacePrivate->interface_type == NULL) { 1901 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet; 1902 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet; 1903 interfacePrivate->sort_order = kSortEthernet; 1904 1905 // BOND support only enabled for ethernet devices 1906 interfacePrivate->supportsBond = TRUE; 1907 } 1908 1909 // enable Bridge support 1910 interfacePrivate->supportsBridge = TRUE; 1911 1912 // built-in 1913 val = isA_CFBoolean(CFDictionaryGetValue(interface_dict, CFSTR(kIOBuiltin))); 1914 if (val == NULL) { 1915 val = isA_CFBoolean(CFDictionaryGetValue(interface_dict, CFSTR(kIOPrimaryInterface))); 1916 } 1917 if (val != NULL) { 1918 interfacePrivate->builtin = CFBooleanGetValue(val); 1919 } else { 1920 interfacePrivate->builtin = isBuiltin(interface); 1921 } 1922 1923 if (!interfacePrivate->builtin && 1924 CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeIEEE80211)) { 1925 // always treat AirPort interfaces as built-in 1926 interfacePrivate->builtin = TRUE; 1927 } 1928 1929 // location 1930 interfacePrivate->location = IODictionaryCopyCFStringValue(interface_dict, CFSTR(kIOLocation)); 1931 if ((interfacePrivate->location != NULL) && 1932 (CFStringGetLength(interfacePrivate->location) == 0)) { 1933 CFRelease(interfacePrivate->location); 1934 interfacePrivate->location = NULL; 1935 } 1936 1937 // VLAN support 1938 num = CFDictionaryGetValue(controller_dict, CFSTR(kIOFeatures)); 1939 if (isA_CFNumber(num) && 1940 CFNumberGetValue(num, kCFNumberIntType, & iVal)) { 1941 if (iVal & (kIONetworkFeatureHardwareVlan | kIONetworkFeatureSoftwareVlan)) { 1942 interfacePrivate->supportsVLAN = TRUE; 1943 } 1944 } 1945 1946 // localized name 1947 if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeIEEE80211)) { 1948 interfacePrivate->localized_key = CFSTR("airport"); 1949 } else if (interfacePrivate->sort_order == kSortThunderbolt) { 1950 if ((interfacePrivate->location == NULL) || 1951 (CFStringGetLength(interfacePrivate->location) == 0)) { 1952 interfacePrivate->localized_key = CFSTR("thunderbolt"); 1953 } else { 1954 interfacePrivate->localized_key = CFSTR("multithunderbolt"); 1955 interfacePrivate->localized_arg1 = CFRetain(interfacePrivate->location); 1956 } 1957 } else if (interfacePrivate->sort_order == kSortBluetoothPAN_GN) { 1958 interfacePrivate->localized_key = CFSTR("bluetooth-pan-gn"); 1959 } else if (interfacePrivate->sort_order == kSortBluetoothPAN_NAP) { 1960 interfacePrivate->localized_key = CFSTR("bluetooth-pan-nap"); 1961 } else if (interfacePrivate->sort_order == kSortBluetoothPAN_U) { 1962 interfacePrivate->localized_key = CFSTR("bluetooth-pan-u"); 1963 } else if (interfacePrivate->sort_order == kSortOtherWireless) { 1964 interfacePrivate->localized_key = CFSTR("wireless"); 1965 interfacePrivate->localized_arg1 = CFRetain(CFSTR("")); // ?? 1966 } else if (interfacePrivate->builtin) { 1967 if ((interfacePrivate->location == NULL) || 1968 (CFStringGetLength(interfacePrivate->location) == 0)) { 1969 interfacePrivate->localized_key = CFSTR("ether"); 1970 } else { 1971 interfacePrivate->localized_key = CFSTR("multiether"); 1972 interfacePrivate->localized_arg1 = CFRetain(interfacePrivate->location); 1973 } 1974 } else { 1975 CFStringRef provider; 1976 1977 // check provider class 1978 provider = IORegistryEntrySearchCFProperty(interface, 1979 kIOServicePlane, 1980 CFSTR(kIOProviderClassKey), 1981 NULL, 1982 kIORegistryIterateRecursively | kIORegistryIterateParents); 1983 if (provider != NULL) { 1984 if (CFEqual(provider, CFSTR("IOPCIDevice"))) { 1985 CFStringRef port_name; 1986 CFStringRef slot_name; 1987 1988 // set interface "name" 1989 if (!update_interface_name(interfacePrivate, interface, FALSE) && 1990 pci_slot_info(interface, ift, &slot_name, &port_name)) { 1991 if (isThunderbolt(interface)) { 1992 if (port_name == NULL) { 1993 interfacePrivate->localized_key = CFSTR("thunderbolt-ether"); 1994 interfacePrivate->localized_arg1 = slot_name; 1995 } else { 1996 interfacePrivate->localized_key = CFSTR("thunderbolt-multiether"); 1997 interfacePrivate->localized_arg1 = slot_name; 1998 interfacePrivate->localized_arg2 = port_name; 1999 } 2000 2001 } else { 2002 if (port_name == NULL) { 2003 interfacePrivate->localized_key = CFSTR("pci-ether"); 2004 interfacePrivate->localized_arg1 = slot_name; 2005 } else { 2006 interfacePrivate->localized_key = CFSTR("pci-multiether"); 2007 interfacePrivate->localized_arg1 = slot_name; 2008 interfacePrivate->localized_arg2 = port_name; 2009 } 2010 } 2011 } 2012 } else { 2013 io_registry_entry_t node = interface; 2014 2015 while (provider != NULL) { 2016#if !TARGET_OS_SIMULATOR 2017 if (CFEqual(provider, CFSTR(kIOUSBDeviceClassName)) || 2018 CFEqual(provider, CFSTR(kIOUSBInterfaceClassName)) || 2019 CFEqual(provider, CFSTR(kIOUSBHostInterfaceClassName))) { 2020 // get USB info (if available) 2021 processUSBInterface(interfacePrivate, 2022 interface, 2023 interface_dict, 2024 controller, 2025 controller_dict, 2026 bus, 2027 bus_dict); 2028 2029 // set interface "name" 2030 if (!update_interface_name(interfacePrivate, interface, TRUE)) { 2031 interfacePrivate->localized_key = CFSTR("usb-ether"); 2032 interfacePrivate->localized_arg1 = IODictionaryCopyBSDName(interface_dict); 2033 } 2034 break; 2035 } 2036#endif // !TARGET_OS_SIMULATOR 2037 2038 if (node == interface) { 2039 node = controller; 2040 } else if (node == controller ) { 2041 node = bus; 2042 } else { 2043 break; 2044 } 2045 2046 CFRelease(provider); 2047 provider = IORegistryEntrySearchCFProperty(node, 2048 kIOServicePlane, 2049 CFSTR(kIOProviderClassKey), 2050 NULL, 2051 kIORegistryIterateRecursively | kIORegistryIterateParents); 2052 } 2053 2054 if (interfacePrivate->localized_key == NULL) { 2055 update_interface_name(interfacePrivate, interface, FALSE); 2056 } 2057 } 2058 2059 if (provider != NULL) CFRelease(provider); 2060 } 2061 2062 if (interfacePrivate->localized_key == NULL) { 2063 // if no provider, not a PCI device, or no slot information 2064 interfacePrivate->localized_key = CFSTR("generic-ether"); 2065 interfacePrivate->localized_arg1 = IODictionaryCopyBSDName(interface_dict); 2066 } 2067 } 2068 2069 break; 2070 case IFT_IEEE1394 : 2071 // Type 2072 interfacePrivate->interface_type = kSCNetworkInterfaceTypeFireWire; 2073 2074 // Entity 2075 interfacePrivate->entity_type = kSCValNetInterfaceTypeFireWire; 2076 2077 // built-in 2078 interfacePrivate->builtin = isBuiltin(interface); 2079 2080 // sort order 2081 interfacePrivate->sort_order = kSortFireWire; 2082 2083 // localized name 2084 if (interfacePrivate->builtin) { 2085 interfacePrivate->localized_key = CFSTR("firewire"); 2086 } else { 2087 CFStringRef port_name; 2088 CFStringRef slot_name; 2089 2090 // set interface "name" 2091 if (!update_interface_name(interfacePrivate, interface, FALSE) && 2092 pci_slot_info(interface, ift, &slot_name, &port_name)) { 2093 if (isThunderbolt(interface)) { 2094 if (port_name == NULL) { 2095 interfacePrivate->localized_key = CFSTR("thunderbolt-firewire"); 2096 interfacePrivate->localized_arg1 = slot_name; 2097 } else { 2098 interfacePrivate->localized_key = CFSTR("thunderbolt-multifirewire"); 2099 interfacePrivate->localized_arg1 = slot_name; 2100 interfacePrivate->localized_arg2 = port_name; 2101 } 2102 } else { 2103 if (port_name == NULL) { 2104 interfacePrivate->localized_key = CFSTR("pci-firewire"); 2105 interfacePrivate->localized_arg1 = slot_name; 2106 } else { 2107 interfacePrivate->localized_key = CFSTR("pci-multifirewire"); 2108 interfacePrivate->localized_arg1 = slot_name; 2109 interfacePrivate->localized_arg2 = port_name; 2110 } 2111 } 2112 } 2113 } 2114 2115 break; 2116 default : 2117 SC_log(LOG_INFO, "unknown interface type = %d", ift); 2118 return FALSE; 2119 } 2120 2121 // Device 2122 interfacePrivate->entity_device = IODictionaryCopyBSDName(interface_dict); 2123 2124 // Hardware (MAC) address 2125 data = CFDictionaryGetValue(controller_dict, CFSTR(kIOMACAddress)); 2126 if (isA_CFData(data)) { 2127 interfacePrivate->address = CFRetain(data); 2128 } 2129 2130 // interface prefix 2131 str = CFDictionaryGetValue(interface_dict, CFSTR(kIOInterfaceNamePrefix)); 2132 if (isA_CFString(str)) { 2133 interfacePrivate->prefix = CFRetain(str); 2134 } 2135 2136 // interface unit 2137 num = CFDictionaryGetValue(interface_dict, CFSTR(kIOInterfaceUnit)); 2138 if (isA_CFNumber(num) && 2139 CFNumberGetValue(num, kCFNumberIntType, & iVal)) { 2140 interfacePrivate->unit = CFRetain(num); 2141 } 2142 2143 // configuration [PPP] template override (now deprecated, use NetworkConfigurationOverrides) 2144 merge_override(interfacePrivate, interface, kSCNetworkInterfaceTypePPP); 2145 2146 return TRUE; 2147} 2148 2149 2150static void 2151set_connection_script(SCNetworkInterfacePrivateRef interfacePrivate, CFStringRef script) 2152{ 2153 CFDictionaryRef dict; 2154 CFMutableDictionaryRef newDict; 2155 2156 if (interfacePrivate->overrides == NULL) { 2157 interfacePrivate->overrides = CFDictionaryCreateMutable(NULL, 2158 0, 2159 &kCFTypeDictionaryKeyCallBacks, 2160 &kCFTypeDictionaryValueCallBacks); 2161 } 2162 2163 dict = CFDictionaryGetValue(interfacePrivate->overrides, kSCNetworkInterfaceTypeModem); 2164 if (dict != NULL) { 2165 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict); 2166 } else { 2167 newDict = CFDictionaryCreateMutable(NULL, 2168 0, 2169 &kCFTypeDictionaryKeyCallBacks, 2170 &kCFTypeDictionaryValueCallBacks); 2171 } 2172 if (script != NULL) { 2173 CFDictionarySetValue(newDict, kSCPropNetModemConnectionScript, script); 2174 } else { 2175 CFDictionaryRemoveValue(newDict, kSCPropNetModemConnectionScript); 2176 } 2177 if (CFDictionaryGetCount(newDict) > 0) { 2178 CFDictionarySetValue(interfacePrivate->overrides, kSCNetworkInterfaceTypeModem, newDict); 2179 } else { 2180 CFDictionaryRemoveValue(interfacePrivate->overrides, kSCNetworkInterfaceTypeModem); 2181 } 2182 CFRelease(newDict); 2183 2184 if (CFDictionaryGetCount(interfacePrivate->overrides) == 0) { 2185 CFRelease(interfacePrivate->overrides); 2186 interfacePrivate->overrides = NULL; 2187 } 2188 return; 2189} 2190 2191 2192static Boolean 2193is_valid_connection_script(CFStringRef script) 2194{ 2195 char ccl[MAXPATHLEN]; 2196 char path[MAXPATHLEN]; 2197 sysdir_search_path_enumeration_state state; 2198 2199 (void) _SC_cfstring_to_cstring(script, 2200 ccl, 2201 sizeof(ccl), 2202 kCFStringEncodingUTF8); 2203 2204 state = sysdir_start_search_path_enumeration(SYSDIR_DIRECTORY_LIBRARY, 2205 SYSDIR_DOMAIN_MASK_LOCAL|SYSDIR_DOMAIN_MASK_SYSTEM); 2206 while ((state = sysdir_get_next_search_path_enumeration(state, path))) { 2207 size_t n; 2208 struct stat statBuf; 2209 2210 if (ccl[0] == '/') { 2211 path[0] = '\0'; // if modemCCL is a full path 2212 } else { 2213 strlcat(path, "/Modem Scripts/", sizeof(path)); 2214 } 2215 strlcat(path, ccl, sizeof(path)); 2216 2217 if (stat(path, &statBuf) != 0) { 2218 if (errno == ENOENT) { 2219 goto bundle; 2220 } 2221 2222 SC_log(LOG_INFO, "stat() failed: %s", strerror(errno)); 2223 continue; 2224 } 2225 if (S_ISREG(statBuf.st_mode)) { 2226 // if we have a valid CCL script 2227 return TRUE; 2228 } 2229 2230#define BUNDLE_EXT ".ccl" 2231#define BUNDLE_EXT_LEN sizeof(BUNDLE_EXT) - 1 2232 2233 bundle : 2234 2235 n = strlen(path); 2236 if ((n <= BUNDLE_EXT_LEN) || 2237 (strstr(&path[n - BUNDLE_EXT_LEN], BUNDLE_EXT) == NULL)) { 2238 strlcat(path, BUNDLE_EXT, sizeof(path)); 2239 if (stat(path, &statBuf) != 0) { 2240 if (errno == ENOENT) { 2241 continue; 2242 } 2243 2244 SC_log(LOG_INFO, "stat() failed: %s", strerror(errno)); 2245 continue; 2246 } 2247 } 2248 if (S_ISDIR(statBuf.st_mode)) { 2249 // if we have a valid CCL bundle 2250 return TRUE; 2251 } 2252 } 2253 2254 return FALSE; 2255} 2256 2257 2258static Boolean 2259processSerialInterface(SCNetworkInterfacePrivateRef interfacePrivate, 2260 io_registry_entry_t interface, 2261 CFDictionaryRef interface_dict, 2262 io_registry_entry_t controller, 2263 CFDictionaryRef controller_dict, 2264 io_registry_entry_t bus, 2265 CFDictionaryRef bus_dict) 2266{ 2267 CFStringRef base = NULL; 2268 CFStringRef ift; 2269 Boolean isModem = FALSE; 2270 Boolean isWWAN = FALSE; 2271 CFStringRef modemCCL = NULL; 2272 Boolean ok = FALSE; 2273 CFTypeRef val; 2274 2275 // check if initializing 2276 val = IORegistryEntrySearchCFProperty(interface, 2277 kIOServicePlane, 2278 kSCNetworkInterfaceInitializingKey, 2279 NULL, 2280 kIORegistryIterateRecursively | kIORegistryIterateParents); 2281 if (val != NULL) { 2282 Boolean initializing; 2283 2284 initializing = isA_CFBoolean(val) && CFBooleanGetValue(val); 2285 CFRelease(val); 2286 if (initializing) { 2287 return FALSE; // if this interface is still initializing 2288 } 2289 } 2290 2291 // check if WWAN 2292 val = IORegistryEntrySearchCFProperty(interface, 2293 kIOServicePlane, 2294 CFSTR("WWAN"), 2295 NULL, 2296 kIORegistryIterateRecursively | kIORegistryIterateParents); 2297 if (val != NULL) { 2298 isWWAN = isA_CFBoolean(val) && CFBooleanGetValue(val); 2299 CFRelease(val); 2300 } 2301 2302 // Entity (Device) 2303 interfacePrivate->entity_device = IODictionaryCopyCFStringValue(interface_dict, CFSTR(kIOTTYDeviceKey)); 2304 if (interfacePrivate->entity_device == NULL) { 2305 return FALSE; 2306 } 2307 2308 base = IODictionaryCopyCFStringValue(interface_dict, CFSTR(kIOTTYBaseNameKey)); 2309 if (base == NULL) { 2310 base = CFRetain(interfacePrivate->entity_device); 2311 } 2312 2313 /* 2314 * From MoreSCF: 2315 * 2316 * Exclude ports named "irda" because otherwise the IrDA ports on the 2317 * original iMac (rev's A through D) show up as serial ports. Given 2318 * that only the rev A actually had an IrDA port, and Mac OS X doesn't 2319 * even support it, these ports definitely shouldn't be listed. 2320 */ 2321 if (CFStringCompare(base, 2322 CFSTR("irda"), 2323 kCFCompareCaseInsensitive) == kCFCompareEqualTo) { 2324 goto done; 2325 } 2326 2327 if (IOStringValueHasPrefix(base, CFSTR("bluetooth"))) { 2328 Boolean haveController = FALSE; 2329 2330 // Bluetooth 2331 interfacePrivate->interface_type = kSCNetworkInterfaceTypeBluetooth; 2332 interfacePrivate->sort_order = kSortBluetooth; 2333 interfacePrivate->builtin = isBluetoothBuiltin(&haveController); 2334 if (!haveController) { 2335 // if device with no controller present 2336 goto done; 2337 } 2338 } else if (IOStringValueHasPrefix(base, CFSTR("irda-ircomm"))) { 2339 // IrDA 2340 interfacePrivate->interface_type = kSCNetworkInterfaceTypeIrDA; 2341 interfacePrivate->sort_order = kSortIrDA; 2342 } else if (isWWAN) { 2343 // WWAN 2344 interfacePrivate->interface_type = kSCNetworkInterfaceTypeWWAN; 2345 interfacePrivate->sort_order = kSortWWAN; 2346 } else { 2347 // Modem 2348 interfacePrivate->interface_type = kSCNetworkInterfaceTypeModem; 2349 interfacePrivate->sort_order = kSortModem; 2350 } 2351 2352 // Entity (Type) 2353 interfacePrivate->entity_type = kSCEntNetModem; 2354 2355 // Entity (Hardware) 2356 ift = CFDictionaryGetValue(interface_dict, CFSTR(kIOSerialBSDTypeKey)); 2357 if (!isA_CFString(ift)) { 2358 goto done; 2359 } 2360 2361 if (CFEqual(ift, CFSTR(kIOSerialBSDModemType))) { 2362 // if modem 2363 isModem = TRUE; 2364 2365 if (CFEqual(base, CFSTR("modem"))) { 2366 interfacePrivate->builtin = TRUE; 2367 interfacePrivate->sort_order = kSortInternalModem; 2368 } else if (CFEqual(base, CFSTR("usbmodem"))) { 2369 interfacePrivate->sort_order = kSortUSBModem; 2370 } 2371 } else if (CFEqual(ift, CFSTR(kIOSerialBSDRS232Type))) { 2372 // if serial port 2373 interfacePrivate->sort_order = kSortSerialPort; 2374 } else { 2375 goto done; 2376 } 2377 2378 // configuration [PPP] template override (now deprecated, use NetworkConfigurationOverrides) 2379 merge_override(interfacePrivate, interface, kSCNetworkInterfaceTypePPP); 2380 2381 // configuration [Modem] template override (now deprecated, use NetworkConfigurationOverrides) 2382 merge_override(interfacePrivate, interface, kSCNetworkInterfaceTypeModem); 2383 2384 // look for modem CCL, unique identifier 2385 if (interfacePrivate->overrides != NULL) { 2386 val = CFDictionaryGetValue(interfacePrivate->overrides, kSCNetworkInterfaceTypeModem); 2387 if (val != NULL) { 2388 CFStringRef uniqueID; 2389 2390 modemCCL = CFDictionaryGetValue(val, kSCPropNetModemConnectionScript); 2391 modemCCL = isA_CFString(modemCCL); 2392 2393 uniqueID = CFDictionaryGetValue(val, CFSTR("UniqueIdentifier")); 2394 uniqueID = isA_CFString(uniqueID); 2395 if (uniqueID != NULL) { 2396 // retain the device's base name and the unique id 2397 CFRelease(interfacePrivate->entity_device); 2398 interfacePrivate->entity_device = CFRetain(base); 2399 interfacePrivate->entity_device_unique = CFStringCreateCopy(NULL, uniqueID); 2400 } 2401 } 2402 } 2403 2404 // if not part of the NetworkConfigurationOverrides/DeviceModemOverrides, look 2405 // a bit harder for the modem CCL 2406 if (modemCCL == NULL) { 2407 val = IORegistryEntrySearchCFProperty(interface, 2408 kIOServicePlane, 2409 CFSTR("ModemCCL"), 2410 NULL, 2411 kIORegistryIterateRecursively | kIORegistryIterateParents); 2412 if (val != NULL) { 2413 modemCCL = IOCopyCFStringValue(val); 2414 if (modemCCL != NULL) { 2415 set_connection_script(interfacePrivate, modemCCL); 2416 CFRelease(modemCCL); 2417 } 2418 2419 CFRelease(val); 2420 } 2421 } 2422 2423 // localized name 2424 if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeIrDA)) { 2425 interfacePrivate->localized_key = CFSTR("irda"); 2426 } else if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeBluetooth)) { 2427 interfacePrivate->localized_key = CFSTR("bluetooth"); 2428 } else { 2429 CFStringRef localized = NULL; 2430 CFStringRef name = NULL; 2431 CFMutableStringRef port; 2432 2433 port = CFStringCreateMutableCopy(NULL, 0, base); 2434 CFStringLowercase(port, NULL); 2435 2436 if (!isModem) { 2437 CFStringAppend(port, CFSTR("-port")); 2438 } 2439 2440 // set non-localized name 2441 if (bundle != NULL) { 2442 name = copy_interface_string(bundle, port, FALSE); 2443 } 2444 if (name != NULL) { 2445 if (!CFEqual(port, name)) { 2446 // if [English] localization available 2447 interfacePrivate->name = name; 2448 } else { 2449 // if no [English] localization available, use TTY base name 2450 CFRelease(name); 2451 interfacePrivate->name = CFStringCreateCopy(NULL, base); 2452 } 2453 } else { 2454 interfacePrivate->name = CFStringCreateCopy(NULL, base); 2455 } 2456 2457 // set localized name 2458 if (bundle != NULL) { 2459 localized = copy_interface_string(bundle, port, TRUE); 2460 } 2461 if (localized != NULL) { 2462 if (!CFEqual(port, localized)) { 2463 // if localization available 2464 interfacePrivate->localized_name = localized; 2465 } else { 2466 // if no localization available, use TTY base name 2467 CFRelease(localized); 2468 interfacePrivate->localized_name = CFStringCreateCopy(NULL, base); 2469 } 2470 } else { 2471 interfacePrivate->localized_name = CFStringCreateCopy(NULL, base); 2472 } 2473 2474 if (!isModem || !CFEqual(base, CFSTR("modem"))) { 2475 // get USB info (if available) 2476 processUSBInterface(interfacePrivate, 2477 interface, 2478 interface_dict, 2479 controller, 2480 controller_dict, 2481 bus, 2482 bus_dict); 2483 2484 // set interface "name" 2485 if (update_interface_name(interfacePrivate, interface, TRUE)) { 2486 // if "ModemCCL" not provided, also check if the product/interface 2487 // name matches a CCL script 2488 if ((modemCCL == NULL) && 2489 is_valid_connection_script(interfacePrivate->name)) { 2490 set_connection_script(interfacePrivate, interfacePrivate->name); 2491 } 2492 } 2493 } 2494 2495 CFRelease(port); 2496 } 2497 2498 ok = TRUE; 2499 2500 done : 2501 2502 if (!ok && (interfacePrivate->entity_device != NULL)) { 2503 CFRelease(interfacePrivate->entity_device); 2504 interfacePrivate->entity_device = NULL; 2505 } 2506 if (base != NULL) CFRelease(base); 2507 2508 return ok; 2509} 2510 2511 2512static CFStringRef 2513__SC_IORegistryEntryCopyPath(io_registry_entry_t entry, const io_name_t plane) 2514{ 2515 /* 2516 * Create a path for a registry entry. 2517 */ 2518 io_string_t path; 2519 IOReturn status; 2520 CFStringRef str = NULL; 2521 2522 status = IORegistryEntryGetPath(entry, plane, path); 2523 if (status == kIOReturnSuccess) { 2524 str = CFStringCreateWithCString(NULL, path, kCFStringEncodingUTF8); 2525 } else if (status == kIOReturnBadArgument) { 2526 io_registry_entry_t parent; 2527 2528 status = IORegistryEntryGetParentEntry(entry, plane, &parent); 2529 if (status == kIOReturnSuccess) { 2530 CFStringRef str_parent; 2531 2532 str_parent = __SC_IORegistryEntryCopyPath(parent, plane); 2533 if (str_parent != NULL) { 2534 io_name_t name; 2535 2536 status = IORegistryEntryGetNameInPlane(entry, plane, name); 2537 if (status == kIOReturnSuccess) { 2538 io_name_t location; 2539 2540 status = IORegistryEntryGetLocationInPlane(entry, plane, location); 2541 if (status == kIOReturnSuccess) { 2542 str = CFStringCreateWithFormat(NULL, 2543 NULL, 2544 CFSTR("%@/%s@%s"), 2545 str_parent, 2546 name, 2547 location); 2548 } else { 2549 str = CFStringCreateWithFormat(NULL, 2550 NULL, 2551 CFSTR("%@/%s"), 2552 str_parent, 2553 name); 2554 } 2555 } 2556 2557 CFRelease(str_parent); 2558 } 2559 2560 IOObjectRelease(parent); 2561 } 2562 } 2563 2564 return str; 2565} 2566 2567static CFMutableDictionaryRef 2568copyIORegistryProperties(io_registry_entry_t reg_ent, const CFStringRef *reg_keys, CFIndex numKeys) 2569{ 2570 CFIndex idx = 0; 2571 CFMutableDictionaryRef reg_dict = NULL; 2572 CFTypeRef value = NULL; 2573 2574 reg_dict = CFDictionaryCreateMutable(NULL, 2575 0, 2576 &kCFTypeDictionaryKeyCallBacks , 2577 &kCFTypeDictionaryValueCallBacks); 2578 2579 for (; idx < numKeys; idx++) { 2580 value = IORegistryEntryCreateCFProperty(reg_ent, reg_keys[idx], NULL, 0); 2581 if (value != NULL) { 2582 CFDictionaryAddValue(reg_dict, reg_keys[idx], value); 2583 CFRelease(value); 2584 } 2585 } 2586 2587 return reg_dict; 2588} 2589 2590static SCNetworkInterfaceRef 2591createInterface(io_registry_entry_t interface, processInterface func, 2592 CFStringRef hidden_key) 2593{ 2594 io_registry_entry_t bus = MACH_PORT_NULL; 2595 CFMutableDictionaryRef bus_dict = NULL; 2596 io_registry_entry_t controller = MACH_PORT_NULL; 2597 CFMutableDictionaryRef controller_dict = NULL; 2598 uint64_t entryID = 0; 2599 SCNetworkInterfacePrivateRef interfacePrivate = NULL; 2600 CFMutableDictionaryRef interface_dict = NULL; 2601 kern_return_t kr; 2602 CFTypeRef val; 2603 2604 // Keys of interest 2605 const CFStringRef interface_dict_keys[] = { 2606 CFSTR(kIOInterfaceType), 2607 CFSTR(kIOBuiltin), 2608 CFSTR(kIOBSDNameKey), 2609 CFSTR(kIOPrimaryInterface), 2610 CFSTR(kIOInterfaceNamePrefix), 2611 CFSTR(kIOInterfaceUnit), 2612 CFSTR(kIOTTYDeviceKey), 2613 CFSTR(kIOTTYBaseNameKey), 2614 CFSTR(kIOSerialBSDTypeKey), 2615 CFSTR(kIOLocation) 2616 }; 2617 2618 const CFStringRef controller_dict_keys[] = { 2619 CFSTR(kIOFeatures), 2620 CFSTR(kIOMACAddress) 2621 }; 2622 2623 const CFStringRef bus_dict_keys[] = { 2624 CFSTR("name") 2625 }; 2626 2627 if (hidden_key != NULL) { 2628 // check if hidden 2629 val = IORegistryEntrySearchCFProperty(interface, 2630 kIOServicePlane, 2631 hidden_key, 2632 NULL, 2633 kIORegistryIterateRecursively | kIORegistryIterateParents); 2634 if (val != NULL) { 2635 CFRelease(val); 2636 goto done; // if this interface should not be exposed 2637 } 2638 } 2639 2640 interface_dict = copyIORegistryProperties(interface, 2641 interface_dict_keys, 2642 sizeof(interface_dict_keys)/sizeof(interface_dict_keys[0])); 2643 2644 // get the controller node 2645 kr = IORegistryEntryGetParentEntry(interface, kIOServicePlane, &controller); 2646 if (kr != kIOReturnSuccess) { 2647 SC_log(LOG_INFO, "IORegistryEntryGetParentEntry() failed, kr = 0x%x", kr); 2648 goto done; 2649 } 2650 2651 controller_dict = copyIORegistryProperties(controller, 2652 controller_dict_keys, 2653 sizeof(controller_dict_keys)/sizeof(controller_dict_keys[0])); 2654 2655 // get the bus node 2656 kr = IORegistryEntryGetParentEntry(controller, kIOServicePlane, &bus); 2657 if (kr != kIOReturnSuccess) { 2658 SC_log(LOG_INFO, "IORegistryEntryGetParentEntry() failed, kr = 0x%x", kr); 2659 goto done; 2660 } 2661 2662 bus_dict = copyIORegistryProperties(bus, 2663 bus_dict_keys, 2664 sizeof(bus_dict_keys)/sizeof(bus_dict_keys[0])); 2665 2666 // get the registry entry ID 2667 kr = IORegistryEntryGetRegistryEntryID(interface, &entryID); 2668 if (kr != kIOReturnSuccess) { 2669 SC_log(LOG_INFO, "IORegistryEntryGetRegistryEntryID() failed, kr = 0x%x", kr); 2670 goto done; 2671 } 2672 2673 interfacePrivate = __SCNetworkInterfaceCreatePrivate(NULL, NULL, NULL, NULL); 2674 assert(interfacePrivate != NULL); 2675 interfacePrivate->path = __SC_IORegistryEntryCopyPath(interface, kIOServicePlane); 2676 interfacePrivate->entryID = entryID; 2677 2678 // configuration [PPP, Modem, DNS, IPv4, IPv6, Proxies, SMB] template overrides 2679 val = IORegistryEntrySearchCFProperty(interface, 2680 kIOServicePlane, 2681 kSCNetworkInterfaceNetworkConfigurationOverridesKey, 2682 NULL, 2683 kIORegistryIterateRecursively | kIORegistryIterateParents); 2684 if (val != NULL) { 2685 if (isA_CFDictionary(val)) { 2686 interfacePrivate->overrides = CFDictionaryCreateMutableCopy(NULL, 0, val); 2687 } 2688 CFRelease(val); 2689 } 2690 2691 if ((*func)(interfacePrivate, interface, interface_dict, controller, controller_dict, bus, bus_dict)) { 2692 // get user-notification / auto-configuration preference 2693 val = IORegistryEntrySearchCFProperty(interface, 2694 kIOServicePlane, 2695 kSCNetworkInterfaceConfigurationActionKey, 2696 NULL, 2697 kIORegistryIterateRecursively | kIORegistryIterateParents); 2698 if (val != NULL) { 2699 if (isA_CFString(val)) { 2700 interfacePrivate->configurationAction = CFRetain(val); 2701 } 2702 CFRelease(val); 2703 } 2704 2705 // get HiddenConfiguration preference 2706 val = IORegistryEntrySearchCFProperty(interface, 2707 kIOServicePlane, 2708 kSCNetworkInterfaceHiddenConfigurationKey, 2709 NULL, 2710 kIORegistryIterateRecursively | kIORegistryIterateParents); 2711 if (val != NULL) { 2712 interfacePrivate->hidden = TRUE; 2713 CFRelease(val); 2714 } 2715 2716#if TARGET_OS_IPHONE 2717 // get TrustRequired preference 2718 val = IORegistryEntrySearchCFProperty(interface, 2719 kIOServicePlane, 2720 kSCNetworkInterfaceTrustRequiredKey, 2721 NULL, 2722 kIORegistryIterateRecursively | kIORegistryIterateParents); 2723 if (val != NULL) { 2724 if (isA_CFBoolean(val)) { 2725 interfacePrivate->trustRequired = CFBooleanGetValue(val); 2726 } 2727 CFRelease(val); 2728 } 2729#endif // TARGET_OS_IPHONE 2730 } else { 2731 CFRelease(interfacePrivate); 2732 interfacePrivate = NULL; 2733 } 2734 2735 done : 2736 2737 if (interface_dict != NULL) CFRelease(interface_dict); 2738 2739 if (controller != MACH_PORT_NULL) IOObjectRelease(controller); 2740 if (controller_dict != NULL) CFRelease(controller_dict); 2741 2742 if (bus != MACH_PORT_NULL) IOObjectRelease(bus); 2743 if (bus_dict != NULL) CFRelease(bus_dict); 2744 2745 return (SCNetworkInterfaceRef)interfacePrivate; 2746} 2747 2748 2749static CF_RETURNS_RETAINED CFArrayRef 2750findMatchingInterfaces(CFDictionaryRef matching, 2751 processInterface func, 2752 CFStringRef hidden_key, 2753 Boolean keep_pre_configured) 2754{ 2755 CFMutableArrayRef interfaces; 2756 io_registry_entry_t interface; 2757 kern_return_t kr; 2758 io_iterator_t iterator = MACH_PORT_NULL; 2759 2760 /* 2761 * A reference to the "matching" dictionary will be consumed by the 2762 * the call to IOServiceGetMatchingServices so we bump up the retain 2763 * count. 2764 */ 2765 CFRetain(matching); 2766 2767 kr = IOServiceGetMatchingServices(masterPort, matching, &iterator); 2768 if (kr != kIOReturnSuccess) { 2769 SC_log(LOG_INFO, "IOServiceGetMatchingServices() failed, kr = 0x%x", kr); 2770 return NULL; 2771 } 2772 2773 interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 2774 2775 while ((interface = IOIteratorNext(iterator)) != MACH_PORT_NULL) { 2776 SCNetworkInterfaceRef match; 2777 2778 match = createInterface(interface, func, hidden_key); 2779 if (match != NULL) { 2780 if (keep_pre_configured || !_SCNetworkInterfaceIsApplePreconfigured(match)) { 2781 CFArrayAppendValue(interfaces, match); 2782 } 2783 CFRelease(match); 2784 } 2785 2786 IOObjectRelease(interface); 2787 } 2788 2789 IOObjectRelease(iterator); 2790 2791 return interfaces; 2792} 2793 2794 2795#pragma mark - 2796#pragma mark helper functions 2797 2798 2799static CFIndex 2800findConfiguration(CFStringRef interface_type) 2801{ 2802 for (size_t i = 0; i < sizeof(configurations)/sizeof(configurations[0]); i++) { 2803 if (CFEqual(interface_type, *configurations[i].interface_type)) { 2804 return i; 2805 } 2806 } 2807 2808 return kCFNotFound; 2809} 2810 2811 2812__private_extern__ 2813CFStringRef 2814__SCNetworkInterfaceGetDefaultConfigurationType(SCNetworkInterfaceRef interface) 2815{ 2816 CFIndex interfaceIndex; 2817 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 2818 2819 if (interfacePrivate->serviceID == NULL) { 2820 // if not associated with a service (yet) 2821 _SCErrorSet(kSCStatusInvalidArgument); 2822 return NULL; 2823 } 2824 2825 interfaceIndex = findConfiguration(interfacePrivate->interface_type); 2826 if (interfaceIndex == kCFNotFound) { 2827 // unknown interface type, use per-service configuration preferences 2828 return interfacePrivate->interface_type; // entity 2829 } 2830 2831 if (configurations[interfaceIndex].entity_hardware != NULL) { 2832 // if configuration information can be associated with this interface type 2833 return *configurations[interfaceIndex].entity_hardware; 2834 } 2835 2836 _SCErrorSet(kSCStatusInvalidArgument); 2837 return NULL; 2838} 2839 2840 2841__private_extern__ 2842Boolean 2843__SCNetworkInterfaceIsValidExtendedConfigurationType(SCNetworkInterfaceRef interface, 2844 CFStringRef extendedType, 2845 Boolean requirePerInterface) 2846{ 2847 CFStringRef defaultType; 2848 CFIndex extendedIndex; 2849 CFIndex interfaceIndex; 2850 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 2851 Boolean isL2TP = FALSE; 2852 Boolean ok = FALSE; 2853 2854 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface); 2855 if (defaultType == NULL) { 2856 goto done; 2857 } 2858 2859 if (CFEqual(extendedType, defaultType)) { 2860 // extended and default configuration types cannot conflict 2861 goto done; 2862 } 2863 2864 interfaceIndex = findConfiguration(interfacePrivate->interface_type); 2865 if (interfaceIndex == kCFNotFound) { 2866 // configuration information for unknown interface type's 2867 // are stored along with the service and we don't allow 2868 // per-service extended configurations 2869 goto done; 2870 } 2871 2872 if (CFEqual(extendedType, kSCEntNetIPSec)) { 2873 CFStringRef interfaceType; 2874 2875 interfaceType = SCNetworkInterfaceGetInterfaceType(interface); 2876 if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) { 2877 SCNetworkInterfaceRef child; 2878 2879 child = SCNetworkInterfaceGetInterface(interface); 2880 if (child != NULL) { 2881 interfaceType = SCNetworkInterfaceGetInterfaceType(child); 2882 if (CFEqual(interfaceType, kSCNetworkInterfaceTypeL2TP)) { 2883 isL2TP = TRUE; 2884 } 2885 } 2886 } 2887 } 2888 2889 if (requirePerInterface && 2890 !configurations[interfaceIndex].per_interface_config && 2891 !isL2TP) { 2892 // we don't allow per-service extended configurations (except 2893 // that we do allow IPSec as an extended type for PPP->L2TP) 2894 goto done; 2895 } 2896 2897 extendedIndex = findConfiguration(extendedType); 2898 if ((extendedIndex != kCFNotFound) && !isL2TP) { 2899 // extended type cannot match a known interface type (except 2900 // that we do allow IPSec as an extended type for PPP->L2TP) 2901 goto done; 2902 } 2903 2904 /* 2905 * ??? 2906 * Should we check/match and specifically allow known extended 2907 * configuration types (e.g. EAPOL)? 2908 * 2909 * Should we check/match and specifically block known internal 2910 * configuration types (e.g. QoSMarking)? 2911 * 2912 * Lastly, should we ensure that any non-standard extended configuration 2913 * types be of the form com.myCompany.myType? 2914 * ??? 2915 */ 2916 2917 ok = TRUE; 2918 2919 done : 2920 2921 if (!ok) { 2922 _SCErrorSet(kSCStatusInvalidArgument); 2923 } 2924 return ok; 2925} 2926 2927 2928typedef struct { 2929 CFStringRef defaultType; 2930 CFMutableArrayRef types; 2931} extendedConfiguration, *extendedConfigurationRef; 2932 2933 2934static void 2935__addExtendedConfigurationType(const void *key, const void *value, void *context) 2936{ 2937#pragma unused(value) 2938 CFStringRef extendedType = (CFStringRef)key; 2939 extendedConfigurationRef myContextRef = (extendedConfigurationRef)context; 2940 2941 if (CFEqual(extendedType, myContextRef->defaultType)) { 2942 // do not include the default configuration type 2943 return; 2944 } 2945 2946 if (CFArrayContainsValue(myContextRef->types, 2947 CFRangeMake(0, CFArrayGetCount(myContextRef->types)), 2948 extendedType)) { 2949 // if extendedType already has already been added 2950 return; 2951 } 2952 2953 CFArrayAppendValue(myContextRef->types, extendedType); 2954 2955 return; 2956} 2957 2958 2959static CFIndex 2960findPerInterfaceConfiguration(SCNetworkInterfaceRef interface) 2961{ 2962 CFIndex interfaceIndex; 2963 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 2964 2965 interfaceIndex = findConfiguration(interfacePrivate->interface_type); 2966 if (interfaceIndex == kCFNotFound) { 2967 // if per-service (not per interface) configuration 2968 return kCFNotFound; 2969 } 2970 2971 if (!configurations[interfaceIndex].per_interface_config) { 2972 // if per-interface configuration not allowed 2973 return kCFNotFound; 2974 } 2975 2976 return interfaceIndex; 2977} 2978 2979 2980static CF_RETURNS_RETAINED CFArrayRef 2981extendedConfigurationTypes(SCNetworkInterfaceRef interface) 2982{ 2983 CFIndex i; 2984 CFIndex interfaceIndex; 2985 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 2986 extendedConfiguration myContext; 2987 SCNetworkServiceRef service; 2988 CFArrayRef sets; 2989 CFIndex n; 2990 2991 myContext.defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface); 2992 if (myContext.defaultType == NULL) { 2993 myContext.types = NULL; 2994 goto done; 2995 } 2996 2997 myContext.types = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 2998 2999 if (interfacePrivate->serviceID == NULL) { 3000 // if not associated with a service (yet) 3001 goto done; 3002 } 3003 3004 interfaceIndex = findPerInterfaceConfiguration(interface); 3005 if (interfaceIndex == kCFNotFound) { 3006 // if no per-interface configuration 3007 goto done; 3008 } 3009 3010 service = (SCNetworkServiceRef)__SCNetworkServiceCreatePrivate(NULL, 3011 interfacePrivate->prefs, 3012 interfacePrivate->serviceID, 3013 interface); 3014 3015 sets = SCNetworkSetCopyAll(interfacePrivate->prefs); 3016 n = (sets != NULL) ? CFArrayGetCount(sets) : 0; 3017 3018 for (i = 0; i < n; i++) { 3019 CFDictionaryRef configs; 3020 Boolean found; 3021 CFStringRef path; 3022 CFArrayRef services; 3023 SCNetworkSetRef set; 3024 3025 set = CFArrayGetValueAtIndex(sets, i); 3026 services = SCNetworkSetCopyServices(set); 3027 found = CFArrayContainsValue(services, 3028 CFRangeMake(0, CFArrayGetCount(services)), 3029 service); 3030 CFRelease(services); 3031 3032 if (!found) { 3033 continue; 3034 } 3035 3036 // add stored extended configuration types 3037 path = SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL, // allocator 3038 SCNetworkSetGetSetID(set), // set 3039 interfacePrivate->entity_device, // service 3040 NULL); // entity 3041 configs = __getPrefsConfiguration(interfacePrivate->prefs, path); 3042 CFRelease(path); 3043 if (isA_CFDictionary(configs)) { 3044 CFDictionaryApplyFunction(configs, 3045 __addExtendedConfigurationType, 3046 &myContext); 3047 } 3048 3049 // add not-yet-stored extended configuration types 3050 if (interfacePrivate->unsaved != NULL) { 3051 CFDictionaryApplyFunction(interfacePrivate->unsaved, 3052 __addExtendedConfigurationType, 3053 &myContext); 3054 } 3055 3056 break; 3057 } 3058 3059 CFRelease(service); 3060 if (sets != NULL) CFRelease(sets); 3061 3062 done : 3063 3064 return myContext.types; 3065} 3066 3067static CFArrayRef 3068stringCreateArray(CFStringRef str) 3069{ 3070 return (CFArrayCreate(NULL, (const void **)&str, 1, &kCFTypeArrayCallBacks)); 3071} 3072 3073static CFArrayRef 3074copyPerInterfaceConfigurationPaths(SCNetworkInterfacePrivateRef interfacePrivate, 3075 CFStringRef extendedType) 3076{ 3077 CFMutableArrayRef array = NULL; 3078 CFIndex i; 3079 CFIndex n; 3080 CFStringRef path; 3081 SCNetworkServiceRef service; 3082 CFArrayRef sets; 3083 3084 // known interface type, per-interface configuration preferences 3085 // 3086 // 1. look for all sets which contain the associated service 3087 // 2. add a per-set path for the interface configuration for 3088 // each set. 3089 3090 service = (SCNetworkServiceRef)__SCNetworkServiceCreatePrivate(NULL, 3091 interfacePrivate->prefs, 3092 interfacePrivate->serviceID, 3093 (SCNetworkInterfaceRef)interfacePrivate); 3094 3095 sets = SCNetworkSetCopyAll(interfacePrivate->prefs); 3096 n = (sets != NULL) ? CFArrayGetCount(sets) : 0; 3097 3098 for (i = 0; i < n; i++) { 3099 CFArrayRef services; 3100 SCNetworkSetRef set; 3101 3102 set = CFArrayGetValueAtIndex(sets, i); 3103 services = SCNetworkSetCopyServices(set); 3104 if (CFArrayContainsValue(services, 3105 CFRangeMake(0, CFArrayGetCount(services)), 3106 service)) { 3107 path = SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL, // allocator 3108 SCNetworkSetGetSetID(set), // set 3109 interfacePrivate->entity_device, // service 3110 extendedType); // entity 3111 if (array == NULL) { 3112 array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 3113 } 3114 CFArrayAppendValue(array, path); 3115 CFRelease(path); 3116 } 3117 CFRelease(services); 3118 } 3119 3120 CFRelease(service); 3121 if (sets != NULL) CFRelease(sets); 3122 return array; 3123 3124} 3125 3126static CFArrayRef 3127copyConfigurationPaths(SCNetworkInterfacePrivateRef interfacePrivate, 3128 CFStringRef extendedType) 3129{ 3130 CFArrayRef array = NULL; 3131 CFIndex interfaceIndex; 3132 CFStringRef path; 3133 3134 interfaceIndex = findConfiguration(interfacePrivate->interface_type); 3135 if (interfaceIndex == kCFNotFound) { 3136 // unknown interface type, use per-service configuration preferences 3137 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator 3138 interfacePrivate->serviceID, // service 3139 extendedType); // entity 3140 array = stringCreateArray(path); 3141 CFRelease(path); 3142 } 3143 3144 else if (!configurations[interfaceIndex].per_interface_config) { 3145 // known interface type, per-service configuration preferences 3146 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator 3147 interfacePrivate->serviceID, // service 3148 extendedType); // entity 3149 array = stringCreateArray(path); 3150 CFRelease(path); 3151 } 3152 3153 else if (interfacePrivate->serviceID != NULL) { 3154 array = copyPerInterfaceConfigurationPaths(interfacePrivate, extendedType); 3155 } 3156 3157 return (array); 3158} 3159 3160 3161#pragma mark - 3162#pragma mark SCNetworkInterface <--> preferences entity 3163 3164 3165__private_extern__ 3166CFDictionaryRef 3167__SCNetworkInterfaceCopyInterfaceEntity(SCNetworkInterfaceRef interface) 3168{ 3169 CFMutableDictionaryRef entity; 3170 CFIndex interfaceIndex; 3171 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 3172 3173 entity = CFDictionaryCreateMutable(NULL, 3174 0, 3175 &kCFTypeDictionaryKeyCallBacks, 3176 &kCFTypeDictionaryValueCallBacks); 3177 if (interfacePrivate->entity_type != NULL) { 3178 CFDictionarySetValue(entity, 3179 kSCPropNetInterfaceType, 3180 interfacePrivate->entity_type); 3181 } 3182 if (interfacePrivate->entity_subtype != NULL) { 3183 CFDictionarySetValue(entity, 3184 kSCPropNetInterfaceSubType, 3185 interfacePrivate->entity_subtype); 3186 } 3187 if (interfacePrivate->entity_device != NULL) { 3188 CFDictionarySetValue(entity, 3189 kSCPropNetInterfaceDeviceName, 3190 interfacePrivate->entity_device); 3191 } 3192 if (interfacePrivate->entity_device_unique != NULL) { 3193 CFDictionarySetValue(entity, 3194 CFSTR("DeviceUniqueIdentifier"), 3195 interfacePrivate->entity_device_unique); 3196 } 3197 if (interfacePrivate->hidden) { 3198 CFDictionarySetValue(entity, 3199 kSCNetworkInterfaceHiddenConfigurationKey, 3200 kCFBooleanTrue); 3201 } 3202#if TARGET_OS_IPHONE 3203 if (interfacePrivate->trustRequired) { 3204 CFDictionarySetValue(entity, 3205 kSCNetworkInterfaceTrustRequiredKey, 3206 kCFBooleanTrue); 3207 } 3208#endif // TARGET_OS_IPHONE 3209 3210 // match the "hardware" with the lowest layer 3211 while (TRUE) { 3212 SCNetworkInterfaceRef nextInterface; 3213 3214 nextInterface = SCNetworkInterfaceGetInterface(interface); 3215 if (nextInterface == NULL) { 3216 break; 3217 } 3218 3219 interface = nextInterface; 3220 } 3221 interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 3222 3223 if (CFEqual(interface, kSCNetworkInterfaceIPv4)) { 3224 return entity; 3225 } 3226 3227 interfaceIndex = findConfiguration(interfacePrivate->interface_type); 3228 if (interfaceIndex != kCFNotFound) { 3229 if (configurations[interfaceIndex].entity_hardware != NULL) { 3230 CFDictionarySetValue(entity, 3231 kSCPropNetInterfaceHardware, 3232 *configurations[interfaceIndex].entity_hardware); 3233 } 3234 } else { 3235 CFDictionarySetValue(entity, 3236 kSCPropNetInterfaceHardware, 3237 interfacePrivate->interface_type); 3238 } 3239 3240 // add the localized display name (which will only be used when/if the 3241 // interface is removed from the system) 3242 CFDictionarySetValue(entity, 3243 kSCPropUserDefinedName, 3244 SCNetworkInterfaceGetLocalizedDisplayName(interface)); 3245 3246 return entity; 3247} 3248 3249 3250static SCNetworkInterfaceRef 3251findInterface(CFArrayRef interfaces, CFStringRef match_if) 3252{ 3253 CFIndex i; 3254 CFIndex n; 3255 3256 n = CFArrayGetCount(interfaces); 3257 for (i = 0; i < n; i++) { 3258 SCNetworkInterfaceRef interface = CFArrayGetValueAtIndex(interfaces, i); 3259 CFStringRef interfaceName; 3260 3261 interfaceName = SCNetworkInterfaceGetBSDName(interface); 3262 if ((interfaceName != NULL) && CFEqual(interfaceName, match_if)) { 3263 CFRetain(interface); 3264 return interface; 3265 } 3266 } 3267 3268 return NULL; 3269} 3270 3271#if !TARGET_OS_IPHONE 3272static SCNetworkInterfaceRef 3273findBondInterface(SCPreferencesRef prefs, CFStringRef ifDevice) 3274{ 3275 CFArrayRef bonds; 3276 SCNetworkInterfaceRef interface = NULL; 3277 3278 if (prefs == NULL) { 3279 return (NULL); 3280 } 3281 3282 // check if the interface is an Ethernet Bond 3283 bonds = SCBondInterfaceCopyAll(prefs); 3284 if (bonds != NULL) { 3285 interface = findInterface(bonds, ifDevice); 3286 CFRelease(bonds); 3287 } 3288 return interface; 3289} 3290#endif // !TARGET_OS_IPHONE 3291 3292static SCNetworkInterfaceRef 3293findBridgeInterface(SCPreferencesRef prefs, CFStringRef ifDevice) 3294{ 3295 CFArrayRef bridges; 3296 SCNetworkInterfaceRef interface = NULL; 3297 3298 if (prefs == NULL) { 3299 return (NULL); 3300 } 3301 3302 // check if the interface is an bridge 3303 bridges = SCBridgeInterfaceCopyAll(prefs); 3304 if (bridges != NULL) { 3305 interface = findInterface(bridges, ifDevice); 3306 CFRelease(bridges); 3307 } 3308 return interface; 3309} 3310 3311static SCNetworkInterfaceRef 3312findVLANInterface(SCPreferencesRef prefs, CFStringRef ifDevice) 3313{ 3314 SCNetworkInterfaceRef interface = NULL; 3315 CFArrayRef vlans; 3316 3317 if (prefs == NULL) { 3318 return (NULL); 3319 } 3320 3321 // check if the interface is a VLAN 3322 vlans = SCVLANInterfaceCopyAll(prefs); 3323 if (vlans != NULL) { 3324 interface = findInterface(vlans, ifDevice); 3325 CFRelease(vlans); 3326 } 3327 return interface; 3328} 3329 3330 3331#define N_QUICK 32 3332 3333 3334static CFMutableDictionaryRef 3335copy_ppp_entity(CFStringRef bsdName) 3336{ 3337 CFMutableDictionaryRef entity = NULL; 3338 CFStringRef pattern; 3339 CFMutableArrayRef patterns; 3340 CFDictionaryRef dict; 3341 3342 patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 3343 pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetPPP); 3344 CFArrayAppendValue(patterns, pattern); 3345 CFRelease(pattern); 3346 pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, kSCCompAnyRegex, kSCEntNetInterface); 3347 CFArrayAppendValue(patterns, pattern); 3348 CFRelease(pattern); 3349 dict = SCDynamicStoreCopyMultiple(NULL, NULL, patterns); 3350 CFRelease(patterns); 3351 if (dict != NULL) { 3352 CFIndex i; 3353 const void * keys_q[N_QUICK]; 3354 const void ** keys = keys_q; 3355 CFIndex n; 3356 const void * vals_q[N_QUICK]; 3357 const void ** vals = vals_q; 3358 3359 n = CFDictionaryGetCount(dict); 3360 if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) { 3361 keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0); 3362 vals = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0); 3363 } 3364 CFDictionaryGetKeysAndValues(dict, keys, vals); 3365 for (i = 0; i < n; i++) { 3366 CFArrayRef components; 3367 CFStringRef interfaceKey; 3368 CFDictionaryRef interfaceVal; 3369 CFStringRef ifName; 3370 CFStringRef pppKey = (CFStringRef)keys[i]; 3371 CFDictionaryRef pppVal = (CFDictionaryRef)vals[i]; 3372 CFStringRef serviceID; 3373 3374 if (!CFStringHasSuffix(pppKey, kSCEntNetPPP) || 3375 !CFDictionaryGetValueIfPresent(pppVal, kSCPropInterfaceName, (const void **)&ifName) || 3376 !CFEqual(bsdName, ifName)) { 3377 // if not matching PPP interface 3378 continue; 3379 } 3380 3381 components = CFStringCreateArrayBySeparatingStrings(NULL, pppKey, CFSTR("/")); 3382 serviceID = CFArrayGetValueAtIndex(components, 3); 3383 interfaceKey = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, serviceID, kSCEntNetInterface); 3384 interfaceVal = CFDictionaryGetValue(dict, interfaceKey); 3385 CFRelease(interfaceKey); 3386 CFRelease(components); 3387 if (interfaceVal != NULL) { 3388 entity = CFDictionaryCreateMutableCopy(NULL, 0, interfaceVal); 3389 break; 3390 } 3391 } 3392 if (keys != keys_q) { 3393 CFAllocatorDeallocate(NULL, keys); 3394 CFAllocatorDeallocate(NULL, vals); 3395 } 3396 3397 CFRelease(dict); 3398 } 3399 3400 return entity; 3401} 3402 3403 3404SCNetworkInterfaceRef 3405_SCNetworkInterfaceCreateWithBSDName(CFAllocatorRef allocator, 3406 CFStringRef bsdName, 3407 UInt32 flags) 3408{ 3409#pragma unused(allocator) 3410 CFMutableDictionaryRef entity = NULL; 3411 struct ifreq ifr; 3412 SCNetworkInterfaceRef interface; 3413 3414 memset(&ifr, 0, sizeof(ifr)); 3415 if (_SC_cfstring_to_cstring(bsdName, ifr.ifr_name, sizeof(ifr.ifr_name), kCFStringEncodingASCII) != NULL) { 3416 int s; 3417 3418 s = socket(AF_INET, SOCK_DGRAM, 0); 3419 if (s != -1) { 3420 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) == -1) { 3421 ifr.ifr_flags = 0; 3422 } 3423 close(s); 3424 } 3425 3426 if ((ifr.ifr_flags & IFF_POINTOPOINT) != 0) { 3427 // if PPP 3428 entity = copy_ppp_entity(bsdName); 3429 } 3430 } 3431 3432 if (entity == NULL) { 3433 entity = CFDictionaryCreateMutable(NULL, 3434 0, 3435 &kCFTypeDictionaryKeyCallBacks, 3436 &kCFTypeDictionaryValueCallBacks); 3437 CFDictionarySetValue(entity, kSCPropNetInterfaceDeviceName, bsdName); 3438 } 3439 3440#if !TARGET_OS_IPHONE 3441 if ((flags & kIncludeBondInterfaces) == 0) { 3442 CFDictionarySetValue(entity, CFSTR("_NO_BOND_INTERFACES_"), kCFBooleanTrue); 3443 } 3444#endif // !TARGET_OS_IPHONE 3445 3446 if ((flags & kIncludeBridgeInterfaces) == 0) { 3447 CFDictionarySetValue(entity, CFSTR("_NO_BRIDGE_INTERFACES_"), kCFBooleanTrue); 3448 } 3449 3450 if ((flags & kIncludeVLANInterfaces) == 0) { 3451 CFDictionarySetValue(entity, CFSTR("_NO_VLAN_INTERFACES_"), kCFBooleanTrue); 3452 } 3453 3454 interface = _SCNetworkInterfaceCreateWithEntity(NULL, entity, NULL); 3455 CFRelease(entity); 3456 3457 return interface; 3458} 3459 3460 3461static CFStringRef 3462_SCNetworkInterfaceCopyPrefixFromBSDName(CFStringRef bsdName) 3463{ 3464 CFMutableStringRef interfacePrefix = NULL; 3465 UniChar lastChar; 3466 CFIndex length = 0; 3467 3468 if (isA_CFString(bsdName) == NULL) { 3469 SC_log(LOG_DEBUG, "no BSD name"); 3470 goto done; 3471 } 3472 3473 interfacePrefix = CFStringCreateMutableCopy(NULL, 0, bsdName); 3474 length = CFStringGetLength(interfacePrefix); 3475 3476 while (length > 0) { 3477 lastChar = CFStringGetCharacterAtIndex(interfacePrefix, length - 1); 3478 if (lastChar >= '0' && lastChar <= '9') { 3479 CFStringDelete(interfacePrefix, 3480 CFRangeMake(length-1, 1)); 3481 } 3482 else { 3483 break; 3484 } 3485 length = CFStringGetLength(interfacePrefix); 3486 } 3487done: 3488 return interfacePrefix; 3489} 3490 3491 3492static void 3493__SCNetworkInterfaceSetIOInterfacePrefix(SCNetworkInterfaceRef interface, 3494 CFStringRef prefix); 3495 3496 3497static Boolean 3498__SCNetworkInterfaceUpdateBSDName(SCNetworkInterfaceRef interface, CFStringRef currentBSDName, CFStringRef newBSDName) 3499{ 3500 Boolean success = FALSE; 3501 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 3502 3503 if (isA_SCNetworkInterface(interface) == NULL) { 3504 SC_log(LOG_INFO, "No interface"); 3505 goto done; 3506 } 3507 3508 if (CFEqual(currentBSDName, newBSDName)) { 3509 // if no change 3510 goto done; 3511 } 3512 3513 if (interfacePrivate->entity_device != NULL) { 3514 CFRelease(interfacePrivate->entity_device); 3515 } 3516 interfacePrivate->entity_device = CFRetain(newBSDName); 3517 success = TRUE; 3518done: 3519 return success; 3520} 3521 3522 3523static Boolean 3524__SCNetworkInterfaceUpdateIOPath(SCNetworkInterfaceRef interface) 3525{ 3526 Boolean success = FALSE; 3527 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 3528 CFStringRef oldPath = NULL; 3529 CFStringRef newPath = NULL; 3530 3531 // Using the BSD Name update the path 3532 oldPath = interfacePrivate->path; 3533 if (isA_CFString(oldPath) == NULL) { 3534 goto done; 3535 } 3536 newPath = CFStringCreateWithFormat(NULL, NULL, CFSTR("Migrated_From: %@"), oldPath); 3537 if (interfacePrivate->path != NULL) { 3538 CFRelease(interfacePrivate->path); 3539 } 3540 interfacePrivate->path = CFRetain(newPath); 3541 success = TRUE; 3542 3543done: 3544 if (newPath != NULL) { 3545 CFRelease(newPath); 3546 } 3547 return success; 3548} 3549 3550 3551static void 3552__SCNetworkInterfaceSetIOInterfacePrefix (SCNetworkInterfaceRef interface, 3553 CFStringRef prefix) 3554{ 3555 SCNetworkInterfacePrivateRef interfacePrivate; 3556 3557 if (isA_CFString(prefix) == NULL) { 3558 return; 3559 } 3560 3561 interfacePrivate = (SCNetworkInterfacePrivateRef) interface; 3562 3563 CFRetain(prefix); 3564 3565 if (interfacePrivate->prefix != NULL) { 3566 CFRelease(interfacePrivate->prefix); 3567 } 3568 3569 interfacePrivate->prefix = prefix; 3570 return; 3571} 3572 3573 3574__private_extern__ 3575void 3576__SCNetworkInterfaceSetIOInterfaceUnit(SCNetworkInterfaceRef interface, 3577 CFNumberRef unit) 3578{ 3579 SCNetworkInterfacePrivateRef interfacePrivate; 3580 CFStringRef newBSDName = NULL; 3581 CFStringRef oldBSDName = NULL; 3582 3583 if (isA_CFNumber(unit) == NULL) { 3584 return; 3585 } 3586 interfacePrivate = (SCNetworkInterfacePrivateRef) interface; 3587 3588 oldBSDName = SCNetworkInterfaceGetBSDName(interface); 3589 3590 if (interfacePrivate->prefix == NULL) { 3591 if (isA_CFString(interfacePrivate->entity_device) != NULL) { 3592 CFStringRef interfaceNamePrefix = _SCNetworkInterfaceCopyPrefixFromBSDName(interfacePrivate->entity_device); 3593 if (interfaceNamePrefix == NULL) { 3594 SC_log(LOG_INFO, "interfaceNamePrefix is NULL"); 3595 } 3596 else { 3597 __SCNetworkInterfaceSetIOInterfacePrefix(interface, interfaceNamePrefix); 3598 CFRelease(interfaceNamePrefix); 3599 } 3600 } 3601 } 3602 3603 if (interfacePrivate->prefix != NULL) { 3604 newBSDName = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), interfacePrivate->prefix, unit); 3605 } 3606 3607 // Update the BSD Name 3608 if ((newBSDName == NULL) || 3609 (!__SCNetworkInterfaceUpdateBSDName(interface, oldBSDName, newBSDName))) { 3610 SC_log(LOG_INFO, "BSD name update failed"); 3611 } 3612 3613 // Update the path 3614 if (!__SCNetworkInterfaceUpdateIOPath(interface)) { 3615 SC_log(LOG_INFO, "IOPath update failed"); 3616 } 3617 3618 CFRetain(unit); 3619 if (interfacePrivate->unit != NULL) { 3620 CFRelease(interfacePrivate->unit); 3621 } 3622 interfacePrivate->unit = unit; 3623 3624 3625 if (newBSDName != NULL) { 3626 CFRelease(newBSDName); 3627 } 3628 return; 3629} 3630 3631 3632__private_extern__ 3633CFDictionaryRef 3634__SCNetworkInterfaceCopyStorageEntity(SCNetworkInterfaceRef interface) 3635{ 3636 CFMutableDictionaryRef interface_entity = NULL; 3637 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 3638 CFBooleanRef active = NULL; 3639 CFStringRef bsdName = NULL; 3640 CFBooleanRef builtin = NULL; 3641 CFStringRef interfaceNamePrefix = NULL; 3642 CFNumberRef interfaceType = NULL; 3643 CFNumberRef interfaceUnit = NULL; 3644 CFDataRef macAddress = NULL; 3645 CFStringRef pathMatch = NULL; 3646 CFDictionaryRef info = NULL; 3647 CFStringRef type = NULL; 3648 3649 if (interfacePrivate->active) { 3650 active = kCFBooleanTrue; 3651 } 3652 3653 bsdName = SCNetworkInterfaceGetBSDName(interface); 3654 if (!isA_CFString(bsdName)) { 3655 goto done; 3656 } 3657 3658 builtin = interfacePrivate->builtin ? kCFBooleanTrue : kCFBooleanFalse; 3659 interfaceNamePrefix = _SCNetworkInterfaceGetIOInterfaceNamePrefix(interface); 3660 if (!isA_CFString(interfaceNamePrefix)) { 3661 goto done; 3662 } 3663 3664 interfaceType = _SCNetworkInterfaceGetIOInterfaceType(interface); 3665 if (!isA_CFNumber(interfaceType)) { 3666 goto done; 3667 } 3668 3669 interfaceUnit = _SCNetworkInterfaceGetIOInterfaceUnit(interface); 3670 if (!isA_CFNumber(interfaceUnit)) { 3671 goto done; 3672 } 3673 3674 macAddress = _SCNetworkInterfaceGetHardwareAddress(interface); 3675 if (!isA_CFData(macAddress)) { 3676 goto done; 3677 } 3678 3679 pathMatch = _SCNetworkInterfaceGetIOPath(interface); 3680 if (!isA_CFString(pathMatch)) { 3681 goto done; 3682 } 3683 3684 info = _SCNetworkInterfaceCopyInterfaceInfo(interface); 3685 if (!isA_CFDictionary(info)) { 3686 goto done; 3687 } 3688 3689 type = SCNetworkInterfaceGetInterfaceType(interface); 3690 if (!isA_CFString(type)) { 3691 goto done; 3692 } 3693 3694 interface_entity = CFDictionaryCreateMutable(NULL, 0, 3695 &kCFTypeDictionaryKeyCallBacks, 3696 &kCFTypeDictionaryValueCallBacks); 3697 3698 if (isA_CFBoolean(active) != NULL) { 3699 CFDictionaryAddValue(interface_entity, CFSTR(kSCNetworkInterfaceActive), active); 3700 } 3701 3702 CFDictionaryAddValue(interface_entity, CFSTR(kSCNetworkInterfaceBSDName), bsdName); 3703 CFDictionaryAddValue(interface_entity, CFSTR(kSCNetworkInterfaceIOBuiltin), builtin); 3704 CFDictionaryAddValue(interface_entity, CFSTR(kSCNetworkInterfaceIOInterfaceNamePrefix), interfaceNamePrefix); 3705 CFDictionaryAddValue(interface_entity, CFSTR(kSCNetworkInterfaceIOInterfaceType), interfaceType); 3706 CFDictionaryAddValue(interface_entity, CFSTR(kSCNetworkInterfaceIOInterfaceUnit), interfaceUnit); 3707 CFDictionaryAddValue(interface_entity, CFSTR(kSCNetworkInterfaceIOMACAddress), macAddress); 3708 CFDictionaryAddValue(interface_entity, CFSTR(kSCNetworkInterfaceIOPathMatch), pathMatch); 3709 CFDictionaryAddValue(interface_entity, CFSTR(kSCNetworkInterfaceInfo), info); 3710 CFDictionaryAddValue(interface_entity, CFSTR(kSCNetworkInterfaceType), type); 3711done: 3712 if (info != NULL) { 3713 CFRelease(info); 3714 } 3715 return interface_entity; 3716} 3717 3718 3719static void 3720__SCNetworkInterfaceSetService(SCNetworkInterfaceRef interface, 3721 SCNetworkServiceRef service) 3722{ 3723 SCNetworkInterfacePrivateRef interfacePrivate; 3724 SCNetworkServicePrivateRef servicePrivate; 3725 3726 interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 3727 if (interfacePrivate->prefs != NULL) { 3728 CFRelease(interfacePrivate->prefs); 3729 interfacePrivate->prefs = NULL; 3730 } 3731 if (interfacePrivate->serviceID != NULL) { 3732 CFRelease(interfacePrivate->serviceID); 3733 interfacePrivate->serviceID = NULL; 3734 } 3735 3736 servicePrivate = (SCNetworkServicePrivateRef)service; 3737 if (servicePrivate->prefs != NULL) { 3738 interfacePrivate->prefs = CFRetain(servicePrivate->prefs); 3739 } 3740 if (servicePrivate->serviceID != NULL) { 3741 interfacePrivate->serviceID = CFRetain(servicePrivate->serviceID); 3742 } 3743 3744 return; 3745} 3746 3747 3748__private_extern__ 3749Boolean 3750__SCNetworkInterfaceMatchesName(CFStringRef name, CFStringRef key) 3751{ 3752 Boolean match; 3753 CFStringRef str; 3754 3755 if (bundle == NULL) { 3756 SC_log(LOG_NOTICE, "no bundle information to compare interface names"); 3757 return FALSE; 3758 } 3759 3760 if (!isA_CFString(name)) { 3761 // if no interface "name" 3762 return FALSE; 3763 } 3764 3765 // check non-localized name for a match 3766 str = copy_interface_string(bundle, key, FALSE); 3767 if (str != NULL) { 3768 match = CFEqual(name, str); 3769 CFRelease(str); 3770 if (match) { 3771 return TRUE; 3772 } 3773 } 3774 3775 // check localized name for a match 3776 str = copy_interface_string(bundle, key, TRUE); 3777 if (str != NULL) { 3778 match = CFEqual(name, str); 3779 CFRelease(str); 3780 if (match) { 3781 return TRUE; 3782 } 3783 } 3784 3785 return FALSE; 3786} 3787 3788 3789#define kInterfaceTypeEthernetValue 6 3790#define kInterfaceTypeFirewireValue 144 3791 3792 3793static SCNetworkInterfaceRef 3794__SCNetworkInterfaceCreateWithStorageEntity(CFAllocatorRef allocator, 3795 CFDictionaryRef interface_entity) 3796{ 3797#pragma unused(allocator) 3798 SCNetworkInterfacePrivateRef interfacePrivate = NULL; 3799 CFBooleanRef active = NULL; 3800 CFStringRef bsdName = NULL; 3801 CFBooleanRef ioBuiltin = NULL; 3802 CFStringRef ioInterfaceNamePrefix = NULL; 3803 CFNumberRef ioInterfaceType = NULL; 3804 int ioInterfaceTypeNum; 3805 CFNumberRef ioInterfaceUnit = NULL; 3806 CFDataRef ioMACAddress = NULL; 3807 CFStringRef ioPathMatch = NULL; 3808 CFDictionaryRef SCNetworkInterfaceInfo = NULL; 3809 CFStringRef userDefinedName = NULL; 3810 CFStringRef usbProductName = NULL; 3811 CFNumberRef idProduct = NULL; 3812 CFNumberRef idVendor = NULL; 3813 CFStringRef type = NULL; 3814 3815 /* initialize runtime */ 3816 pthread_once(&initialized, __SCNetworkInterfaceInitialize); 3817 3818 if (isA_CFDictionary(interface_entity) == NULL) { 3819 SC_log(LOG_INFO, "No interface entity"); 3820 goto done; 3821 } 3822 active = CFDictionaryGetValue(interface_entity, CFSTR(kSCNetworkInterfaceActive)); 3823 if (isA_CFBoolean(active) == NULL) { 3824 active = kCFBooleanFalse; 3825 } 3826 bsdName = CFDictionaryGetValue(interface_entity, CFSTR(kSCNetworkInterfaceBSDName)); 3827 if (isA_CFString(bsdName) == NULL) { 3828 SC_log(LOG_INFO, "No BSD name"); 3829 goto done; 3830 } 3831 ioBuiltin = CFDictionaryGetValue(interface_entity, CFSTR(kSCNetworkInterfaceIOBuiltin)); 3832 if (isA_CFBoolean(ioBuiltin) == NULL) { 3833 SC_log(LOG_INFO, "No IOBuiltin property"); 3834 goto done; 3835 } 3836 ioInterfaceNamePrefix = CFDictionaryGetValue(interface_entity, CFSTR(kSCNetworkInterfaceIOInterfaceNamePrefix)); 3837 if (isA_CFString(ioInterfaceNamePrefix) == NULL) { 3838 ioInterfaceNamePrefix = _SCNetworkInterfaceCopyPrefixFromBSDName(bsdName); 3839 if (ioInterfaceNamePrefix == NULL) { 3840 SC_log(LOG_INFO, "No BSD interface name prefix"); 3841 goto done; 3842 } 3843 } else { 3844 CFRetain(ioInterfaceNamePrefix); 3845 } 3846 ioInterfaceType = CFDictionaryGetValue(interface_entity, CFSTR(kSCNetworkInterfaceIOInterfaceType)); 3847 if (isA_CFNumber(ioInterfaceType) == NULL) { 3848 SC_log(LOG_INFO, "No IOInterfaceType"); 3849 goto done; 3850 } 3851 if (!CFNumberGetValue(ioInterfaceType, kCFNumberIntType, &ioInterfaceTypeNum)) { 3852 SC_log(LOG_NOTICE, "Count not extract value from ioInterfaceType"); 3853 } 3854 ioInterfaceUnit = CFDictionaryGetValue(interface_entity, CFSTR(kSCNetworkInterfaceIOInterfaceUnit)); 3855 if (isA_CFNumber(ioInterfaceUnit) == NULL) { 3856 SC_log(LOG_INFO, "No IOInterfaceUnit"); 3857 3858 goto done; 3859 } 3860 ioMACAddress = CFDictionaryGetValue(interface_entity, CFSTR(kSCNetworkInterfaceIOMACAddress)); 3861 if (isA_CFData(ioMACAddress) == NULL) { 3862 SC_log(LOG_INFO, "No IOMACAddress"); 3863 goto done; 3864 } 3865 ioPathMatch = CFDictionaryGetValue(interface_entity, CFSTR(kSCNetworkInterfaceIOPathMatch)); 3866 if (isA_CFString(ioPathMatch) == NULL) { 3867 SC_log(LOG_INFO, "No IOPathMatch"); 3868 goto done; 3869 } else { 3870 // Check if Path contains the BSD Name in the end 3871 } 3872 SCNetworkInterfaceInfo = CFDictionaryGetValue(interface_entity, CFSTR(kSCNetworkInterfaceInfo)); 3873 if (isA_CFDictionary(SCNetworkInterfaceInfo) == NULL) { 3874 SC_log(LOG_INFO, "No SCNetworkInterfaceInfo"); 3875 goto done; 3876 } 3877 userDefinedName = CFDictionaryGetValue(SCNetworkInterfaceInfo, kSCPropUserDefinedName); 3878#if !TARGET_OS_SIMULATOR 3879 usbProductName = CFDictionaryGetValue(SCNetworkInterfaceInfo, CFSTR(kUSBProductString)); 3880 idProduct = CFDictionaryGetValue(SCNetworkInterfaceInfo, CFSTR(kUSBProductID)); 3881 idVendor = CFDictionaryGetValue(SCNetworkInterfaceInfo, CFSTR(kUSBVendorID)); 3882#endif // !TARGET_OS_SIMULATOR 3883 3884 type = CFDictionaryGetValue(interface_entity, CFSTR(kSCNetworkInterfaceType)); 3885 if (isA_CFString(type) == NULL) { 3886 SC_log(LOG_INFO, "No SCNetworkInterfaceType"); 3887 goto done; 3888 } 3889 3890 interfacePrivate = __SCNetworkInterfaceCreatePrivate(NULL, NULL, NULL, NULL); 3891 interfacePrivate->active = CFBooleanGetValue(active); 3892 interfacePrivate->entity_device = CFRetain(bsdName); 3893 interfacePrivate->builtin = CFBooleanGetValue(ioBuiltin); 3894 interfacePrivate->prefix = CFRetain(ioInterfaceNamePrefix); 3895 interfacePrivate->type = CFRetain(ioInterfaceType); 3896 interfacePrivate->unit = CFRetain(ioInterfaceUnit); 3897 interfacePrivate->address = CFRetain(ioMACAddress); 3898 interfacePrivate->path = CFRetain(ioPathMatch); 3899 interfacePrivate->name = ((userDefinedName != NULL) ? CFRetain(userDefinedName) : NULL); 3900 interfacePrivate->localized_name = ((userDefinedName != NULL) ? CFRetain(userDefinedName) : NULL); 3901 interfacePrivate->usb.name = ((usbProductName != NULL) ? CFRetain(usbProductName) : NULL); 3902 interfacePrivate->usb.pid = ((idProduct != NULL) ? CFRetain(idProduct) : NULL); 3903 interfacePrivate->usb.vid = ((idVendor != NULL) ? CFRetain(idVendor) : NULL); 3904 3905 // Handling interface types to be seen in NetworkInterfaces.plist 3906 CFIndex interfaceIndex; 3907 3908 interfaceIndex = findConfiguration(type); 3909 if (interfaceIndex != kCFNotFound) { 3910 interfacePrivate->interface_type = *configurations[interfaceIndex].interface_type; 3911 } else { 3912 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet; 3913 } 3914 3915 // Extracting entity type from value of interface type 3916 if (ioInterfaceTypeNum == kInterfaceTypeEthernetValue) { 3917 interfacePrivate->entity_type = kSCValNetInterfaceTypeEthernet; // kSCNetworkInterfaceTypeEthernet; 3918 } else if (ioInterfaceTypeNum == kInterfaceTypeFirewireValue) { 3919 interfacePrivate->entity_type = kSCValNetInterfaceTypeFireWire; 3920 } 3921done: 3922 if (ioInterfaceNamePrefix != NULL) { 3923 CFRelease(ioInterfaceNamePrefix); 3924 } 3925 3926 return (SCNetworkInterfaceRef)interfacePrivate; 3927} 3928 3929 3930__private_extern__ 3931void 3932_SCNetworkInterfaceCacheOpen(void) 3933{ 3934 if (!__SCNetworkInterfaceCacheIsOpen()) { 3935 S_interface_cache = CFDictionaryCreateMutable(NULL, 3936 0, 3937 &kCFTypeDictionaryKeyCallBacks, 3938 &kCFTypeDictionaryValueCallBacks); 3939 SC_log(LOG_DEBUG, "SCNetworkInterface cache (%p): open", S_interface_cache); 3940 } 3941} 3942 3943 3944__private_extern__ 3945void 3946_SCNetworkInterfaceCacheClose(void) 3947{ 3948 if (__SCNetworkInterfaceCacheIsOpen()) { 3949 SC_log(LOG_DEBUG, "SCNetworkInterface cache (%p): close", S_interface_cache); 3950 CFRelease(S_interface_cache); 3951 S_interface_cache = NULL; 3952 } 3953} 3954 3955 3956static void 3957__SCNetworkInterfaceCacheAdd(CFStringRef bsdName, CFArrayRef matchingInterfaces) 3958{ 3959 if (__SCNetworkInterfaceCacheIsOpen() && 3960 bsdName != NULL && 3961 matchingInterfaces != NULL) { 3962 SC_log(LOG_DEBUG, "SCNetworkInterface cache (%p): add %@", S_interface_cache, bsdName); 3963 CFDictionaryAddValue(S_interface_cache, bsdName, matchingInterfaces); 3964 } 3965} 3966 3967 3968static inline Boolean 3969__SCNetworkInterfaceCacheIsOpen(void) 3970{ 3971 return (S_interface_cache != NULL); 3972} 3973 3974 3975static CFArrayRef 3976__SCNetworkInterfaceCacheCopy(CFStringRef bsdName) 3977{ 3978 if (__SCNetworkInterfaceCacheIsOpen() && 3979 bsdName != NULL) { 3980 CFArrayRef matchingInterfaces = CFDictionaryGetValue(S_interface_cache, bsdName); 3981 if (matchingInterfaces) { 3982 CFRetain(matchingInterfaces); 3983 SC_log(LOG_DEBUG, "SCNetworkInterface cache (%p): copy w/ match for %@", S_interface_cache, bsdName); 3984 } else { 3985 SC_log(LOG_DEBUG, "SCNetworkInterface cache (%p): copy w/ no match for %@", S_interface_cache, bsdName); 3986 } 3987 3988 return matchingInterfaces; 3989 } 3990 3991 return NULL; 3992} 3993 3994 3995SCNetworkInterfaceRef 3996_SCNetworkInterfaceCreateWithEntity(CFAllocatorRef allocator, 3997 CFDictionaryRef interface_entity, 3998 SCNetworkServiceRef service) 3999{ 4000#pragma unused(allocator) 4001 SCNetworkInterfacePrivateRef interfacePrivate = NULL; 4002 CFStringRef ifDevice; 4003 CFStringRef ifName = NULL; 4004 CFStringRef ifSubType; 4005 CFStringRef ifType; 4006 CFStringRef ifUnique; 4007 CFArrayRef matching_interfaces = NULL; 4008 SCPreferencesRef servicePref = NULL; 4009 Boolean useSystemInterfaces = TRUE; 4010 4011 /* initialize runtime (and kSCNetworkInterfaceIPv4) */ 4012 pthread_once(&initialized, __SCNetworkInterfaceInitialize); 4013 4014 if (service != NULL) { 4015 servicePref = ((SCNetworkServicePrivateRef)service)->prefs; 4016 useSystemInterfaces = ((__SCPreferencesUsingDefaultPrefs(servicePref)) && 4017 (!__SCPreferencesGetLimitSCNetworkConfiguration(servicePref))); 4018 } 4019 4020 ifType = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceType); 4021 if (ifType == NULL) { 4022 /* 4023 * The interface "Type" was not specified. We'll make an 4024 * assumption that this is an "Ethernet" interface. If a 4025 * real interface exists with the provided interface name 4026 * then the actual type will be set accordingly. If not, we'll 4027 * end up crafting an "Ethernet" SCNetworkInterface that 4028 * will keep the rest of the configuration APIs happy. 4029 */ 4030 ifType = kSCValNetInterfaceTypeEthernet; 4031 } 4032 4033 if (!isA_CFString(ifType)) { 4034 return NULL; 4035 } 4036 4037 ifSubType = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceSubType); 4038 if (CFEqual(ifType, kSCValNetInterfaceTypePPP) || 4039 CFEqual(ifType, kSCValNetInterfaceTypeVPN)) { 4040 if (!isA_CFString(ifSubType)) { 4041 return NULL; 4042 } 4043 } 4044 4045 ifDevice = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceDeviceName); 4046 ifUnique = CFDictionaryGetValue(interface_entity, CFSTR("DeviceUniqueIdentifier")); 4047 4048 if (CFEqual(ifType, kSCValNetInterfaceTypeEthernet) || 4049 CFEqual(ifType, kSCValNetInterfaceTypeFireWire) || 4050 (CFEqual(ifType, kSCValNetInterfaceTypePPP) && CFEqual(ifSubType, kSCValNetInterfaceSubTypePPPoE))) { 4051 char bsdName[IFNAMSIZ]; 4052 CFMutableDictionaryRef matching; 4053 4054 if (!isA_CFString(ifDevice)) { 4055 return NULL; 4056 } 4057 4058 if (CFEqual(ifDevice, CFSTR("lo0"))) { // for _SCNetworkInterfaceCreateWithBSDName 4059 interfacePrivate = __SCNetworkInterfaceCreateCopy(NULL, kSCNetworkInterfaceLoopback, NULL, NULL); 4060 goto done; 4061 } 4062 if (useSystemInterfaces) { 4063 // Check to see if we already have the info in the cache 4064 matching_interfaces = __SCNetworkInterfaceCacheCopy(ifDevice); 4065 if (matching_interfaces == NULL) { 4066 if (_SC_cfstring_to_cstring(ifDevice, bsdName, sizeof(bsdName), kCFStringEncodingASCII) == NULL) { 4067 goto done; 4068 } 4069 4070 matching = IOBSDNameMatching(masterPort, 0, bsdName); 4071 if (matching == NULL) { 4072 goto done; 4073 } 4074 matching_interfaces = findMatchingInterfaces(matching, 4075 processNetworkInterface, 4076 kSCNetworkInterfaceHiddenInterfaceKey, 4077 TRUE); 4078 4079 __SCNetworkInterfaceCacheAdd(ifDevice, matching_interfaces); 4080 CFRelease(matching); 4081 } 4082 } 4083 } else if (CFEqual(ifType, kSCValNetInterfaceTypePPP)) { 4084 if (CFEqual(ifSubType, kSCValNetInterfaceSubTypePPPSerial)) { 4085 CFDictionaryRef matching; 4086 CFStringRef match_keys[2]; 4087 CFStringRef match_vals[2]; 4088 4089 if (!isA_CFString(ifDevice)) { 4090 return NULL; 4091 } 4092 4093 if (useSystemInterfaces) { 4094 match_keys[0] = CFSTR(kIOProviderClassKey); 4095 match_vals[0] = CFSTR(kIOSerialBSDServiceValue); 4096 4097 match_keys[1] = CFSTR(kIOTTYBaseNameKey); 4098 match_vals[1] = ifDevice; 4099 4100 matching = CFDictionaryCreate(NULL, 4101 (const void **)match_keys, 4102 (const void **)match_vals, 4103 sizeof(match_keys)/sizeof(match_keys[0]), 4104 &kCFTypeDictionaryKeyCallBacks, 4105 &kCFTypeDictionaryValueCallBacks); 4106 matching_interfaces = findMatchingInterfaces(matching, 4107 processSerialInterface, 4108 kSCNetworkInterfaceHiddenPortKey, 4109 TRUE); 4110 CFRelease(matching); 4111 } 4112 if (ifUnique == NULL) { 4113 CFIndex n; 4114 Boolean useDeviceName = TRUE; 4115 4116 n = (matching_interfaces != NULL) ? CFArrayGetCount(matching_interfaces) : 0; 4117 if (n > 0) { 4118 CFIndex i; 4119 4120 for (i = 0; i < n; i++) { 4121 SCNetworkInterfacePrivateRef scanPrivate; 4122 4123 scanPrivate = (SCNetworkInterfacePrivateRef)CFArrayGetValueAtIndex(matching_interfaces, i); 4124 if (scanPrivate->entity_device_unique != NULL) { 4125 useDeviceName = FALSE; 4126 break; 4127 } 4128 } 4129 } 4130 4131 if (useDeviceName && useSystemInterfaces) { 4132 if (matching_interfaces != NULL) { 4133 CFRelease(matching_interfaces); 4134 } 4135 4136 match_keys[1] = CFSTR(kIOTTYDeviceKey); 4137 matching = CFDictionaryCreate(NULL, 4138 (const void **)match_keys, 4139 (const void **)match_vals, 4140 sizeof(match_keys)/sizeof(match_keys[0]), 4141 &kCFTypeDictionaryKeyCallBacks, 4142 &kCFTypeDictionaryValueCallBacks); 4143 matching_interfaces = findMatchingInterfaces(matching, 4144 processSerialInterface, 4145 kSCNetworkInterfaceHiddenPortKey, 4146 TRUE); 4147 CFRelease(matching); 4148 } 4149 } 4150 } else if (CFEqual(ifSubType, kSCValNetInterfaceSubTypeL2TP)) { 4151 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4, 4152 kSCNetworkInterfaceTypeL2TP); 4153#pragma GCC diagnostic push 4154#pragma GCC diagnostic ignored "-Wdeprecated" 4155 } else if (CFEqual(ifSubType, kSCValNetInterfaceSubTypePPTP)) { 4156 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4, 4157 kSCNetworkInterfaceTypePPTP); 4158#pragma GCC diagnostic pop 4159 } else { 4160 // XXX do we allow non-Apple variants of PPP??? XXX 4161 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4, 4162 ifSubType); 4163 } 4164 } else if (CFEqual(ifType, kSCValNetInterfaceType6to4)) { 4165 if (!isA_CFString(ifDevice)) { 4166 return NULL; 4167 } 4168 4169 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4, 4170 kSCNetworkInterfaceType6to4); 4171 } else if (CFEqual(ifType, kSCValNetInterfaceTypeIPSec)) { 4172 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4, 4173 kSCNetworkInterfaceTypeIPSec); 4174 } else if (CFEqual(ifType, kSCValNetInterfaceTypeLoopback)) { 4175 interfacePrivate = __SCNetworkInterfaceCreateCopy(NULL, kSCNetworkInterfaceLoopback, NULL, NULL); 4176 } else if (CFEqual(ifType, kSCValNetInterfaceTypeVPN)) { 4177 if (CFStringFind(ifSubType, CFSTR("."), 0).location != kCFNotFound) { 4178 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4, 4179 ifSubType); 4180 } 4181 } else if ((CFStringFind(ifType, CFSTR("."), 0).location != kCFNotFound) && (ifDevice == NULL)) { 4182 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4, 4183 ifType); 4184 } 4185 4186 if (matching_interfaces != NULL) { 4187 CFIndex n; 4188 SCPreferencesRef prefs; 4189 Boolean temp_preferences = FALSE; 4190 4191 n = CFArrayGetCount(matching_interfaces); 4192 switch (n) { 4193 case 1 : 4194 interfacePrivate = (SCNetworkInterfacePrivateRef)CFArrayGetValueAtIndex(matching_interfaces, 0); 4195 if (_SC_CFEqual(ifUnique, interfacePrivate->entity_device_unique)) { 4196 // if the unique ID's match 4197 CFRetain(interfacePrivate); 4198 break; 4199 } 4200 4201 interfacePrivate = NULL; 4202 // fall through 4203 case 0 : 4204 if (!CFEqual(ifType, kSCValNetInterfaceTypeEthernet)) { 4205 break; 4206 } 4207 4208 if (CFDictionaryGetValueIfPresent(interface_entity, 4209 kSCPropUserDefinedName, 4210 (const void **)&ifName) && 4211 CFEqual(ifName, CFSTR(BT_PAN_NAME))) { 4212 break; 4213 } 4214 4215 prefs = (service != NULL) ? ((SCNetworkServicePrivateRef)service)->prefs : NULL; 4216 if (prefs == NULL) { 4217 prefs = SCPreferencesCreate(NULL, CFSTR("SCNetworkInterface"), NULL); 4218 if (prefs != NULL) { 4219 temp_preferences = TRUE; 4220 } 4221 } 4222 if (prefs == NULL) { 4223 break; 4224 } 4225#if !TARGET_OS_IPHONE 4226 if (!CFDictionaryContainsKey(interface_entity, CFSTR("_NO_BOND_INTERFACES_"))) { 4227 interfacePrivate = (SCNetworkInterfacePrivateRef)findBondInterface(prefs, ifDevice); 4228 } 4229#endif // !TARGET_OS_IPHONE 4230 if ((interfacePrivate == NULL) 4231 && !CFDictionaryContainsKey(interface_entity, CFSTR("_NO_BRIDGE_INTERFACES_"))) { 4232 interfacePrivate = (SCNetworkInterfacePrivateRef)findBridgeInterface(prefs, ifDevice); 4233 } 4234 4235 if ((interfacePrivate == NULL) 4236 && !CFDictionaryContainsKey(interface_entity, CFSTR("_NO_VLAN_INTERFACES_"))) { 4237 interfacePrivate = (SCNetworkInterfacePrivateRef)findVLANInterface(prefs, ifDevice); 4238 } 4239 if (temp_preferences) CFRelease(prefs); 4240 break; 4241 default : 4242 if (ifUnique != NULL) { 4243 CFIndex i; 4244 4245 // we are looking for an interface with a unique ID 4246 // so let's try to focus our choices 4247 for (i = 0; i < n; i++) { 4248 SCNetworkInterfacePrivateRef scanPrivate; 4249 4250 scanPrivate = (SCNetworkInterfacePrivateRef)CFArrayGetValueAtIndex(matching_interfaces, i); 4251 if (_SC_CFEqual(ifUnique, scanPrivate->entity_device_unique)) { 4252 if (interfacePrivate != NULL) { 4253 // if we've matched more than one interface 4254 interfacePrivate = NULL; 4255 break; 4256 } 4257 interfacePrivate = scanPrivate; 4258 } 4259 } 4260 } else if (CFDictionaryGetValueIfPresent(interface_entity, 4261 kSCPropUserDefinedName, 4262 (const void **)&ifName)) { 4263 CFIndex i; 4264 4265 // we don't have a unique ID but do have an interface 4266 // name. If the matching interfaces do have IDs than 4267 // we can try to focus our choices using the name 4268 for (i = 0; i < n; i++) { 4269 SCNetworkInterfacePrivateRef scanPrivate; 4270 4271 scanPrivate = (SCNetworkInterfacePrivateRef)CFArrayGetValueAtIndex(matching_interfaces, i); 4272 if (scanPrivate->entity_device_unique != NULL) { 4273 SCNetworkInterfaceRef scan = (SCNetworkInterfaceRef)scanPrivate; 4274 CFStringRef scanName; 4275 4276 scanName = __SCNetworkInterfaceGetNonLocalizedDisplayName(scan); 4277 if ((scanName != NULL) && !_SC_CFEqual(ifName, scanName)) { 4278 continue; // if not the same display name 4279 } 4280 } 4281 4282 if (interfacePrivate != NULL) { 4283 // if we've matched more than one interface 4284 interfacePrivate = NULL; 4285 break; 4286 } 4287 interfacePrivate = scanPrivate; 4288 } 4289 } 4290 if (interfacePrivate == NULL) { 4291 SC_log(LOG_NOTICE, "more than one interface matches %@", ifDevice); 4292 interfacePrivate = (SCNetworkInterfacePrivateRef)CFArrayGetValueAtIndex(matching_interfaces, 0); 4293 } 4294 CFRetain(interfacePrivate); 4295 break; 4296 } 4297 CFRelease(matching_interfaces); 4298 } 4299 4300 done : 4301 4302 if ((interfacePrivate == NULL) || !useSystemInterfaces) { 4303 /* 4304 * if device not present on this system 4305 */ 4306 if (!useSystemInterfaces) { 4307 if (interfacePrivate != NULL) { 4308 CFRelease(interfacePrivate); 4309 } 4310 } 4311 4312 interfacePrivate = __SCNetworkInterfaceCreatePrivate(NULL, NULL, NULL, NULL); 4313 interfacePrivate->entity_type = (ifType != NULL) ? ifType : NULL; 4314 interfacePrivate->entity_subtype = (ifSubType != NULL) ? ifSubType : NULL; 4315 interfacePrivate->entity_device = (ifDevice != NULL) ? CFStringCreateCopy(NULL, ifDevice) : NULL; 4316 interfacePrivate->entity_device_unique = (ifUnique != NULL) ? CFStringCreateCopy(NULL, ifUnique) : NULL; 4317 4318 // Using UserDefinedName to check the validity of preferences file 4319 // when useSystemInterfaces is FALSE 4320 if (!useSystemInterfaces) { 4321 CFStringRef userDefinedName = CFDictionaryGetValue(interface_entity, kSCPropUserDefinedName); 4322 if (isA_CFString(userDefinedName) != NULL) { 4323 CFRetain(userDefinedName); 4324 if (interfacePrivate->name != NULL) { 4325 CFRelease(interfacePrivate->name); 4326 } 4327 interfacePrivate->name = userDefinedName; 4328 4329 CFRetain(userDefinedName); 4330 if (interfacePrivate->localized_name != NULL) { 4331 CFRelease(interfacePrivate->localized_name); 4332 } 4333 interfacePrivate->localized_name = userDefinedName; 4334 } 4335 } 4336 4337 if (CFEqual(ifType, kSCValNetInterfaceTypeEthernet)) { 4338 CFStringRef entity_hardware; 4339 SCNetworkInterfaceRef virtualInterface; 4340 4341 if (!useSystemInterfaces && 4342 (((virtualInterface = findBridgeInterface(servicePref, ifDevice)) != NULL) || 4343#if !TARGET_OS_IPHONE 4344 ((virtualInterface = findBondInterface(servicePref, ifDevice)) != NULL) || 4345#endif // !TARGET_OS_IPHONE 4346 ((virtualInterface = findVLANInterface(servicePref, ifDevice)) != NULL))) { 4347 CFRelease(interfacePrivate); 4348 interfacePrivate = (SCNetworkInterfacePrivateRef)virtualInterface; 4349 } else { 4350 entity_hardware = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceHardware); 4351 if (isA_CFString((entity_hardware)) && 4352 CFEqual(entity_hardware, kSCEntNetAirPort)) { 4353 interfacePrivate->interface_type = kSCNetworkInterfaceTypeIEEE80211; 4354 interfacePrivate->localized_key = CFSTR("airport"); 4355 interfacePrivate->sort_order = kSortAirPort; 4356 } else { 4357 CFStringRef name; 4358 4359 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet; 4360 4361 name = CFDictionaryGetValue(interface_entity, kSCPropUserDefinedName); 4362 if (__SCNetworkInterfaceMatchesName(name, CFSTR("iPhone"))) { 4363 interfacePrivate->localized_key = CFSTR("iPhone"); 4364 interfacePrivate->sort_order = kSortTethered; 4365 } else if (__SCNetworkInterfaceMatchesName(name, CFSTR("iPad"))) { 4366 interfacePrivate->localized_key = CFSTR("iPad"); 4367 interfacePrivate->sort_order = kSortTethered; 4368 } else if (__SCNetworkInterfaceMatchesName(name, CFSTR("thunderbolt"))) { 4369 interfacePrivate->localized_key = CFSTR("thunderbolt"); 4370 interfacePrivate->sort_order = kSortThunderbolt; 4371 } else if (__SCNetworkInterfaceMatchesName(name, CFSTR("bluetooth-pan-gn"))) { 4372 interfacePrivate->localized_key = CFSTR("bluetooth-pan-gn"); 4373 interfacePrivate->sort_order = kSortBluetoothPAN_GN; 4374 } else if (__SCNetworkInterfaceMatchesName(name, CFSTR("bluetooth-pan-nap"))) { 4375 interfacePrivate->localized_key = CFSTR("bluetooth-pan-nap"); 4376 interfacePrivate->sort_order = kSortBluetoothPAN_NAP; 4377 } else if (__SCNetworkInterfaceMatchesName(name, CFSTR("bluetooth-pan-u"))) { 4378 interfacePrivate->localized_key = CFSTR("bluetooth-pan-u"); 4379 interfacePrivate->sort_order = kSortBluetoothPAN_U; 4380 } else { 4381 interfacePrivate->sort_order = kSortEthernet; 4382 } 4383 } 4384 } 4385 } else if (CFEqual(ifType, kSCValNetInterfaceTypeFireWire)) { 4386 interfacePrivate->interface_type = kSCNetworkInterfaceTypeFireWire; 4387 interfacePrivate->sort_order = kSortFireWire; 4388 } else if (CFEqual(ifType, kSCValNetInterfaceTypePPP) && (ifSubType != NULL)) { 4389 if (CFEqual(ifSubType, kSCValNetInterfaceSubTypePPPoE)) { 4390 CFStringRef entity_hardware; 4391 4392 entity_hardware = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceHardware); 4393 if (isA_CFString((entity_hardware)) && 4394 CFEqual(entity_hardware, kSCEntNetAirPort)) { 4395 interfacePrivate->interface_type = kSCNetworkInterfaceTypeIEEE80211; 4396 interfacePrivate->sort_order = kSortAirPort; 4397 } else { 4398 interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet; 4399 interfacePrivate->sort_order = kSortEthernet; 4400 } 4401 } else if (CFEqual(ifSubType, kSCValNetInterfaceSubTypePPPSerial)) { 4402 if (CFStringHasPrefix(ifDevice, CFSTR("Bluetooth"))) { 4403 interfacePrivate->interface_type = kSCNetworkInterfaceTypeBluetooth; 4404 interfacePrivate->sort_order = kSortBluetooth; 4405 } else if (CFStringHasPrefix(ifDevice, CFSTR("irda"))) { 4406 interfacePrivate->interface_type = kSCNetworkInterfaceTypeIrDA; 4407 interfacePrivate->sort_order = kSortIrDA; 4408 } else if (CFStringHasPrefix(ifDevice, CFSTR("wwan"))) { 4409 interfacePrivate->interface_type = kSCNetworkInterfaceTypeWWAN; 4410 interfacePrivate->sort_order = kSortWWAN; 4411 } else { 4412 interfacePrivate->interface_type = kSCNetworkInterfaceTypeModem; 4413 interfacePrivate->sort_order = kSortModem; 4414 } 4415 } else { 4416 SCNetworkInterfaceRef child; 4417 // PPTP, L2TP, ... 4418 CFRelease(interfacePrivate); 4419 child = SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4, ifSubType); 4420 interfacePrivate = (SCNetworkInterfacePrivateRef)child; 4421 if (interfacePrivate == NULL) { 4422 return NULL; 4423 } 4424 } 4425 } else if (CFEqual(ifType, kSCValNetInterfaceTypeVPN) && (ifSubType != NULL)) { 4426 SCNetworkInterfaceRef child; 4427 CFRelease(interfacePrivate); 4428 child = SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4, ifSubType); 4429 interfacePrivate = (SCNetworkInterfacePrivateRef)child; 4430 if (interfacePrivate == NULL) { 4431 return NULL; 4432 } 4433 } else if (CFEqual(ifType, kSCValNetInterfaceTypeIPSec)) { 4434 CFRelease(interfacePrivate); 4435 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4, 4436 kSCNetworkInterfaceTypeIPSec); 4437 } else if (CFEqual(ifType, kSCValNetInterfaceType6to4)) { 4438 CFRelease(interfacePrivate); 4439 if (!isA_CFString(ifDevice)) { 4440 return NULL; 4441 } 4442 interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4, 4443 kSCNetworkInterfaceType6to4); 4444 } else if (CFEqual(ifType, kSCValNetInterfaceTypeLoopback)) { 4445 CFRelease(interfacePrivate); 4446 interfacePrivate = __SCNetworkInterfaceCreateCopy(NULL, kSCNetworkInterfaceLoopback, NULL, NULL); 4447 } else if (CFStringFind(ifType, CFSTR("."), 0).location != kCFNotFound) { 4448 // if vendor interface 4449 pthread_mutex_lock(&lock); 4450 if (vendor_interface_types == NULL) { 4451 vendor_interface_types = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks); 4452 } 4453 CFSetAddValue(vendor_interface_types, ifType); 4454 interfacePrivate->interface_type = CFSetGetValue(vendor_interface_types, ifType); 4455 pthread_mutex_unlock(&lock); 4456 } else { 4457 // if unknown interface 4458 CFRelease(interfacePrivate); 4459 interfacePrivate = NULL; 4460 return NULL; 4461 } 4462 4463 if (CFDictionaryContainsKey(interface_entity, kSCNetworkInterfaceHiddenConfigurationKey)) { 4464 interfacePrivate->hidden = TRUE; 4465 } 4466#if TARGET_OS_IPHONE 4467 if (CFDictionaryContainsKey(interface_entity, kSCNetworkInterfaceTrustRequiredKey)) { 4468 interfacePrivate->trustRequired = TRUE; 4469 } 4470#endif // TARGET_OS_IPHONE 4471 } 4472 4473 if (service != NULL) { 4474 __SCNetworkInterfaceSetService((SCNetworkInterfaceRef)interfacePrivate, 4475 service); 4476 4477#if !TARGET_OS_IPHONE 4478 // set prefs & serviceID to Bond member interfaces 4479 if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeBond)) { 4480 CFIndex i; 4481 CFArrayRef members; 4482 CFIndex n; 4483 4484 members = SCBondInterfaceGetMemberInterfaces((SCNetworkInterfaceRef)interfacePrivate); 4485 n = (members != NULL) ? CFArrayGetCount(members) : 0; 4486 for (i = 0; i < n; i++) { 4487 SCNetworkInterfaceRef member; 4488 4489 member = CFArrayGetValueAtIndex(members, i); 4490 __SCNetworkInterfaceSetService(member, service); 4491 } 4492 } 4493#endif // !TARGET_OS_IPHONE 4494 4495 // set prefs & serviceID to Bridge member interfaces 4496 if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeBridge)) { 4497 CFIndex i; 4498 CFArrayRef members; 4499 CFIndex n; 4500 4501 members = SCBridgeInterfaceGetMemberInterfaces((SCNetworkInterfaceRef)interfacePrivate); 4502 n = (members != NULL) ? CFArrayGetCount(members) : 0; 4503 for (i = 0; i < n; i++) { 4504 SCNetworkInterfaceRef member; 4505 4506 member = CFArrayGetValueAtIndex(members, i); 4507 __SCNetworkInterfaceSetService(member, service); 4508 } 4509 } 4510 // set prefs & serviceID to VLAN pyhsical interface 4511 if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeVLAN)) { 4512 SCNetworkInterfaceRef vlan_physical; 4513 4514 vlan_physical = SCVLANInterfaceGetPhysicalInterface((SCNetworkInterfaceRef)interfacePrivate); 4515 if (vlan_physical != NULL) { 4516 __SCNetworkInterfaceSetService(vlan_physical, service); 4517 } 4518 } 4519 } 4520 4521 if (CFEqual(ifType, kSCValNetInterfaceTypePPP)) { 4522 SCNetworkInterfaceRef parent; 4523 4524 // create parent 4525 parent = SCNetworkInterfaceCreateWithInterface((SCNetworkInterfaceRef)interfacePrivate, 4526 kSCNetworkInterfaceTypePPP); 4527 CFRelease(interfacePrivate); 4528 interfacePrivate = (SCNetworkInterfacePrivateRef)parent; 4529 } else if (CFEqual(ifType, kSCValNetInterfaceTypeVPN)) { 4530 SCNetworkInterfaceRef parent; 4531 4532 // create parent 4533 parent = SCNetworkInterfaceCreateWithInterface((SCNetworkInterfaceRef)interfacePrivate, 4534 kSCNetworkInterfaceTypeVPN); 4535 CFRelease(interfacePrivate); 4536 interfacePrivate = (SCNetworkInterfacePrivateRef)parent; 4537 } 4538 4539 return (SCNetworkInterfaceRef)interfacePrivate; 4540} 4541 4542 4543#pragma mark - 4544#pragma mark SCNetworkInterface APIs 4545 4546 4547__private_extern__ 4548CFArrayRef 4549__SCNetworkInterfaceCopyAll_IONetworkInterface(Boolean keep_pre_configured) 4550{ 4551 CFDictionaryRef matching; 4552 CFArrayRef new_interfaces; 4553 4554 // get Ethernet, Firewire, Thunderbolt, and AirPort interfaces 4555 4556 matching = IOServiceMatching(kIONetworkInterfaceClass); 4557 new_interfaces = findMatchingInterfaces(matching, 4558 processNetworkInterface, 4559 kSCNetworkInterfaceHiddenInterfaceKey, 4560 keep_pre_configured); 4561 CFRelease(matching); 4562 4563 return new_interfaces; 4564} 4565 4566 4567static 4568CFArrayRef 4569__SCNetworkInterfaceCopyAll_Modem() 4570{ 4571 CFDictionaryRef matching; 4572 CFStringRef match_keys[2]; 4573 CFStringRef match_vals[2]; 4574 CFArrayRef new_interfaces; 4575 4576 match_keys[0] = CFSTR(kIOProviderClassKey); 4577 match_vals[0] = CFSTR(kIOSerialBSDServiceValue); 4578 4579 match_keys[1] = CFSTR(kIOSerialBSDTypeKey); 4580 match_vals[1] = CFSTR(kIOSerialBSDModemType); 4581 4582 matching = CFDictionaryCreate(NULL, 4583 (const void **)match_keys, 4584 (const void **)match_vals, 4585 sizeof(match_keys)/sizeof(match_keys[0]), 4586 &kCFTypeDictionaryKeyCallBacks, 4587 &kCFTypeDictionaryValueCallBacks); 4588 new_interfaces = findMatchingInterfaces(matching, 4589 processSerialInterface, 4590 kSCNetworkInterfaceHiddenPortKey, 4591 FALSE); 4592 CFRelease(matching); 4593 4594 return new_interfaces; 4595} 4596 4597 4598static 4599CFArrayRef 4600__SCNetworkInterfaceCopyAll_RS232() 4601{ 4602 CFDictionaryRef matching; 4603 CFStringRef match_keys[2]; 4604 CFStringRef match_vals[2]; 4605 CFArrayRef new_interfaces; 4606 4607 match_keys[0] = CFSTR(kIOProviderClassKey); 4608 match_vals[0] = CFSTR(kIOSerialBSDServiceValue); 4609 4610 match_keys[1] = CFSTR(kIOSerialBSDTypeKey); 4611 match_vals[1] = CFSTR(kIOSerialBSDRS232Type); 4612 4613 matching = CFDictionaryCreate(NULL, 4614 (const void **)match_keys, 4615 (const void **)match_vals, 4616 sizeof(match_keys)/sizeof(match_keys[0]), 4617 &kCFTypeDictionaryKeyCallBacks, 4618 &kCFTypeDictionaryValueCallBacks); 4619 new_interfaces = findMatchingInterfaces(matching, 4620 processSerialInterface, 4621 kSCNetworkInterfaceHiddenPortKey, 4622 FALSE); 4623 CFRelease(matching); 4624 4625 return new_interfaces; 4626} 4627 4628 4629#if !TARGET_OS_IPHONE 4630static void 4631addBTPANInterface(CFMutableArrayRef all_interfaces) 4632{ 4633 CFIndex i; 4634 SCNetworkInterfaceRef interface; 4635 CFIndex n; 4636 4637 n = CFArrayGetCount(all_interfaces); 4638 for (i = 0; i < n; i++) { 4639 SCNetworkInterfaceRef interface; 4640 4641 interface = CFArrayGetValueAtIndex(all_interfaces, i); 4642 if (_SCNetworkInterfaceIsBluetoothPAN(interface)) { 4643 // if we already have a BT-PAN interface 4644 return; 4645 } 4646 } 4647 4648 interface = _SCNetworkInterfaceCopyBTPANInterface(); 4649 if (interface != NULL) { 4650 // include BT-PAN interface 4651 CFArrayAppendValue(all_interfaces, interface); 4652 CFRelease(interface); 4653 } 4654 4655 return; 4656} 4657#endif // !TARGET_OS_IPHONE 4658 4659 4660static void 4661add_interfaces(CFMutableArrayRef all_interfaces, CFArrayRef new_interfaces) 4662{ 4663 CFIndex i; 4664 CFIndex n; 4665 4666 n = CFArrayGetCount(new_interfaces); 4667 for (i = 0; i < n; i++) { 4668 CFStringRef bsdName; 4669 SCNetworkInterfaceRef interface; 4670 4671 interface = CFArrayGetValueAtIndex(new_interfaces, i); 4672 bsdName = SCNetworkInterfaceGetBSDName(interface); 4673 if (bsdName != NULL) { 4674 CFArrayAppendValue(all_interfaces, interface); 4675 } 4676 } 4677 4678 return; 4679} 4680 4681 4682static void 4683__waitForInterfaces() 4684{ 4685 CFStringRef key = NULL; 4686 CFArrayRef keys; 4687 Boolean ok; 4688 SCDynamicStoreRef store = NULL; 4689 4690 CRSetCrashLogMessage("Waiting for IOKit to quiesce (or timeout)"); 4691 4692 store = SCDynamicStoreCreate(NULL, CFSTR("SCNetworkInterfaceCopyAll"), NULL, NULL); 4693 if (store == NULL) { 4694 goto done; 4695 } 4696 4697 key = SCDynamicStoreKeyCreate(NULL, CFSTR("%@" "InterfaceNamer"), kSCDynamicStoreDomainPlugin); 4698 keys = CFArrayCreate(NULL, (const void **)&key, 1, &kCFTypeArrayCallBacks); 4699 ok = SCDynamicStoreSetNotificationKeys(store, keys, NULL); 4700 CFRelease(keys); 4701 if (!ok) { 4702 SC_log(LOG_NOTICE, "SCDynamicStoreSetNotificationKeys() failed: %s", SCErrorString(SCError())); 4703 goto done; 4704 } 4705 4706 while (TRUE) { 4707 CFArrayRef changedKeys; 4708 CFDictionaryRef dict; 4709 Boolean quiet = FALSE; 4710 4711 // check if quiet 4712 dict = SCDynamicStoreCopyValue(store, key); 4713 if (dict != NULL) { 4714 if (isA_CFDictionary(dict) && 4715 (CFDictionaryContainsKey(dict, kInterfaceNamerKey_Quiet) || 4716 CFDictionaryContainsKey(dict, kInterfaceNamerKey_Timeout))) { 4717 quiet = TRUE; 4718 } 4719 CFRelease(dict); 4720 } 4721 if (quiet) { 4722 break; 4723 } 4724 4725 ok = SCDynamicStoreNotifyWait(store); 4726 if (!ok) { 4727 SC_log(LOG_NOTICE, "SCDynamicStoreNotifyWait() failed: %s", SCErrorString(SCError())); 4728 goto done; 4729 } 4730 4731 changedKeys = SCDynamicStoreCopyNotifiedKeys(store); 4732 if (changedKeys != NULL) { 4733 CFRelease(changedKeys); 4734 } 4735 } 4736 4737 done : 4738 4739 CRSetCrashLogMessage(NULL); 4740 4741 if (key != NULL) CFRelease(key); 4742 if (store != NULL) CFRelease(store); 4743 return; 4744} 4745 4746 4747CFArrayRef /* of SCNetworkInterfaceRef's */ 4748_SCNetworkInterfaceCopyAllWithPreferences(SCPreferencesRef prefs) 4749{ 4750 CFMutableArrayRef all_interfaces; 4751 CFArrayRef new_interfaces; 4752 Boolean temp_preferences = FALSE; 4753 4754 /* initialize runtime */ 4755 pthread_once(&initialized, __SCNetworkInterfaceInitialize); 4756 4757 /* wait for IOKit to quiesce */ 4758 pthread_once(&iokit_quiet, __waitForInterfaces); 4759 4760 all_interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 4761 4762 // get Ethernet, Firewire, Thunderbolt, and AirPort interfaces 4763 new_interfaces = __SCNetworkInterfaceCopyAll_IONetworkInterface(FALSE); 4764 if (new_interfaces != NULL) { 4765 add_interfaces(all_interfaces, new_interfaces); 4766 CFRelease(new_interfaces); 4767 } 4768 4769 // get Modem interfaces 4770 new_interfaces = __SCNetworkInterfaceCopyAll_Modem(); 4771 if (new_interfaces != NULL) { 4772 add_interfaces(all_interfaces, new_interfaces); 4773 CFRelease(new_interfaces); 4774 } 4775 4776 // get serial (RS232) interfaces 4777 new_interfaces = __SCNetworkInterfaceCopyAll_RS232(); 4778 if (new_interfaces != NULL) { 4779 add_interfaces(all_interfaces, new_interfaces); 4780 CFRelease(new_interfaces); 4781 } 4782 4783 // get virtual network interfaces (Bond, Bridge, VLAN) 4784 if (prefs == NULL) { 4785 prefs = SCPreferencesCreate(NULL, CFSTR("SCNetworkInterfaceCopyAll"), NULL); 4786 if (prefs != NULL) { 4787 temp_preferences = TRUE; 4788 } 4789 } 4790 if (prefs != NULL) { 4791#if !TARGET_OS_IPHONE 4792 new_interfaces = SCBondInterfaceCopyAll(prefs); 4793 if (new_interfaces != NULL) { 4794 add_interfaces(all_interfaces, new_interfaces); 4795 CFRelease(new_interfaces); 4796 } 4797#endif // !TARGET_OS_IPHONE 4798 4799 new_interfaces = SCBridgeInterfaceCopyAll(prefs); 4800 if (new_interfaces != NULL) { 4801 add_interfaces(all_interfaces, new_interfaces); 4802 CFRelease(new_interfaces); 4803 } 4804 4805 new_interfaces = SCVLANInterfaceCopyAll(prefs); 4806 if (new_interfaces != NULL) { 4807 add_interfaces(all_interfaces, new_interfaces); 4808 CFRelease(new_interfaces); 4809 } 4810 4811#if !TARGET_OS_IPHONE 4812 // add BT-PAN interface 4813 addBTPANInterface(all_interfaces); 4814#endif // !TARGET_OS_IPHONE 4815 4816 if (temp_preferences) CFRelease(prefs); 4817 } 4818 4819 // all interfaces have been identified, order and return 4820 sort_interfaces(all_interfaces); 4821 4822 return all_interfaces; 4823} 4824 4825 4826CFArrayRef /* of SCNetworkInterfaceRef's */ 4827SCNetworkInterfaceCopyAll() 4828{ 4829 CFArrayRef all_interfaces; 4830 4831 all_interfaces = _SCNetworkInterfaceCopyAllWithPreferences(NULL); 4832 return all_interfaces; 4833} 4834 4835 4836CFArrayRef /* of kSCNetworkInterfaceTypeXXX CFStringRef's */ 4837SCNetworkInterfaceGetSupportedInterfaceTypes(SCNetworkInterfaceRef interface) 4838{ 4839 CFIndex i; 4840 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 4841 4842 if (!isA_SCNetworkInterface(interface)) { 4843 _SCErrorSet(kSCStatusInvalidArgument); 4844 return NULL; 4845 } 4846 4847 if (interfacePrivate->supported_interface_types != NULL) { 4848 goto done; 4849 } 4850 4851 i = findConfiguration(interfacePrivate->interface_type); 4852 if (i != kCFNotFound) { 4853 if (configurations[i].supported_interfaces != doNone) { 4854 interfacePrivate->supported_interface_types = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 4855 if (configurations[i].supported_interfaces & do6to4) { 4856 CFArrayAppendValue(interfacePrivate->supported_interface_types, kSCNetworkInterfaceType6to4); 4857 } 4858 if (configurations[i].supported_interfaces & doL2TP) { 4859 CFArrayAppendValue(interfacePrivate->supported_interface_types, kSCNetworkInterfaceTypeL2TP); 4860 } 4861 if (configurations[i].supported_interfaces & doPPP) { 4862 CFArrayAppendValue(interfacePrivate->supported_interface_types, kSCNetworkInterfaceTypePPP); 4863 } 4864 if (configurations[i].supported_interfaces & doIPSec) { 4865 CFArrayAppendValue(interfacePrivate->supported_interface_types, kSCNetworkInterfaceTypeIPSec); 4866 } 4867 } 4868 } else { 4869 SCNetworkInterfaceRef child; 4870 4871 child = SCNetworkInterfaceGetInterface(interface); 4872 if ((child != NULL) && CFEqual(child, kSCNetworkInterfaceIPv4)) { 4873 interfacePrivate->supported_interface_types = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 4874 CFArrayAppendValue(interfacePrivate->supported_interface_types, kSCNetworkInterfaceTypeVPN); 4875 } 4876 } 4877 4878 done : 4879 4880 return interfacePrivate->supported_interface_types; 4881} 4882 4883 4884CFArrayRef /* of kSCNetworkProtocolTypeXXX CFStringRef's */ 4885SCNetworkInterfaceGetSupportedProtocolTypes(SCNetworkInterfaceRef interface) 4886{ 4887 CFIndex i; 4888 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 4889 4890 if (!isA_SCNetworkInterface(interface)) { 4891 _SCErrorSet(kSCStatusInvalidArgument); 4892 return NULL; 4893 } 4894 4895 if (interfacePrivate->supported_protocol_types != NULL) { 4896 goto done; 4897 } 4898 4899 i = findConfiguration(interfacePrivate->interface_type); 4900 if (i != kCFNotFound) { 4901 if (configurations[i].supported_protocols != doNone) { 4902 interfacePrivate->supported_protocol_types = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 4903 if (configurations[i].supported_protocols & doDNS) { 4904 CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeDNS); 4905 } 4906 if (configurations[i].supported_protocols & doIPv4) { 4907 CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeIPv4); 4908 } 4909 if (configurations[i].supported_protocols & doIPv6) { 4910 CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeIPv6); 4911 } 4912 if (configurations[i].supported_protocols & doProxies) { 4913 CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeProxies); 4914 } 4915#if !TARGET_OS_IPHONE 4916 if (configurations[i].supported_protocols & doSMB) { 4917 CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeSMB); 4918 } 4919#endif // !TARGET_OS_IPHONE 4920 } 4921 } 4922 4923 done : 4924 4925 return interfacePrivate->supported_protocol_types; 4926} 4927 4928 4929SCNetworkInterfaceRef 4930SCNetworkInterfaceCreateWithInterface(SCNetworkInterfaceRef child, CFStringRef interfaceType) 4931{ 4932 SCNetworkInterfacePrivateRef childPrivate = (SCNetworkInterfacePrivateRef)child; 4933 CFIndex childIndex; 4934 SCNetworkInterfacePrivateRef parentPrivate; 4935 4936 if (!isA_SCNetworkInterface(child)) { 4937 _SCErrorSet(kSCStatusInvalidArgument); 4938 return NULL; 4939 } 4940 4941 if (!isA_CFString(interfaceType)) { 4942 _SCErrorSet(kSCStatusInvalidArgument); 4943 return NULL; 4944 } 4945 4946 if (CFEqual(child, kSCNetworkInterfaceLoopback)) { 4947 // can't layer on top of loopback 4948 _SCErrorSet(kSCStatusInvalidArgument); 4949 return NULL; 4950 } 4951 4952 childIndex = findConfiguration(childPrivate->interface_type); 4953 4954 parentPrivate = __SCNetworkInterfaceCreatePrivate(NULL, 4955 child, 4956 childPrivate->prefs, 4957 childPrivate->serviceID); 4958 if (parentPrivate == NULL) { 4959 _SCErrorSet(kSCStatusFailed); 4960 return NULL; 4961 } 4962 4963 if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) { 4964 parentPrivate->interface_type = kSCNetworkInterfaceTypePPP; 4965 parentPrivate->entity_type = kSCValNetInterfaceTypePPP; 4966 4967 // entity subtype 4968 if (childIndex != kCFNotFound) { 4969 if (configurations[childIndex].ppp_subtype != NULL) { 4970 parentPrivate->entity_subtype = *configurations[childIndex].ppp_subtype; 4971 } else { 4972 // sorry, the child interface does not support PPP 4973 goto fail; 4974 } 4975 } else { 4976 // if the child's interface type not known, use the child entities "Type" 4977 parentPrivate->entity_subtype = childPrivate->entity_type; 4978 } 4979 4980 if (childPrivate->entity_device != NULL) { 4981 parentPrivate->entity_device = CFStringCreateCopy(NULL, childPrivate->entity_device); 4982 } 4983 4984 if (childPrivate->entity_device_unique != NULL) { 4985 parentPrivate->entity_device_unique = CFStringCreateCopy(NULL, childPrivate->entity_device_unique); 4986 } 4987 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeL2TP)) { 4988 if ((childIndex == kCFNotFound) || 4989 ((configurations[childIndex].supported_interfaces & doL2TP) != doL2TP)) { 4990 // if the child interface does not support L2TP 4991 goto fail; 4992 } 4993 parentPrivate->interface_type = kSCNetworkInterfaceTypeL2TP; 4994 parentPrivate->localized_key = CFSTR("l2tp"); 4995 parentPrivate->entity_type = kSCEntNetL2TP; // interface config goes into "L2TP" 4996#pragma GCC diagnostic push 4997#pragma GCC diagnostic ignored "-Wdeprecated" 4998 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPTP)) { 4999 if ((childIndex == kCFNotFound) || 5000 ((configurations[childIndex].supported_interfaces & doPPTP) != doPPTP)) { 5001 // if the child interface does not support PPTP 5002 goto fail; 5003 } 5004 parentPrivate->interface_type = kSCNetworkInterfaceTypePPTP; 5005 parentPrivate->localized_key = CFSTR("pptp"); 5006 parentPrivate->entity_type = kSCEntNetPPTP; // interface config goes into "PPTP" 5007#pragma GCC diagnostic pop 5008 } else if (CFEqual(interfaceType, kSCNetworkInterfaceType6to4)) { 5009 if ((childIndex == kCFNotFound) || 5010 ((configurations[childIndex].supported_interfaces & do6to4) != do6to4)) { 5011 // if the child interface does not support 6to4 5012 goto fail; 5013 } 5014 5015 parentPrivate->interface_type = kSCNetworkInterfaceType6to4; 5016 parentPrivate->localized_key = CFSTR("6to4"); 5017 parentPrivate->entity_type = kSCValNetInterfaceType6to4; 5018 parentPrivate->entity_device = CFRetain(CFSTR("stf0")); 5019 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeIPSec)) { 5020 if ((childIndex == kCFNotFound) || 5021 ((configurations[childIndex].supported_interfaces & doIPSec) != doIPSec)) { 5022 // if the child interface does not support IPSec 5023 goto fail; 5024 } 5025 parentPrivate->interface_type = kSCNetworkInterfaceTypeIPSec; 5026 parentPrivate->localized_key = CFSTR("ipsec"); 5027 parentPrivate->entity_type = kSCValNetInterfaceTypeIPSec; 5028 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeVPN)) { 5029 if (childIndex != kCFNotFound) { 5030 // if not a "vendor" child interface 5031 goto fail; 5032 } 5033 5034 parentPrivate->interface_type = kSCNetworkInterfaceTypeVPN; 5035 parentPrivate->localized_key = CFSTR("vpn"); 5036 parentPrivate->localized_arg1 = CFRetain(childPrivate->entity_type); 5037 parentPrivate->entity_type = kSCValNetInterfaceTypeVPN; 5038 parentPrivate->entity_subtype = childPrivate->entity_type; 5039 if (childPrivate->entity_device != NULL) { 5040 parentPrivate->entity_device = CFStringCreateCopy(NULL, childPrivate->entity_device); 5041 } 5042 if (parentPrivate->entity_subtype != NULL) { 5043 CFArrayRef components; 5044 CFIndex n; 5045 CFStringRef vpnType; 5046 5047 // 5048 // the "default" interface name is derived from the VPN type 5049 // 5050 // e.g. 5051 // com.apple.Apple-VPN.vpnplugin --> "Apple VPN" 5052 // ^^^^^^^^^ 5053 // 5054 vpnType = parentPrivate->entity_subtype; 5055 components = CFStringCreateArrayBySeparatingStrings(NULL, vpnType, CFSTR(".")); 5056 n = CFArrayGetCount(components); 5057 if ((n >= 4) && 5058 CFEqual(CFArrayGetValueAtIndex(components, n - 1), CFSTR("vpnplugin"))) { 5059 CFMutableStringRef str; 5060 5061 str = CFStringCreateMutableCopy(NULL, 5062 0, 5063 CFArrayGetValueAtIndex(components, n - 2)); 5064 (void) CFStringFindAndReplace(str, 5065 CFSTR("-"), 5066 CFSTR(" "), 5067 CFRangeMake(0, CFStringGetLength(str)), 5068 0); 5069 parentPrivate->localized_name = str; 5070 } 5071 CFRelease(components); 5072 } 5073 } else if (CFStringFind(interfaceType, CFSTR("."), 0).location != kCFNotFound) { 5074 // if custom interface type 5075 pthread_mutex_lock(&lock); 5076 if (vendor_interface_types == NULL) { 5077 vendor_interface_types = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks); 5078 } 5079 CFSetAddValue(vendor_interface_types, interfaceType); 5080 parentPrivate->interface_type = CFSetGetValue(vendor_interface_types, interfaceType); 5081 pthread_mutex_unlock(&lock); 5082 5083 parentPrivate->entity_type = parentPrivate->interface_type; // interface config goes into a 5084 // a dictionary with the same 5085 // name as the interfaceType 5086 } else { 5087 // unknown interface type 5088 goto fail; 5089 } 5090 5091 parentPrivate->hidden = childPrivate->hidden; 5092 5093#if TARGET_OS_IPHONE 5094 parentPrivate->trustRequired = childPrivate->trustRequired; 5095#endif // TARGET_OS_IPHONE 5096 5097 if (childPrivate->overrides != NULL) { 5098 parentPrivate->overrides = CFDictionaryCreateMutableCopy(NULL, 0, childPrivate->overrides); 5099 } 5100 5101 // The following change handles the case where a user has both an Ethernet and 5102 // PPPoE network service. Because a PPPoE service is typically associated with 5103 // an ISP we want it to be sorted higher in the service order. 5104 if ((parentPrivate->entity_subtype != NULL) && 5105 (CFEqual(parentPrivate->entity_subtype, kSCValNetInterfaceSubTypePPPoE))) { 5106 if ((childPrivate->interface_type != NULL) && 5107 (CFEqual(childPrivate->interface_type, kSCNetworkInterfaceTypeIEEE80211))) { 5108 parentPrivate->sort_order = kSortAirportPPP; 5109 } else { 5110 parentPrivate->sort_order = kSortEthernetPPP; 5111 } 5112 } else { 5113 // set sort order of the parent to match the child interface 5114 parentPrivate->sort_order = childPrivate->sort_order; 5115 } 5116 5117 return (SCNetworkInterfaceRef)parentPrivate; 5118 5119 fail : 5120 5121 CFRelease(parentPrivate); 5122 _SCErrorSet(kSCStatusInvalidArgument); 5123 return NULL; 5124} 5125 5126 5127__private_extern__ 5128CFDictionaryRef 5129__SCNetworkInterfaceGetDefaultConfiguration(SCNetworkSetRef set, SCNetworkInterfaceRef interface) 5130{ 5131 CFDictionaryRef config = NULL; 5132 CFStringRef defaultType; 5133 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 5134 5135 /* initialize runtime (and kSCNetworkInterfaceIPv4) */ 5136 pthread_once(&initialized, __SCNetworkInterfaceInitialize); 5137 5138 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface); 5139 if (defaultType != NULL) { 5140 if (set != NULL) { 5141 CFStringRef path; 5142 5143 path = SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL, // allocator 5144 SCNetworkSetGetSetID(set), // set 5145 interfacePrivate->entity_device, // interface 5146 defaultType); // entity 5147 if (path != NULL) { 5148 config = __getPrefsConfiguration(interfacePrivate->prefs, path); 5149 CFRelease(path); 5150 5151 if (config == NULL) { 5152 // if the "set" does not have a saved configuration, use 5153 // the [template] "interface" configuration 5154 if (interfacePrivate->unsaved != NULL) { 5155 config = CFDictionaryGetValue(interfacePrivate->unsaved, defaultType); 5156 if (config == (CFDictionaryRef)kCFNull) { 5157 config = NULL; 5158 } 5159 } 5160 } 5161 if (isA_CFDictionary(config) && (CFDictionaryGetCount(config) == 0)) { 5162 config = NULL; 5163 } 5164 } 5165 } 5166 } 5167 5168 return config; 5169} 5170 5171 5172static CFDictionaryRef 5173__SCNetworkInterfaceGetConfiguration(SCNetworkInterfaceRef interface, 5174 CFStringRef extendedType) 5175{ 5176 CFDictionaryRef config = NULL; 5177 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 5178 CFArrayRef paths; 5179 5180 /* initialize runtime (and kSCNetworkInterfaceIPv4) */ 5181 pthread_once(&initialized, __SCNetworkInterfaceInitialize); 5182 5183 paths = copyConfigurationPaths(interfacePrivate, extendedType); 5184 if (paths != NULL) { 5185 CFStringRef path; 5186 5187 path = CFArrayGetValueAtIndex(paths, 0); 5188 config = __getPrefsConfiguration(interfacePrivate->prefs, path); 5189 5190 CFRelease(paths); 5191 } else { 5192 if (interfacePrivate->unsaved != NULL) { 5193 config = CFDictionaryGetValue(interfacePrivate->unsaved, extendedType); 5194 if (config == (CFDictionaryRef)kCFNull) { 5195 config = NULL; 5196 } 5197 } 5198 } 5199 5200 if (isA_CFDictionary(config) && (CFDictionaryGetCount(config) == 0)) { 5201 config = NULL; 5202 } 5203 5204 return config; 5205} 5206 5207 5208CFDictionaryRef 5209SCNetworkInterfaceGetConfiguration(SCNetworkInterfaceRef interface) 5210{ 5211 CFDictionaryRef config; 5212 CFStringRef defaultType; 5213 5214 if (!isA_SCNetworkInterface(interface)) { 5215 _SCErrorSet(kSCStatusInvalidArgument); 5216 return NULL; 5217 } 5218 5219 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface); 5220 if (defaultType == NULL) { 5221 return NULL; 5222 } 5223 5224 config = __SCNetworkInterfaceGetConfiguration(interface, defaultType); 5225 if (config == NULL) { 5226 if (CFEqual(defaultType, kSCEntNetAirPort)) { 5227 SCNetworkInterfacePrivateRef interfacePrivate; 5228 CFStringRef path; 5229 5230 // if AirPort interface, check for a per-service config 5231 interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 5232 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator 5233 interfacePrivate->serviceID, // service 5234 kSCEntNetAirPort); // entity 5235 config = __getPrefsConfiguration(interfacePrivate->prefs, path); 5236 CFRelease(path); 5237 } 5238 } 5239 if (config == NULL) { 5240 _SCErrorSet(kSCStatusOK); 5241 } 5242 5243 return config; 5244} 5245 5246 5247CFDictionaryRef 5248SCNetworkInterfaceGetExtendedConfiguration(SCNetworkInterfaceRef interface, 5249 CFStringRef extendedType) 5250{ 5251 CFDictionaryRef config; 5252 5253 if (!isA_SCNetworkInterface(interface)) { 5254 _SCErrorSet(kSCStatusInvalidArgument); 5255 return NULL; 5256 } 5257 5258 if (!__SCNetworkInterfaceIsValidExtendedConfigurationType(interface, extendedType, TRUE)) { 5259 _SCErrorSet(kSCStatusInvalidArgument); 5260 return NULL; 5261 } 5262 5263 config = __SCNetworkInterfaceGetConfiguration(interface, extendedType); 5264 if (config == NULL) { 5265 _SCErrorSet(kSCStatusOK); 5266 } 5267 5268 return config; 5269} 5270 5271 5272__private_extern__ 5273CFStringRef 5274__SCNetworkInterfaceGetEntityType(SCNetworkInterfaceRef interface) 5275{ 5276 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 5277 5278 return interfacePrivate->entity_type; 5279} 5280 5281 5282__private_extern__ 5283CFStringRef 5284__SCNetworkInterfaceGetEntitySubType(SCNetworkInterfaceRef interface) 5285{ 5286 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef) interface; 5287 5288 return interfacePrivate->entity_subtype; 5289} 5290 5291 5292CFStringRef 5293SCNetworkInterfaceGetBSDName(SCNetworkInterfaceRef interface) 5294{ 5295 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 5296 5297 if (!isA_SCNetworkInterface(interface)) { 5298 _SCErrorSet(kSCStatusInvalidArgument); 5299 return NULL; 5300 } 5301 5302 if ((interfacePrivate->interface != NULL) && 5303 (interfacePrivate->interface != kSCNetworkInterfaceIPv4)) { 5304 _SCErrorSet(kSCStatusOK); 5305 return NULL; 5306 } 5307 5308 return interfacePrivate->entity_device; 5309} 5310 5311 5312CFStringRef 5313SCNetworkInterfaceGetHardwareAddressString(SCNetworkInterfaceRef interface) 5314{ 5315 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 5316 5317 if (!isA_SCNetworkInterface(interface)) { 5318 _SCErrorSet(kSCStatusInvalidArgument); 5319 return NULL; 5320 } 5321 5322 if ((interfacePrivate->address != NULL) && 5323 (interfacePrivate->addressString == NULL)) { 5324 uint8_t *bp; 5325 char *cp; 5326 size_t n; 5327 char mac[sizeof("xx:xx:xx:xx:xx:xx:xx:xx")]; 5328 char *mac_p = mac; 5329 5330 bp = (uint8_t *)CFDataGetBytePtr(interfacePrivate->address); 5331 n = CFDataGetLength(interfacePrivate->address) * 3; 5332 5333 if (n > sizeof(mac)) { 5334 mac_p = CFAllocatorAllocate(NULL, n, 0); 5335 } 5336 5337 for (cp = mac_p; n > 0; n -= 3) { 5338 cp += snprintf(cp, n, "%2.2x:", *bp++); 5339 } 5340 5341 interfacePrivate->addressString = CFStringCreateWithCString(NULL, mac_p, kCFStringEncodingUTF8); 5342 if (mac_p != mac) CFAllocatorDeallocate(NULL, mac_p); 5343 } 5344 5345 return interfacePrivate->addressString; 5346} 5347 5348 5349SCNetworkInterfaceRef 5350SCNetworkInterfaceGetInterface(SCNetworkInterfaceRef interface) 5351{ 5352 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 5353 5354 if (!isA_SCNetworkInterface(interface)) { 5355 _SCErrorSet(kSCStatusInvalidArgument); 5356 return NULL; 5357 } 5358 5359 return interfacePrivate->interface; 5360} 5361 5362 5363CFStringRef 5364SCNetworkInterfaceGetInterfaceType(SCNetworkInterfaceRef interface) 5365{ 5366 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 5367 5368 if (!isA_SCNetworkInterface(interface)) { 5369 _SCErrorSet(kSCStatusInvalidArgument); 5370 return NULL; 5371 } 5372 5373 return interfacePrivate->interface_type; 5374} 5375 5376 5377static CFStringRef 5378copy_string_from_bundle(CFBundleRef bundle, CFStringRef key, Boolean localized) 5379{ 5380 CFStringRef str = NULL; 5381 5382 if (localized) { 5383 str = CFBundleCopyLocalizedString(bundle, 5384 key, 5385 key, 5386 NETWORKINTERFACE_LOCALIZATIONS); 5387 } else { 5388 str = _SC_CFBundleCopyNonLocalizedString(bundle, 5389 key, 5390 key, 5391 NETWORKINTERFACE_LOCALIZATIONS); 5392 } 5393 5394 return str; 5395} 5396 5397 5398static CFStringRef 5399copy_interface_string(CFBundleRef bundle, CFStringRef key, Boolean localized) 5400{ 5401 static Boolean reported = FALSE; 5402 CFStringRef str = NULL; 5403 5404 str = copy_string_from_bundle(bundle, key, localized); 5405 5406 if (str == NULL) { 5407 SC_log(LOG_ERR, "Received NULL string for the interface key: {Bundle: %@, key: %@, localized: %d}", bundle, 5408 key, 5409 localized); 5410 goto done; 5411 } 5412 5413 if (CFEqual(str, key) && !reported) { 5414 const CFStringRef knownStrKey = CFSTR("airport"); 5415 CFStringRef knownStrValue = NULL; 5416 5417 knownStrValue = copy_string_from_bundle(bundle, knownStrKey, localized); 5418 if (knownStrValue == NULL || CFEqual(knownStrValue, knownStrKey)) { 5419 /* We are here because we requested for a localized/non-localized string 5420 based on the localization key, but we were given the same key/NULL back, 5421 implying a bad...bad thing! 5422 */ 5423 SC_log(LOG_ERR, "Failed to retrieve the interface string: {Bundle: %@, key: %@, localized: %d}", bundle, 5424 knownStrKey, 5425 localized); 5426 5427#if TARGET_OS_IPHONE 5428 /* ...and we want to know about it! */ 5429 _SC_crash("Failed to retrieve interface string", NULL, NULL); 5430#endif //TARGET_OS_IPHONE 5431 reported = TRUE; 5432 } 5433 5434 if (knownStrValue != NULL) { 5435 CFRelease(knownStrValue); 5436 } 5437 } 5438 5439done: 5440 return str; 5441} 5442 5443 5444static CFStringRef 5445copy_display_name(SCNetworkInterfaceRef interface, Boolean localized, Boolean oldLocalization) 5446{ 5447 CFMutableStringRef local; 5448 CFStringRef name; 5449 5450 local = CFStringCreateMutable(NULL, 0); 5451 5452 while (interface != NULL) { 5453 Boolean added = FALSE; 5454 SCNetworkInterfaceRef child = NULL; 5455 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 5456 5457 if ((interfacePrivate->interface != NULL) && 5458 (interfacePrivate->interface != kSCNetworkInterfaceIPv4) && 5459 !CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeVPN)) { 5460 child = interfacePrivate->interface; 5461 } 5462 5463 if ((bundle != NULL) && (interfacePrivate->localized_key != NULL)) { 5464 CFStringRef fmt; 5465 CFStringRef key = interfacePrivate->localized_key; 5466 5467 if (oldLocalization) { 5468 key = CFStringCreateWithFormat(NULL, NULL, CFSTR("X-%@"), 5469 interfacePrivate->localized_key); 5470 } 5471 fmt = copy_interface_string(bundle, key, localized); 5472 if (fmt != NULL) { 5473 CFStringAppendFormat(local, 5474 NULL, 5475 fmt, 5476 interfacePrivate->localized_arg1, 5477 interfacePrivate->localized_arg2); 5478 CFRelease(fmt); 5479 added = TRUE; 5480 } 5481 if (oldLocalization) { 5482 CFRelease(key); 5483 } 5484 } 5485 5486 if (!added && 5487 (interfacePrivate->prefs != NULL) && 5488 (interfacePrivate->serviceID != NULL) && 5489 (child == NULL)) { 5490 CFDictionaryRef entity; 5491 CFStringRef path; 5492 5493 // check for (and use) the name of the interface when it 5494 // was last available 5495 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, 5496 interfacePrivate->serviceID, 5497 kSCEntNetInterface); 5498 entity = SCPreferencesPathGetValue(interfacePrivate->prefs, path); 5499 CFRelease(path); 5500 if (isA_CFDictionary(entity)) { 5501 CFStringRef name; 5502 5503 name = CFDictionaryGetValue(entity, kSCPropUserDefinedName); 5504 if (isA_CFString(name)) { 5505 CFStringAppend(local, name); 5506 added = TRUE; 5507 } 5508 } 5509 } 5510 5511 if (!added) { 5512 // create (non-)localized name based on the interface type 5513 CFStringAppend(local, interfacePrivate->interface_type); 5514 5515 // ... and, if this is a leaf node, the interface device 5516 if ((interfacePrivate->entity_device != NULL) && (child == NULL)) { 5517 CFStringAppendFormat(local, NULL, CFSTR(" (%@)"), interfacePrivate->entity_device); 5518 } 5519 } 5520 5521 if (child != NULL) { 5522 // if this interface is layered over another 5523 CFStringAppend(local, CFSTR(" --> ")); 5524 } 5525 5526 interface = child; 5527 } 5528 5529 name = CFStringCreateCopy(NULL, local); 5530 CFRelease(local); 5531 5532 return name; 5533} 5534 5535 5536#if !TARGET_OS_IPHONE 5537__private_extern__ 5538CFStringRef 5539__SCNetworkInterfaceCopyXLocalizedDisplayName(SCNetworkInterfaceRef interface) 5540{ 5541 CFStringRef name; 5542 5543 if (!isA_SCNetworkInterface(interface)) { 5544 _SCErrorSet(kSCStatusInvalidArgument); 5545 return NULL; 5546 } 5547 5548 name = copy_display_name(interface, TRUE, TRUE); 5549 return name; 5550} 5551 5552 5553__private_extern__ 5554CFStringRef 5555__SCNetworkInterfaceCopyXNonLocalizedDisplayName(SCNetworkInterfaceRef interface) 5556{ 5557 CFStringRef localized_name; 5558 5559 if (!isA_SCNetworkInterface(interface)) { 5560 _SCErrorSet(kSCStatusInvalidArgument); 5561 return NULL; 5562 } 5563 5564 localized_name = copy_display_name(interface, FALSE, TRUE); 5565 return localized_name; 5566} 5567#endif // !TARGET_OS_IPHONE 5568 5569__private_extern__ 5570void 5571__SCNetworkInterfaceSetUserDefinedName(SCNetworkInterfaceRef interface, CFStringRef name) 5572{ 5573 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 5574 5575 if (!isA_SCNetworkInterface(interface)) { 5576 return; 5577 } 5578 if (name != NULL) { 5579 CFRetain(name); 5580 } 5581 if (interfacePrivate->name != NULL) { 5582 CFRelease(interfacePrivate->name); 5583 } 5584 interfacePrivate->name = name; 5585 5586 if (name != NULL) { 5587 CFRetain(name); 5588 } 5589 if (interfacePrivate->localized_name != NULL) { 5590 CFRelease(interfacePrivate->localized_name); 5591 } 5592 interfacePrivate->localized_name = name; 5593} 5594 5595__private_extern__ 5596CFStringRef 5597__SCNetworkInterfaceGetUserDefinedName(SCNetworkInterfaceRef interface) 5598{ 5599 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 5600 5601 if (!isA_SCNetworkInterface(interface)) { 5602 return NULL; 5603 } 5604 5605 return interfacePrivate->name; 5606} 5607 5608 5609__private_extern__ 5610CFStringRef 5611__SCNetworkInterfaceGetNonLocalizedDisplayName(SCNetworkInterfaceRef interface) 5612{ 5613 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 5614 5615 if (!isA_SCNetworkInterface(interface)) { 5616 _SCErrorSet(kSCStatusInvalidArgument); 5617 return NULL; 5618 } 5619 5620 if (interfacePrivate->name == NULL) { 5621 interfacePrivate->name = copy_display_name(interface, FALSE, FALSE); 5622 } 5623 5624 return interfacePrivate->name; 5625} 5626 5627 5628CFStringRef 5629SCNetworkInterfaceGetLocalizedDisplayName(SCNetworkInterfaceRef interface) 5630{ 5631 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 5632 5633 if (!isA_SCNetworkInterface(interface)) { 5634 _SCErrorSet(kSCStatusInvalidArgument); 5635 return NULL; 5636 } 5637 5638 if (interfacePrivate->localized_name == NULL) { 5639 interfacePrivate->localized_name = copy_display_name(interface, TRUE, FALSE); 5640 } 5641 5642 return interfacePrivate->localized_name; 5643} 5644 5645 5646__private_extern__ 5647CFPropertyListRef 5648__SCNetworkInterfaceGetTemplateOverrides(SCNetworkInterfaceRef interface, CFStringRef overrideType) 5649{ 5650 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 5651 CFPropertyListRef overrides = NULL; 5652 5653 if (interfacePrivate->overrides != NULL) { 5654 overrides = CFDictionaryGetValue(interfacePrivate->overrides, overrideType); 5655 } 5656 5657 return overrides; 5658} 5659 5660 5661CFTypeID 5662SCNetworkInterfaceGetTypeID(void) 5663{ 5664 pthread_once(&initialized, __SCNetworkInterfaceInitialize); /* initialize runtime */ 5665 return __kSCNetworkInterfaceTypeID; 5666} 5667 5668 5669__private_extern__ 5670Boolean 5671__SCNetworkInterfaceSetDefaultConfiguration(SCNetworkSetRef set, 5672 SCNetworkInterfaceRef interface, 5673 CFStringRef defaultType, 5674 CFDictionaryRef config, 5675 Boolean okToHold) 5676{ 5677 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 5678 Boolean ok = FALSE; 5679 5680 /* initialize runtime (and kSCNetworkInterfaceIPv4) */ 5681 pthread_once(&initialized, __SCNetworkInterfaceInitialize); 5682 5683 if (defaultType == NULL) { 5684 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface); 5685 if (defaultType == NULL) { 5686 return FALSE; 5687 } 5688 } 5689 5690 if (isA_CFDictionary(config) && (CFDictionaryGetCount(config) == 0)) { 5691 config = NULL; 5692 } 5693 5694 if (set != NULL) { 5695 CFStringRef path; 5696 5697 path = SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL, // allocator 5698 SCNetworkSetGetSetID(set), // set 5699 interfacePrivate->entity_device, // interface 5700 defaultType); // entity 5701 if (path != NULL) { 5702 ok = __setPrefsConfiguration(interfacePrivate->prefs, path, config, FALSE); 5703 CFRelease(path); 5704 if (ok) { 5705 // if configuration has been saved 5706 if (interfacePrivate->unsaved != NULL) { 5707 CFDictionaryRemoveValue(interfacePrivate->unsaved, defaultType); 5708 if (CFDictionaryGetCount(interfacePrivate->unsaved) == 0) { 5709 CFRelease(interfacePrivate->unsaved); 5710 interfacePrivate->unsaved = NULL; 5711 } 5712 } 5713 } 5714 } else { 5715 if (okToHold) { 5716 if (config == NULL) { 5717 // remember that we are clearing the configuration 5718 config = (CFDictionaryRef)kCFNull; 5719 } 5720 5721 if (interfacePrivate->unsaved == NULL) { 5722 interfacePrivate->unsaved = CFDictionaryCreateMutable(NULL, 5723 0, 5724 &kCFTypeDictionaryKeyCallBacks, 5725 &kCFTypeDictionaryValueCallBacks); 5726 } 5727 CFDictionarySetValue(interfacePrivate->unsaved, defaultType, config); 5728 ok = TRUE; 5729 } else { 5730 _SCErrorSet(kSCStatusNoKey); 5731 } 5732 } 5733 } 5734 5735 return ok; 5736} 5737 5738 5739__private_extern__ 5740Boolean 5741__SCNetworkInterfaceSetConfiguration(SCNetworkInterfaceRef interface, 5742 CFStringRef extendedType, 5743 CFDictionaryRef config, 5744 Boolean okToHold) 5745{ 5746 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 5747 Boolean ok = FALSE; 5748 CFArrayRef paths; 5749 5750 /* initialize runtime (and kSCNetworkInterfaceIPv4) */ 5751 pthread_once(&initialized, __SCNetworkInterfaceInitialize); 5752 5753 if (extendedType == NULL) { 5754 extendedType = __SCNetworkInterfaceGetDefaultConfigurationType(interface); 5755 if (extendedType == NULL) { 5756 return FALSE; 5757 } 5758 } 5759 5760 if (isA_CFDictionary(config) && (CFDictionaryGetCount(config) == 0)) { 5761 config = NULL; 5762 } 5763 5764 paths = copyConfigurationPaths(interfacePrivate, extendedType); 5765 if (paths != NULL) { 5766 CFIndex i; 5767 CFIndex n; 5768 5769 n = CFArrayGetCount(paths); 5770 for (i = 0; i < n; i++) { 5771 CFStringRef path; 5772 5773 path = CFArrayGetValueAtIndex(paths, i); 5774 ok = __setPrefsConfiguration(interfacePrivate->prefs, path, config, FALSE); 5775 if (!ok) { 5776 break; 5777 } 5778 } 5779 5780 if (ok) { 5781 // if configuration has been saved 5782 if (interfacePrivate->unsaved != NULL) { 5783 CFDictionaryRemoveValue(interfacePrivate->unsaved, extendedType); 5784 if (CFDictionaryGetCount(interfacePrivate->unsaved) == 0) { 5785 CFRelease(interfacePrivate->unsaved); 5786 interfacePrivate->unsaved = NULL; 5787 } 5788 } 5789 } 5790 5791 CFRelease(paths); 5792 } else { 5793 if (okToHold) { 5794 if (config == NULL) { 5795 // remember that we are clearing the configuration 5796 config = (CFDictionaryRef)kCFNull; 5797 } 5798 5799 if (interfacePrivate->unsaved == NULL) { 5800 interfacePrivate->unsaved = CFDictionaryCreateMutable(NULL, 5801 0, 5802 &kCFTypeDictionaryKeyCallBacks, 5803 &kCFTypeDictionaryValueCallBacks); 5804 } 5805 CFDictionarySetValue(interfacePrivate->unsaved, extendedType, config); 5806 ok = TRUE; 5807 } else { 5808 _SCErrorSet(kSCStatusNoKey); 5809 } 5810 } 5811 5812 return ok; 5813} 5814 5815 5816Boolean 5817SCNetworkInterfaceSetConfiguration(SCNetworkInterfaceRef interface, CFDictionaryRef config) 5818{ 5819 CFStringRef defaultType; 5820 Boolean ok; 5821 5822 if (!isA_SCNetworkInterface(interface)) { 5823 _SCErrorSet(kSCStatusInvalidArgument); 5824 return FALSE; 5825 } 5826 5827 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface); 5828 if (defaultType == NULL) { 5829 return FALSE; 5830 } 5831 5832 ok = __SCNetworkInterfaceSetConfiguration(interface, defaultType, config, FALSE); 5833 if (ok) { 5834 SC_log(LOG_DEBUG, "SCNetworkInterfaceSetConfiguration(): %@ -> %@", 5835 interface, 5836 config != NULL ? config : (CFDictionaryRef)CFSTR("NULL")); 5837 } 5838 5839 return ok; 5840} 5841 5842 5843Boolean 5844SCNetworkInterfaceSetExtendedConfiguration(SCNetworkInterfaceRef interface, 5845 CFStringRef extendedType, 5846 CFDictionaryRef config) 5847{ 5848 Boolean ok; 5849 5850 if (!isA_SCNetworkInterface(interface)) { 5851 _SCErrorSet(kSCStatusInvalidArgument); 5852 return FALSE; 5853 } 5854 5855 if (!__SCNetworkInterfaceIsValidExtendedConfigurationType(interface, extendedType, TRUE)) { 5856 return FALSE; 5857 } 5858 5859 ok = __SCNetworkInterfaceSetConfiguration(interface, extendedType, config, FALSE); 5860 if (ok) { 5861 SC_log(LOG_DEBUG, "SCNetworkInterfaceSetExtendedConfiguration(): %@ -> %@", 5862 interface, 5863 config != NULL ? config : (CFDictionaryRef)CFSTR("NULL")); 5864 } 5865 5866 return ok; 5867} 5868 5869 5870#pragma mark - 5871#pragma mark SCNetworkInterface [Refresh Configuration] API 5872 5873 5874Boolean 5875_SCNetworkInterfaceForceConfigurationRefresh(CFStringRef ifName) 5876{ 5877 CFStringRef key; 5878 Boolean ok = FALSE; 5879 5880 if (!isA_CFString(ifName)) { 5881 _SCErrorSet(kSCStatusInvalidArgument); 5882 return FALSE; 5883 } 5884 5885 key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, 5886 kSCDynamicStoreDomainState, 5887 ifName, 5888 kSCEntNetRefreshConfiguration); 5889 ok = SCDynamicStoreNotifyValue(NULL, key); 5890 CFRelease(key); 5891 return ok; 5892} 5893 5894 5895static Boolean 5896__SCNetworkInterfaceForceConfigurationRefresh_helper(SCPreferencesRef prefs, CFStringRef ifName) 5897{ 5898 CFDataRef data = NULL; 5899 Boolean ok; 5900 SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs; 5901 uint32_t status = kSCStatusOK; 5902 CFDataRef reply = NULL; 5903 5904 if (prefsPrivate->helper_port == MACH_PORT_NULL) { 5905 ok = __SCPreferencesCreate_helper(prefs); 5906 if (!ok) { 5907 return FALSE; 5908 } 5909 } 5910 5911 // serialize the interface name 5912 ok = _SCSerializeString(ifName, &data, NULL, NULL); 5913 if (!ok) { 5914 goto fail; 5915 } 5916 5917 // have the helper "refresh" the configuration 5918 status = kSCStatusOK; 5919 reply = NULL; 5920 ok = _SCHelperExec(prefsPrivate->helper_port, 5921 SCHELPER_MSG_INTERFACE_REFRESH, 5922 data, 5923 &status, 5924 NULL); 5925 if (data != NULL) CFRelease(data); 5926 if (!ok) { 5927 goto fail; 5928 } 5929 5930 if (status != kSCStatusOK) { 5931 goto error; 5932 } 5933 5934 return TRUE; 5935 5936 fail : 5937 5938 // close helper 5939 if (prefsPrivate->helper_port != MACH_PORT_NULL) { 5940 _SCHelperClose(&prefsPrivate->helper_port); 5941 } 5942 5943 status = kSCStatusAccessError; 5944 5945 error : 5946 5947 // return error 5948 _SCErrorSet(status); 5949 return FALSE; 5950} 5951 5952 5953Boolean 5954SCNetworkInterfaceForceConfigurationRefresh(SCNetworkInterfaceRef interface) 5955{ 5956 CFStringRef ifName; 5957 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 5958 5959 if (!isA_SCNetworkInterface(interface)) { 5960 _SCErrorSet(kSCStatusInvalidArgument); 5961 return FALSE; 5962 } 5963 5964 ifName = SCNetworkInterfaceGetBSDName(interface); 5965 if (ifName == NULL) { 5966 _SCErrorSet(kSCStatusInvalidArgument); 5967 return FALSE; 5968 } 5969 5970 if (interfacePrivate->prefs != NULL) { 5971 SCPreferencesRef prefs = interfacePrivate->prefs; 5972 SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs; 5973 5974 if (prefsPrivate->authorizationData != NULL) { 5975 return __SCNetworkInterfaceForceConfigurationRefresh_helper(prefs, ifName); 5976 } 5977 } 5978 5979 return _SCNetworkInterfaceForceConfigurationRefresh(ifName); 5980} 5981 5982 5983#if !TARGET_OS_IPHONE 5984Boolean 5985SCNetworkInterfaceRefreshConfiguration(CFStringRef ifName) 5986{ 5987 return _SCNetworkInterfaceForceConfigurationRefresh(ifName); 5988} 5989#endif // !TARGET_OS_IPHONE 5990 5991 5992#pragma mark - 5993#pragma mark SCNetworkInterface Password APIs 5994 5995 5996static CFStringRef 5997getPasswordID(CFDictionaryRef config, CFStringRef serviceID) 5998{ 5999 CFStringRef unique_id = NULL; 6000 6001 if (config != NULL) { 6002 CFStringRef encryption; 6003 6004 encryption = CFDictionaryGetValue(config, kSCPropNetPPPAuthPasswordEncryption); 6005 if (isA_CFString(encryption) && 6006 CFEqual(encryption, kSCValNetPPPAuthPasswordEncryptionKeychain)) { 6007 unique_id = CFDictionaryGetValue(config, kSCPropNetPPPAuthPassword); 6008 } 6009 } 6010 if (unique_id == NULL) { 6011 unique_id = serviceID; 6012 } 6013 6014 return unique_id; 6015} 6016 6017 6018static CFStringRef 6019copySharedSecretID(CFDictionaryRef config, CFStringRef serviceID) 6020{ 6021 CFMutableStringRef shared_id = NULL; 6022 6023 if (config != NULL) { 6024 CFStringRef encryption; 6025 6026 encryption = CFDictionaryGetValue(config, kSCPropNetIPSecSharedSecretEncryption); 6027 if (isA_CFString(encryption) && 6028 CFEqual(encryption, kSCValNetIPSecSharedSecretEncryptionKeychain)) { 6029 shared_id = (CFMutableStringRef)CFDictionaryGetValue(config, kSCPropNetIPSecSharedSecret); 6030 if (shared_id != NULL) { 6031 CFRetain(shared_id); 6032 } 6033 } 6034 } 6035 6036 if (shared_id == NULL) { 6037 CFStringRef unique_id; 6038 6039 unique_id = getPasswordID(config, serviceID); 6040 shared_id = CFStringCreateMutableCopy(NULL, 0, unique_id); 6041 CFStringAppend(shared_id, CFSTR(".SS")); 6042 } 6043 6044 return shared_id; 6045} 6046 6047 6048static CFStringRef 6049copyXAuthID(CFDictionaryRef config, CFStringRef serviceID) 6050{ 6051 CFMutableStringRef xauth_id = NULL; 6052 6053 if (config != NULL) { 6054 CFStringRef encryption; 6055 6056 encryption = CFDictionaryGetValue(config, kSCPropNetIPSecXAuthPasswordEncryption); 6057 if (isA_CFString(encryption) && 6058 CFEqual(encryption, kSCValNetIPSecXAuthPasswordEncryptionKeychain)) { 6059 xauth_id = (CFMutableStringRef)CFDictionaryGetValue(config, kSCPropNetIPSecXAuthPassword); 6060 if (xauth_id != NULL) { 6061 CFRetain(xauth_id); 6062 } 6063 } 6064 } 6065 6066 if (xauth_id == NULL) { 6067 CFStringRef unique_id; 6068 6069 unique_id = getPasswordID(config, serviceID); 6070 xauth_id = CFStringCreateMutableCopy(NULL, 0, unique_id); 6071 CFStringAppend(xauth_id, CFSTR(".XAUTH")); 6072 } 6073 6074 return xauth_id; 6075} 6076 6077 6078static Boolean 6079checkInterfacePassword(SCNetworkInterfaceRef interface, 6080 SCNetworkInterfacePasswordType passwordType, 6081 SCPreferencesRef *prefs, 6082 CFStringRef *serviceID) 6083{ 6084 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 6085 6086 if (!isA_SCNetworkInterface(interface)) { 6087 goto error; 6088 } 6089 6090 *serviceID = interfacePrivate->serviceID; 6091 if (*serviceID == NULL) { 6092 goto error; 6093 } 6094 6095 *prefs = interfacePrivate->prefs; 6096 if (*prefs == NULL) { 6097 goto error; 6098 } 6099 6100 switch (passwordType) { 6101 case kSCNetworkInterfacePasswordTypePPP : { 6102 CFStringRef interfaceType; 6103 6104 interfaceType = SCNetworkInterfaceGetInterfaceType(interface); 6105 if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) { 6106 // if PPP 6107 break; 6108 } 6109 6110 goto error; 6111 } 6112 6113 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : { 6114 CFStringRef interfaceType; 6115 6116 interfaceType = SCNetworkInterfaceGetInterfaceType(interface); 6117 if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) { 6118 interface = SCNetworkInterfaceGetInterface(interface); 6119 if (interface != NULL) { 6120 interfaceType = SCNetworkInterfaceGetInterfaceType(interface); 6121 if (CFEqual(interfaceType, kSCNetworkInterfaceTypeL2TP)) { 6122 // if PPP->L2TP interface 6123 break; 6124 } 6125 } 6126 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeIPSec)) { 6127 // if IPSec interface 6128 break; 6129 } 6130 6131 goto error; 6132 } 6133 6134 case kSCNetworkInterfacePasswordTypeEAPOL : { 6135 break; 6136 } 6137 6138 case kSCNetworkInterfacePasswordTypeIPSecXAuth : { 6139 CFStringRef interfaceType; 6140 6141 interfaceType = SCNetworkInterfaceGetInterfaceType(interface); 6142 if (CFEqual(interfaceType, kSCNetworkInterfaceTypeIPSec)) { 6143 // if IPSec interface 6144 break; 6145 } 6146 6147 goto error; 6148 } 6149 6150 case kSCNetworkInterfacePasswordTypeVPN : { 6151 CFStringRef interfaceType; 6152 6153 interfaceType = SCNetworkInterfaceGetInterfaceType(interface); 6154 if (CFEqual(interfaceType, kSCNetworkInterfaceTypeVPN)) { 6155 // if VPN interface 6156 break; 6157 } 6158 6159 goto error; 6160 } 6161 6162 default : 6163 break; 6164 } 6165 6166 return TRUE; 6167 6168 error : 6169 6170 _SCErrorSet(kSCStatusInvalidArgument); 6171 return FALSE; 6172} 6173 6174 6175Boolean 6176SCNetworkInterfaceCheckPassword(SCNetworkInterfaceRef interface, 6177 SCNetworkInterfacePasswordType passwordType) 6178{ 6179 Boolean exists = FALSE; 6180 SCPreferencesRef prefs = NULL; 6181 CFStringRef serviceID = NULL; 6182 6183 if (!checkInterfacePassword(interface, passwordType, &prefs, &serviceID)) { 6184 return FALSE; 6185 } 6186 6187 switch (passwordType) { 6188 case kSCNetworkInterfacePasswordTypePPP : { 6189 CFDictionaryRef config; 6190 CFStringRef unique_id; 6191 6192 // get configuration 6193 config = SCNetworkInterfaceGetConfiguration(interface); 6194 6195 // get serviceID 6196 unique_id = getPasswordID(config, serviceID); 6197 6198 // check 6199 exists = __extract_password(prefs, 6200 config, 6201 kSCPropNetPPPAuthPassword, 6202 kSCPropNetPPPAuthPasswordEncryption, 6203 kSCValNetPPPAuthPasswordEncryptionKeychain, 6204 unique_id, 6205 NULL); 6206 break; 6207 } 6208 6209 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : { 6210 CFDictionaryRef config; 6211 Boolean extended; 6212 CFStringRef shared_id; 6213 6214 // get configuration 6215 extended = CFEqual(SCNetworkInterfaceGetInterfaceType(interface), kSCNetworkInterfaceTypePPP); 6216 if (extended) { 6217 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetIPSec); 6218 } else { 6219 config = SCNetworkInterfaceGetConfiguration(interface); 6220 } 6221 6222 // get sharedSecret ID 6223 shared_id = copySharedSecretID(config, serviceID); 6224 6225 // check 6226 exists = __extract_password(prefs, 6227 config, 6228 kSCPropNetIPSecSharedSecret, 6229 kSCPropNetIPSecSharedSecretEncryption, 6230 kSCValNetIPSecSharedSecretEncryptionKeychain, 6231 shared_id, 6232 NULL); 6233 CFRelease(shared_id); 6234 break; 6235 } 6236 6237 case kSCNetworkInterfacePasswordTypeEAPOL : { 6238 CFDictionaryRef config; 6239 CFStringRef unique_id = NULL; 6240 6241 // get configuration 6242 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetEAPOL); 6243 6244 // get 802.1X identifier 6245 if (config != NULL) { 6246 unique_id = CFDictionaryGetValue(config, kEAPClientPropUserPasswordKeychainItemID); 6247 } 6248 if (!isA_CFString(unique_id)) { 6249 return FALSE; 6250 } 6251 6252 // check password 6253 exists = _SCPreferencesSystemKeychainPasswordItemExists(prefs, unique_id); 6254 break; 6255 } 6256 6257 case kSCNetworkInterfacePasswordTypeIPSecXAuth : { 6258 CFDictionaryRef config; 6259 CFStringRef xauth_id; 6260 6261 // get configuration 6262 config = SCNetworkInterfaceGetConfiguration(interface); 6263 6264 // get XAuth ID 6265 xauth_id = copyXAuthID(config, serviceID); 6266 6267 // check 6268 exists = __extract_password(prefs, 6269 config, 6270 kSCPropNetIPSecXAuthPassword, 6271 kSCPropNetIPSecXAuthPasswordEncryption, 6272 kSCValNetIPSecXAuthPasswordEncryptionKeychain, 6273 xauth_id, 6274 NULL); 6275 CFRelease(xauth_id); 6276 break; 6277 } 6278 6279 case kSCNetworkInterfacePasswordTypeVPN : { 6280 CFDictionaryRef config; 6281 CFStringRef vpn_id; 6282 6283 // get configuration 6284 config = SCNetworkInterfaceGetConfiguration(interface); 6285 6286 // get serviceID 6287 vpn_id = getPasswordID(config, serviceID); 6288 6289 // check 6290 exists = __extract_password(prefs, 6291 config, 6292 kSCPropNetVPNAuthPassword, 6293 kSCPropNetVPNAuthPasswordEncryption, 6294 kSCValNetVPNAuthPasswordEncryptionKeychain, 6295 vpn_id, 6296 NULL); 6297 break; 6298 } 6299 6300 default : 6301 _SCErrorSet(kSCStatusInvalidArgument); 6302 return FALSE; 6303 } 6304 6305 return exists; 6306} 6307 6308 6309CFDataRef 6310SCNetworkInterfaceCopyPassword(SCNetworkInterfaceRef interface, 6311 SCNetworkInterfacePasswordType passwordType) 6312{ 6313 CFDataRef password = NULL; 6314 SCPreferencesRef prefs = NULL; 6315 CFStringRef serviceID = NULL; 6316 6317 if (!checkInterfacePassword(interface, passwordType, &prefs, &serviceID)) { 6318 return NULL; 6319 } 6320 6321 switch (passwordType) { 6322 case kSCNetworkInterfacePasswordTypePPP : { 6323 CFDictionaryRef config; 6324 CFStringRef unique_id; 6325 6326 // get configuration 6327 config = SCNetworkInterfaceGetConfiguration(interface); 6328 6329 // get serviceID 6330 unique_id = getPasswordID(config, serviceID); 6331 6332 // extract 6333 (void) __extract_password(prefs, 6334 config, 6335 kSCPropNetPPPAuthPassword, 6336 kSCPropNetPPPAuthPasswordEncryption, 6337 kSCValNetPPPAuthPasswordEncryptionKeychain, 6338 unique_id, 6339 &password); 6340 break; 6341 } 6342 6343 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : { 6344 CFDictionaryRef config; 6345 Boolean extended; 6346 CFStringRef shared_id; 6347 6348 // get configuration 6349 extended = CFEqual(SCNetworkInterfaceGetInterfaceType(interface), kSCNetworkInterfaceTypePPP); 6350 if (extended) { 6351 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetIPSec); 6352 } else { 6353 config = SCNetworkInterfaceGetConfiguration(interface); 6354 } 6355 6356 // get sharedSecret ID 6357 shared_id = copySharedSecretID(config, serviceID); 6358 6359 // extract 6360 (void) __extract_password(prefs, 6361 config, 6362 kSCPropNetIPSecSharedSecret, 6363 kSCPropNetIPSecSharedSecretEncryption, 6364 kSCValNetIPSecSharedSecretEncryptionKeychain, 6365 shared_id, 6366 &password); 6367 6368 CFRelease(shared_id); 6369 break; 6370 } 6371 6372 case kSCNetworkInterfacePasswordTypeEAPOL : { 6373 CFDictionaryRef config; 6374 CFStringRef unique_id = NULL; 6375 6376 // get configuration 6377 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetEAPOL); 6378 6379 // get 802.1X identifier 6380 if (config != NULL) { 6381 unique_id = CFDictionaryGetValue(config, kEAPClientPropUserPasswordKeychainItemID); 6382 } 6383 if (!isA_CFString(unique_id)) { 6384 _SCErrorSet(kSCStatusFailed); 6385 return NULL; 6386 } 6387 6388 // copy password 6389 password = _SCPreferencesSystemKeychainPasswordItemCopy(prefs, unique_id); 6390 break; 6391 } 6392 6393 case kSCNetworkInterfacePasswordTypeIPSecXAuth : { 6394 CFDictionaryRef config; 6395 CFStringRef xauth_id; 6396 6397 // get configuration 6398 config = SCNetworkInterfaceGetConfiguration(interface); 6399 6400 // get XAuth ID 6401 xauth_id = copyXAuthID(config, serviceID); 6402 6403 // extract 6404 (void) __extract_password(prefs, 6405 config, 6406 kSCPropNetIPSecXAuthPassword, 6407 kSCPropNetIPSecXAuthPasswordEncryption, 6408 kSCValNetIPSecXAuthPasswordEncryptionKeychain, 6409 xauth_id, 6410 &password); 6411 CFRelease(xauth_id); 6412 break; 6413 } 6414 6415 case kSCNetworkInterfacePasswordTypeVPN : { 6416 CFDictionaryRef config; 6417 CFStringRef vpn_id; 6418 6419 // get configuration 6420 config = SCNetworkInterfaceGetConfiguration(interface); 6421 6422 // get serviceID 6423 vpn_id = getPasswordID(config, serviceID); 6424 6425 // extract 6426 (void) __extract_password(prefs, 6427 config, 6428 kSCPropNetVPNAuthPassword, 6429 kSCPropNetVPNAuthPasswordEncryption, 6430 kSCValNetVPNAuthPasswordEncryptionKeychain, 6431 vpn_id, 6432 &password); 6433 break; 6434 } 6435 6436 default : 6437 _SCErrorSet(kSCStatusInvalidArgument); 6438 return NULL; 6439 } 6440 6441 return password; 6442} 6443 6444 6445Boolean 6446SCNetworkInterfaceRemovePassword(SCNetworkInterfaceRef interface, 6447 SCNetworkInterfacePasswordType passwordType) 6448{ 6449 Boolean ok = FALSE; 6450 SCPreferencesRef prefs = NULL; 6451 CFStringRef serviceID = NULL; 6452 6453 if (!checkInterfacePassword(interface, passwordType, &prefs, &serviceID)) { 6454 return FALSE; 6455 } 6456 6457 switch (passwordType) { 6458 case kSCNetworkInterfacePasswordTypePPP : { 6459 CFDictionaryRef config; 6460 CFDictionaryRef newConfig = NULL; 6461 CFStringRef unique_id; 6462 6463 // get configuration 6464 config = SCNetworkInterfaceGetConfiguration(interface); 6465 6466 // get serviceID 6467 unique_id = getPasswordID(config, serviceID); 6468 6469 // remove password 6470 ok = __remove_password(prefs, 6471 config, 6472 kSCPropNetPPPAuthPassword, 6473 kSCPropNetPPPAuthPasswordEncryption, 6474 kSCValNetPPPAuthPasswordEncryptionKeychain, 6475 unique_id, 6476 &newConfig); 6477 if (ok) { 6478 ok = SCNetworkInterfaceSetConfiguration(interface, newConfig); 6479 if (newConfig != NULL) CFRelease(newConfig); 6480 } 6481 6482 break; 6483 } 6484 6485 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : { 6486 CFDictionaryRef config; 6487 Boolean extended; 6488 CFDictionaryRef newConfig = NULL; 6489 CFStringRef shared_id; 6490 6491 // get configuration 6492 extended = CFEqual(SCNetworkInterfaceGetInterfaceType(interface), kSCNetworkInterfaceTypePPP); 6493 if (extended) { 6494 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetIPSec); 6495 } else { 6496 config = SCNetworkInterfaceGetConfiguration(interface); 6497 } 6498 6499 // get sharedSecret ID 6500 shared_id = copySharedSecretID(config, serviceID); 6501 6502 // remove password 6503 ok = __remove_password(prefs, 6504 config, 6505 kSCPropNetIPSecSharedSecret, 6506 kSCPropNetIPSecSharedSecretEncryption, 6507 kSCValNetIPSecSharedSecretEncryptionKeychain, 6508 shared_id, 6509 &newConfig); 6510 if (ok) { 6511 if (extended) { 6512 ok = SCNetworkInterfaceSetExtendedConfiguration(interface, 6513 kSCEntNetIPSec, 6514 newConfig); 6515 } else { 6516 ok = SCNetworkInterfaceSetConfiguration(interface, 6517 newConfig); 6518 } 6519 if (newConfig != NULL) CFRelease(newConfig); 6520 } 6521 6522 CFRelease(shared_id); 6523 break; 6524 } 6525 6526 case kSCNetworkInterfacePasswordTypeEAPOL : { 6527 CFDictionaryRef config; 6528 CFStringRef unique_id = NULL; 6529 6530 // get configuration 6531 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetEAPOL); 6532 6533 // get 802.1X identifier 6534 if (config != NULL) { 6535 unique_id = CFDictionaryGetValue(config, kEAPClientPropUserPasswordKeychainItemID); 6536 } 6537 if (!isA_CFString(unique_id)) { 6538 _SCErrorSet(kSCStatusFailed); 6539 return FALSE; 6540 } 6541 6542 // remove password 6543 ok = _SCPreferencesSystemKeychainPasswordItemRemove(prefs, unique_id); 6544 break; 6545 } 6546 6547 case kSCNetworkInterfacePasswordTypeIPSecXAuth : { 6548 CFDictionaryRef config; 6549 CFDictionaryRef newConfig = NULL; 6550 CFStringRef xauth_id; 6551 6552 // get configuration 6553 config = SCNetworkInterfaceGetConfiguration(interface); 6554 6555 // get XAuth ID 6556 xauth_id = copyXAuthID(config, serviceID); 6557 6558 // remove password 6559 ok = __remove_password(prefs, 6560 config, 6561 kSCPropNetIPSecXAuthPassword, 6562 kSCPropNetIPSecXAuthPasswordEncryption, 6563 kSCValNetIPSecXAuthPasswordEncryptionKeychain, 6564 xauth_id, 6565 &newConfig); 6566 if (ok) { 6567 ok = SCNetworkInterfaceSetConfiguration(interface, newConfig); 6568 if (newConfig != NULL) CFRelease(newConfig); 6569 } 6570 6571 CFRelease(xauth_id); 6572 break; 6573 } 6574 6575 case kSCNetworkInterfacePasswordTypeVPN : { 6576 CFDictionaryRef config; 6577 CFDictionaryRef newConfig = NULL; 6578 CFStringRef vpn_id; 6579 6580 // get configuration 6581 config = SCNetworkInterfaceGetConfiguration(interface); 6582 6583 // get serviceID 6584 vpn_id = getPasswordID(config, serviceID); 6585 6586 // remove password 6587 ok = __remove_password(prefs, 6588 config, 6589 kSCPropNetVPNAuthPassword, 6590 kSCPropNetVPNAuthPasswordEncryption, 6591 kSCValNetVPNAuthPasswordEncryptionKeychain, 6592 vpn_id, 6593 &newConfig); 6594 if (ok) { 6595 ok = SCNetworkInterfaceSetConfiguration(interface, newConfig); 6596 if (newConfig != NULL) CFRelease(newConfig); 6597 } 6598 break; 6599 } 6600 6601 default : 6602 _SCErrorSet(kSCStatusInvalidArgument); 6603 return FALSE; 6604 } 6605 6606 return ok; 6607} 6608 6609 6610Boolean 6611SCNetworkInterfaceSetPassword(SCNetworkInterfaceRef interface, 6612 SCNetworkInterfacePasswordType passwordType, 6613 CFDataRef password, 6614 CFDictionaryRef options) 6615{ 6616 CFStringRef account = NULL; 6617 CFDictionaryRef config; 6618 CFStringRef description = NULL; 6619 CFStringRef label = NULL; 6620 Boolean ok = FALSE; 6621 SCPreferencesRef prefs = NULL; 6622 CFStringRef serviceID = NULL; 6623 6624 if (!checkInterfacePassword(interface, passwordType, &prefs, &serviceID)) { 6625 return FALSE; 6626 } 6627 6628 switch (passwordType) { 6629 case kSCNetworkInterfacePasswordTypePPP : { 6630 SCNetworkServiceRef service = NULL; 6631 CFStringRef unique_id; 6632 6633 // get configuration 6634 config = SCNetworkInterfaceGetConfiguration(interface); 6635 6636 // get serviceID 6637 unique_id = getPasswordID(config, serviceID); 6638 6639 // get "Account", "Name", "Kind" 6640 if (config != NULL) { 6641 // auth name --> keychain "Account" 6642 account = CFDictionaryGetValue(config, kSCPropNetPPPAuthName); 6643 6644 // PPP [user defined] "name" --> keychain "Name" 6645 label = CFDictionaryGetValue(config, kSCPropUserDefinedName); 6646 } 6647 6648 if (label == NULL) { 6649 // service name --> keychain "Name" 6650 service = (SCNetworkServiceRef)__SCNetworkServiceCreatePrivate(NULL, 6651 prefs, 6652 serviceID, 6653 interface); 6654 6655 label = SCNetworkServiceGetName(service); 6656 if (label == NULL) { 6657 // interface name --> keychain "Name" 6658 label = SCNetworkInterfaceGetLocalizedDisplayName(interface); 6659 } 6660 } 6661 6662 if (bundle != NULL) { 6663 // "PPP Password" --> keychain "Kind" 6664 description = CFBundleCopyLocalizedString(bundle, 6665 CFSTR("KEYCHAIN_KIND_PPP_PASSWORD"), 6666 CFSTR("PPP Password"), 6667 NULL); 6668 } 6669 6670 // store password 6671 ok = _SCPreferencesSystemKeychainPasswordItemSet(prefs, 6672 unique_id, 6673 (label != NULL) ? label : CFSTR("Network Connection"), 6674 (description != NULL) ? description : CFSTR("PPP Password"), 6675 account, 6676 password, 6677 options); 6678 if (ok) { 6679 CFMutableDictionaryRef newConfig; 6680 6681 if (config != NULL) { 6682 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config); 6683 } else { 6684 newConfig = CFDictionaryCreateMutable(NULL, 6685 0, 6686 &kCFTypeDictionaryKeyCallBacks, 6687 &kCFTypeDictionaryValueCallBacks); 6688 } 6689 CFDictionarySetValue(newConfig, 6690 kSCPropNetPPPAuthPassword, 6691 unique_id); 6692 CFDictionarySetValue(newConfig, 6693 kSCPropNetPPPAuthPasswordEncryption, 6694 kSCValNetPPPAuthPasswordEncryptionKeychain); 6695 ok = SCNetworkInterfaceSetConfiguration(interface, newConfig); 6696 CFRelease(newConfig); 6697 } 6698 6699 if (description != NULL) CFRelease(description); 6700 if (service != NULL) CFRelease(service); 6701 break; 6702 } 6703 6704 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : { 6705 CFDictionaryRef baseConfig = NULL; 6706 Boolean extended; 6707 SCNetworkServiceRef service = NULL; 6708 CFStringRef shared_id; 6709 6710 // get configuration 6711 extended = CFEqual(SCNetworkInterfaceGetInterfaceType(interface), kSCNetworkInterfaceTypePPP); 6712 config = SCNetworkInterfaceGetConfiguration(interface); 6713 if (extended) { 6714 baseConfig = config; 6715 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetIPSec); 6716 } 6717 6718 // get sharedSecret ID 6719 shared_id = copySharedSecretID(config, serviceID); 6720 6721 // get "Account", "Name", "Kind" 6722 if (config != NULL) { 6723 CFStringRef localIdentifier; 6724 CFStringRef localIdentifierType; 6725 6726 if (CFDictionaryGetValueIfPresent(config, 6727 kSCPropNetIPSecLocalIdentifierType, 6728 (const void **)&localIdentifierType) 6729 && CFEqual(localIdentifierType, kSCValNetIPSecLocalIdentifierTypeKeyID) 6730 && CFDictionaryGetValueIfPresent(config, 6731 kSCPropNetIPSecLocalIdentifier, 6732 (const void **)&localIdentifier) 6733 && isA_CFString(localIdentifier)) { 6734 // local identifier --> keychain "Account" 6735 account = localIdentifier; 6736 } 6737 6738 // PPP [user defined] "name" --> keychain "Name" 6739 if (!extended) { 6740 label = CFDictionaryGetValue(config, kSCPropUserDefinedName); 6741 } else { 6742 if (baseConfig != NULL) { 6743 label = CFDictionaryGetValue(baseConfig, kSCPropUserDefinedName); 6744 } 6745 } 6746 } 6747 6748 if (label == NULL) { 6749 // service name --> keychain "Name" 6750 service = (SCNetworkServiceRef)__SCNetworkServiceCreatePrivate(NULL, 6751 prefs, 6752 serviceID, 6753 interface); 6754 6755 label = SCNetworkServiceGetName(service); 6756 if (label == NULL) { 6757 // interface name --> keychain "Name" 6758 label = SCNetworkInterfaceGetLocalizedDisplayName(interface); 6759 } 6760 } 6761 6762 if (bundle != NULL) { 6763 // "IPSec Shared Secret" --> keychain "Kind" 6764 description = CFBundleCopyLocalizedString(bundle, 6765 CFSTR("KEYCHAIN_KIND_IPSEC_SHARED_SECRET"), 6766 CFSTR("IPSec Shared Secret"), 6767 NULL); 6768 } 6769 6770 // set password 6771 ok = _SCPreferencesSystemKeychainPasswordItemSet(prefs, 6772 shared_id, 6773 (label != NULL) ? label : CFSTR("Network Connection"), 6774 (description != NULL) ? description : CFSTR("IPSec Shared Secret"), 6775 account, 6776 password, 6777 options); 6778 if (ok) { 6779 CFMutableDictionaryRef newConfig = NULL; 6780 6781 if (config != NULL) { 6782 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config); 6783 } else { 6784 newConfig = CFDictionaryCreateMutable(NULL, 6785 0, 6786 &kCFTypeDictionaryKeyCallBacks, 6787 &kCFTypeDictionaryValueCallBacks); 6788 } 6789 CFDictionarySetValue(newConfig, 6790 kSCPropNetIPSecSharedSecret, 6791 shared_id); 6792 CFDictionarySetValue(newConfig, 6793 kSCPropNetIPSecSharedSecretEncryption, 6794 kSCValNetIPSecSharedSecretEncryptionKeychain); 6795 if (extended) { 6796 ok = SCNetworkInterfaceSetExtendedConfiguration(interface, 6797 kSCEntNetIPSec, 6798 newConfig); 6799 } else { 6800 ok = SCNetworkInterfaceSetConfiguration(interface, newConfig); 6801 } 6802 CFRelease(newConfig); 6803 } 6804 6805 if (description != NULL) CFRelease(description); 6806 if (service != NULL) CFRelease(service); 6807 CFRelease(shared_id); 6808 break; 6809 } 6810 6811 case kSCNetworkInterfacePasswordTypeEAPOL : { 6812 CFStringRef account = NULL; 6813 CFStringRef unique_id = NULL; 6814 6815 // get configuration 6816 config = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetEAPOL); 6817 6818 // get 802.1X identifier 6819 if (config != NULL) { 6820 unique_id = CFDictionaryGetValue(config, kEAPClientPropUserPasswordKeychainItemID); 6821 unique_id = isA_CFString(unique_id); 6822 } 6823 if (unique_id != NULL) { 6824 CFRetain(unique_id); 6825 } else { 6826 CFUUIDRef uuid; 6827 6828 uuid = CFUUIDCreate(NULL); 6829 unique_id = CFUUIDCreateString(NULL, uuid); 6830 CFRelease(uuid); 6831 } 6832 6833 // 802.1x UserName --> keychain "Account" 6834 if (config != NULL) { 6835 account = CFDictionaryGetValue(config, kEAPClientPropUserName); 6836 } 6837 6838 // get "Name", "Kind" 6839 if (bundle != NULL) { 6840 CFStringRef interface_name; 6841 6842 // "Network Connection (%@)" --> keychain "Name" 6843 interface_name = SCNetworkInterfaceGetLocalizedDisplayName(interface); 6844 if (interface_name != NULL) { 6845 CFStringRef label_fmt; 6846 6847 label_fmt = CFBundleCopyLocalizedString(bundle, 6848 CFSTR("KEYCHAIN_DESCRIPTION_EAPOL_INTERFACE"), 6849 CFSTR("Network Connection (%@)"), 6850 NULL); 6851 label = CFStringCreateWithFormat(NULL, NULL, label_fmt, interface_name); 6852 CFRelease(label_fmt); 6853 } else { 6854 label = CFBundleCopyLocalizedString(bundle, 6855 CFSTR("KEYCHAIN_DESCRIPTION_EAPOL"), 6856 CFSTR("Network Connection"), 6857 NULL); 6858 } 6859 6860 // "802.1X Password" --> keychain "Kind" 6861 description = CFBundleCopyLocalizedString(bundle, 6862 CFSTR("KEYCHAIN_KIND_EAPOL"), 6863 CFSTR("802.1X Password"), 6864 NULL); 6865 } 6866 6867 // set password 6868 ok = _SCPreferencesSystemKeychainPasswordItemSet(prefs, 6869 unique_id, 6870 (label != NULL) ? label : CFSTR("Network Connection"), 6871 (description != NULL) ? description : CFSTR("802.1X Password"), 6872 account, 6873 password, 6874 options); 6875 if (ok) { 6876 CFMutableDictionaryRef newConfig = NULL; 6877 6878 if (config != NULL) { 6879 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config); 6880 } else { 6881 newConfig = CFDictionaryCreateMutable(NULL, 6882 0, 6883 &kCFTypeDictionaryKeyCallBacks, 6884 &kCFTypeDictionaryValueCallBacks); 6885 } 6886 CFDictionarySetValue(newConfig, 6887 kEAPClientPropUserPasswordKeychainItemID, 6888 unique_id); 6889 ok = SCNetworkInterfaceSetExtendedConfiguration(interface, 6890 kSCEntNetEAPOL, 6891 newConfig); 6892 CFRelease(newConfig); 6893 } 6894 6895 CFRelease(unique_id); 6896 if (label != NULL) CFRelease(label); 6897 if (description != NULL) CFRelease(description); 6898 break; 6899 } 6900 6901 case kSCNetworkInterfacePasswordTypeIPSecXAuth : { 6902 SCNetworkServiceRef service = NULL; 6903 CFStringRef xauth_id; 6904 6905 // get configuration 6906 config = SCNetworkInterfaceGetConfiguration(interface); 6907 6908 // get XAuth ID 6909 xauth_id = copyXAuthID(config, serviceID); 6910 6911 // get "Account", "Name", "Kind" 6912 if (config != NULL) { 6913 // auth name --> keychain "Account" 6914 account = CFDictionaryGetValue(config, kSCPropNetIPSecXAuthName); 6915 6916 // IPSec [user defined] "name" --> keychain "Name" 6917 label = CFDictionaryGetValue(config, kSCPropUserDefinedName); 6918 } 6919 6920 if (label == NULL) { 6921 // service name --> keychain "Name" 6922 service = (SCNetworkServiceRef)__SCNetworkServiceCreatePrivate(NULL, 6923 prefs, 6924 serviceID, 6925 interface); 6926 6927 label = SCNetworkServiceGetName(service); 6928 if (label == NULL) { 6929 // interface name --> keychain "Name" 6930 label = SCNetworkInterfaceGetLocalizedDisplayName(interface); 6931 } 6932 } 6933 6934 if (bundle != NULL) { 6935 // "IPSec XAuth Password" --> keychain "Kind" 6936 description = CFBundleCopyLocalizedString(bundle, 6937 CFSTR("KEYCHAIN_KIND_IPSEC_XAUTH_PASSWORD"), 6938 CFSTR("IPSec XAuth Password"), 6939 NULL); 6940 } 6941 6942 // store password 6943 ok = _SCPreferencesSystemKeychainPasswordItemSet(prefs, 6944 xauth_id, 6945 (label != NULL) ? label : CFSTR("Network Connection"), 6946 (description != NULL) ? description : CFSTR("IPSec XAuth Password"), 6947 account, 6948 password, 6949 options); 6950 if (ok) { 6951 CFMutableDictionaryRef newConfig; 6952 6953 if (config != NULL) { 6954 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config); 6955 } else { 6956 newConfig = CFDictionaryCreateMutable(NULL, 6957 0, 6958 &kCFTypeDictionaryKeyCallBacks, 6959 &kCFTypeDictionaryValueCallBacks); 6960 } 6961 CFDictionarySetValue(newConfig, 6962 kSCPropNetIPSecXAuthPassword, 6963 xauth_id); 6964 CFDictionarySetValue(newConfig, 6965 kSCPropNetIPSecXAuthPasswordEncryption, 6966 kSCValNetIPSecXAuthPasswordEncryptionKeychain); 6967 ok = SCNetworkInterfaceSetConfiguration(interface, newConfig); 6968 CFRelease(newConfig); 6969 } 6970 6971 CFRelease(xauth_id); 6972 if (description != NULL) CFRelease(description); 6973 if (service != NULL) CFRelease(service); 6974 break; 6975 } 6976 6977 case kSCNetworkInterfacePasswordTypeVPN : { 6978 SCNetworkServiceRef service = NULL; 6979 CFStringRef vpn_id; 6980 6981 // get configuration 6982 config = SCNetworkInterfaceGetConfiguration(interface); 6983 6984 // get serviceID 6985 vpn_id = getPasswordID(config, serviceID); 6986 6987 // get "Account", "Name", "Kind" 6988 if (config != NULL) { 6989 // auth name --> keychain "Account" 6990 account = CFDictionaryGetValue(config, kSCPropNetVPNAuthName); 6991 6992 // VPN [user defined] "name" --> keychain "Name" 6993 label = CFDictionaryGetValue(config, kSCPropUserDefinedName); 6994 } 6995 6996 if (label == NULL) { 6997 // service name --> keychain "Name" 6998 service = (SCNetworkServiceRef)__SCNetworkServiceCreatePrivate(NULL, 6999 prefs, 7000 serviceID, 7001 interface); 7002 7003 label = SCNetworkServiceGetName(service); 7004 if (label == NULL) { 7005 // interface name --> keychain "Name" 7006 label = SCNetworkInterfaceGetLocalizedDisplayName(interface); 7007 } 7008 } 7009 7010 if (bundle != NULL) { 7011 // "VPN Password" --> keychain "Kind" 7012 description = CFBundleCopyLocalizedString(bundle, 7013 CFSTR("KEYCHAIN_KIND_VPN_PASSWORD"), 7014 CFSTR("VPN Password"), 7015 NULL); 7016 } 7017 7018 // store password 7019 ok = _SCPreferencesSystemKeychainPasswordItemSet(prefs, 7020 vpn_id, 7021 (label != NULL) ? label : CFSTR("Network Connection"), 7022 (description != NULL) ? description : CFSTR("VPN Password"), 7023 account, 7024 password, 7025 options); 7026 if (ok) { 7027 CFMutableDictionaryRef newConfig; 7028 7029 if (config != NULL) { 7030 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config); 7031 } else { 7032 newConfig = CFDictionaryCreateMutable(NULL, 7033 0, 7034 &kCFTypeDictionaryKeyCallBacks, 7035 &kCFTypeDictionaryValueCallBacks); 7036 } 7037 CFDictionarySetValue(newConfig, 7038 kSCPropNetVPNAuthPassword, 7039 vpn_id); 7040 CFDictionarySetValue(newConfig, 7041 kSCPropNetVPNAuthPasswordEncryption, 7042 kSCValNetVPNAuthPasswordEncryptionKeychain); 7043 ok = SCNetworkInterfaceSetConfiguration(interface, newConfig); 7044 CFRelease(newConfig); 7045 } 7046 7047 if (description != NULL) CFRelease(description); 7048 if (service != NULL) CFRelease(service); 7049 break; 7050 } 7051 7052 default : 7053 _SCErrorSet(kSCStatusInvalidArgument); 7054 break; 7055 } 7056 7057 return ok; 7058} 7059 7060#pragma mark - 7061#pragma mark SCNetworkInterface [Advisory] SPIs 7062#if TARGET_OS_SIMULATOR 7063Boolean 7064SCNetworkInterfaceSetAdvisory(SCNetworkInterfaceRef interface, 7065 SCNetworkInterfaceAdvisory advisory, 7066 CFStringRef reason) 7067{ 7068#pragma unused(interface) 7069#pragma unused(advisory) 7070#pragma unused(reason) 7071 return (FALSE); 7072} 7073 7074Boolean 7075SCNetworkInterfaceAdvisoryIsSet(SCNetworkInterfaceRef interface) 7076{ 7077#pragma unused(interface) 7078 return (FALSE); 7079} 7080 7081CFStringRef 7082SCNetworkInterfaceCopyAdvisoryNotificationKey(SCNetworkInterfaceRef interface) 7083{ 7084#pragma unused(interface) 7085 return (NULL); 7086} 7087 7088#else /* TARGET_OS_SIMULATOR */ 7089Boolean 7090SCNetworkInterfaceSetAdvisory(SCNetworkInterfaceRef interface, 7091 SCNetworkInterfaceAdvisory advisory, 7092 CFStringRef reason) 7093{ 7094 IPMonitorControlRef control; 7095 SCNetworkInterfacePrivateRef interfacePrivate = 7096 (SCNetworkInterfacePrivateRef)interface; 7097 CFStringRef ifName; 7098 7099 ifName = SCNetworkInterfaceGetBSDName(interface); 7100 if (ifName == NULL) { 7101 _SCErrorSet(kSCStatusInvalidArgument); 7102 return (FALSE); 7103 } 7104 control = interfacePrivate->IPMonitorControl; 7105 if (control == NULL) { 7106 control = IPMonitorControlCreate(); 7107 if (control == NULL) { 7108 _SCErrorSet(kSCStatusFailed); 7109 return (FALSE); 7110 } 7111 interfacePrivate->IPMonitorControl = control; 7112 } 7113 return IPMonitorControlSetInterfaceAdvisory(control, 7114 ifName, 7115 advisory, 7116 reason); 7117} 7118 7119Boolean 7120SCNetworkInterfaceAdvisoryIsSet(SCNetworkInterfaceRef interface) 7121{ 7122 IPMonitorControlRef control; 7123 SCNetworkInterfacePrivateRef interfacePrivate = 7124 (SCNetworkInterfacePrivateRef)interface; 7125 CFStringRef ifName; 7126 7127 ifName = SCNetworkInterfaceGetBSDName(interface); 7128 if (ifName == NULL) { 7129 _SCErrorSet(kSCStatusInvalidArgument); 7130 return (FALSE); 7131 } 7132 control = interfacePrivate->IPMonitorControl; 7133 if (control == NULL) { 7134 control = IPMonitorControlCreate(); 7135 if (control == NULL) { 7136 _SCErrorSet(kSCStatusFailed); 7137 return (FALSE); 7138 } 7139 interfacePrivate->IPMonitorControl = control; 7140 } 7141 return IPMonitorControlInterfaceAdvisoryIsSet(control, ifName); 7142} 7143 7144CFStringRef 7145SCNetworkInterfaceCopyAdvisoryNotificationKey(SCNetworkInterfaceRef interface) 7146{ 7147 CFStringRef ifName; 7148 7149 ifName = SCNetworkInterfaceGetBSDName(interface); 7150 if (ifName == NULL) { 7151 _SCErrorSet(kSCStatusInvalidArgument); 7152 return (NULL); 7153 } 7154 return IPMonitorControlCopyInterfaceAdvisoryNotificationKey(ifName); 7155} 7156#endif /* TARGET_OS_SIMULATOR */ 7157 7158#pragma mark - 7159#pragma mark SCNetworkInterface [InterfaceNamer] SPIs 7160 7161 7162CFDictionaryRef 7163_SCNetworkInterfaceCopyInterfaceInfo(SCNetworkInterfaceRef interface) 7164{ 7165 CFMutableDictionaryRef info; 7166 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 7167 CFStringRef name; 7168 7169 if (interface == NULL) { 7170 return NULL; 7171 } 7172 7173 info = CFDictionaryCreateMutable(NULL, 7174 0, 7175 &kCFTypeDictionaryKeyCallBacks, 7176 &kCFTypeDictionaryValueCallBacks); 7177 7178 // add non-localized interface name 7179 name = __SCNetworkInterfaceGetNonLocalizedDisplayName(interface); 7180 if (name != NULL) { 7181 CFDictionaryAddValue(info, kSCPropUserDefinedName, name); 7182 } 7183 7184 // add USB info 7185 if ((interfacePrivate->usb.vid != NULL) || (interfacePrivate->usb.pid != NULL)) { 7186#if !TARGET_OS_SIMULATOR 7187 if (interfacePrivate->usb.name != NULL) { 7188 CFDictionaryAddValue(info, CFSTR(kUSBProductString), interfacePrivate->usb.name); 7189 } 7190 if (interfacePrivate->usb.vid != NULL) { 7191 CFDictionaryAddValue(info, CFSTR(kUSBVendorID), interfacePrivate->usb.vid); 7192 } 7193 if (interfacePrivate->usb.pid != NULL) { 7194 CFDictionaryAddValue(info, CFSTR(kUSBProductID), interfacePrivate->usb.pid); 7195 } 7196#endif // !TARGET_OS_SIMULATOR 7197 } 7198 7199 if (CFDictionaryGetCount(info) == 0) { 7200 // do not return an empty dictionary 7201 CFRelease(info); 7202 info = NULL; 7203 } 7204 7205 return info; 7206} 7207 7208 7209SCNetworkInterfaceRef 7210_SCNetworkInterfaceCreateWithIONetworkInterfaceObject(io_object_t if_obj) 7211{ 7212 SCNetworkInterfaceRef interface = NULL; 7213 7214 /* initialize runtime */ 7215 pthread_once(&initialized, __SCNetworkInterfaceInitialize); 7216 7217 if (IOObjectConformsTo(if_obj, kIONetworkInterfaceClass)) { 7218 interface = createInterface(if_obj, processNetworkInterface, NULL); 7219 } else if (IOObjectConformsTo(if_obj, kIOSerialBSDServiceValue)) { 7220 interface = createInterface(if_obj, processSerialInterface, kSCNetworkInterfaceHiddenPortKey); 7221 } 7222 7223 return interface; 7224} 7225 7226 7227CFStringRef 7228_SCNetworkInterfaceGetConfigurationAction(SCNetworkInterfaceRef interface) 7229{ 7230 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 7231 7232 return interfacePrivate->configurationAction; 7233} 7234 7235 7236CFDataRef 7237_SCNetworkInterfaceGetHardwareAddress(SCNetworkInterfaceRef interface) 7238{ 7239 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 7240 7241 return interfacePrivate->address; 7242} 7243 7244 7245CFStringRef 7246_SCNetworkInterfaceGetIOInterfaceNamePrefix(SCNetworkInterfaceRef interface) 7247{ 7248 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 7249 7250 return interfacePrivate->prefix; 7251} 7252 7253 7254CFNumberRef 7255_SCNetworkInterfaceGetIOInterfaceType(SCNetworkInterfaceRef interface) 7256{ 7257 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 7258 7259 return interfacePrivate->type; 7260} 7261 7262 7263CFNumberRef 7264_SCNetworkInterfaceGetIOInterfaceUnit(SCNetworkInterfaceRef interface) 7265{ 7266 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 7267 7268 return interfacePrivate->unit; 7269} 7270 7271 7272static void 7273update_ift_family(SCNetworkInterfaceRef interface) 7274{ 7275 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 7276 7277 // note: family/subfamily are not in IORegistry, fetch with ioctl() 7278 7279 if ((interfacePrivate->family == NULL) && (interfacePrivate->subfamily == NULL)) { 7280 CFStringRef bsdName = SCNetworkInterfaceGetBSDName(interface); 7281 struct ifreq ifr; 7282 7283 memset(&ifr, 0, sizeof(ifr)); 7284 if ((bsdName != NULL) && 7285 _SC_cfstring_to_cstring(bsdName, ifr.ifr_name, sizeof(ifr.ifr_name), kCFStringEncodingASCII) != NULL) { 7286 int s; 7287 7288 s = socket(AF_INET, SOCK_DGRAM, 0); 7289 if (s != -1) { 7290 if (ioctl(s, SIOCGIFTYPE, (caddr_t)&ifr) == -1) { 7291 ifr.ifr_type.ift_family = 0; 7292 ifr.ifr_type.ift_subfamily = 0; 7293 } 7294 close(s); 7295 } 7296 } 7297 7298 interfacePrivate->family = CFNumberCreate(NULL, 7299 kCFNumberSInt32Type, 7300 &ifr.ifr_type.ift_family); 7301 interfacePrivate->subfamily = CFNumberCreate(NULL, 7302 kCFNumberSInt32Type, 7303 &ifr.ifr_type.ift_subfamily); 7304 } 7305} 7306 7307 7308CFNumberRef 7309_SCNetworkInterfaceGetFamilyType(SCNetworkInterfaceRef interface) 7310{ 7311 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 7312 7313 // note: family not in IORegistry, fetch with ioctl() 7314 7315 if (interfacePrivate->family == NULL) { 7316 update_ift_family(interface); 7317 } 7318 7319 return interfacePrivate->family; 7320} 7321 7322 7323CFNumberRef 7324_SCNetworkInterfaceGetFamilySubType(SCNetworkInterfaceRef interface) 7325{ 7326 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 7327 7328 // note: subfamily not in IORegistry, fetch with ioctl() 7329 7330 if (interfacePrivate->subfamily == NULL) { 7331 update_ift_family(interface); 7332 } 7333 7334 return interfacePrivate->subfamily; 7335} 7336 7337 7338CFStringRef 7339_SCNetworkInterfaceGetIOPath(SCNetworkInterfaceRef interface) 7340{ 7341 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 7342 7343 return interfacePrivate->path; 7344} 7345 7346 7347uint64_t 7348_SCNetworkInterfaceGetIORegistryEntryID(SCNetworkInterfaceRef interface) 7349{ 7350 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 7351 7352 return interfacePrivate->entryID; 7353} 7354 7355 7356__private_extern__ 7357Boolean 7358__SCNetworkInterfaceIsActive (SCNetworkInterfaceRef interface) 7359{ 7360 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 7361 7362 return interfacePrivate->active; 7363} 7364 7365 7366Boolean 7367_SCNetworkInterfaceIsBuiltin(SCNetworkInterfaceRef interface) 7368{ 7369 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 7370 7371 return interfacePrivate->builtin; 7372} 7373 7374 7375Boolean 7376_SCNetworkInterfaceIsTrustRequired(SCNetworkInterfaceRef interface) 7377{ 7378 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 7379 7380 return interfacePrivate->trustRequired; 7381} 7382 7383 7384#pragma mark - 7385#pragma mark SCNetworkInterface SPIs 7386 7387 7388#if TARGET_OS_OSX 7389 7390SCNetworkInterfaceRef 7391_SCNetworkInterfaceCopyBTPANInterface(void) 7392{ 7393 CFDictionaryRef dict; 7394 SCNetworkInterfaceRef interface = NULL; 7395 CFStringRef key; 7396 7397 key = SCDynamicStoreKeyCreate(NULL, CFSTR("%@" "InterfaceNamer"), kSCDynamicStoreDomainPlugin); 7398 dict = SCDynamicStoreCopyValue(NULL, key); 7399 CFRelease(key); 7400 if (dict != NULL) { 7401 CFDataRef addr; 7402 CFStringRef if_name; 7403 SCNetworkInterfacePrivateRef interfacePrivate; 7404 7405 if (isA_CFDictionary(dict) && 7406 CFDictionaryGetValueIfPresent(dict, 7407 kInterfaceNamerKey_BT_PAN_Name, 7408 (const void **)&if_name) && 7409 isA_CFString(if_name)) { 7410 CFMutableDictionaryRef entity; 7411 7412 entity = CFDictionaryCreateMutable(NULL, 7413 0, 7414 &kCFTypeDictionaryKeyCallBacks, 7415 &kCFTypeDictionaryValueCallBacks); 7416 CFDictionarySetValue(entity, 7417 kSCPropNetInterfaceType, 7418 kSCValNetInterfaceTypeEthernet); 7419 CFDictionarySetValue(entity, 7420 kSCPropNetInterfaceDeviceName, 7421 if_name); 7422 CFDictionarySetValue(entity, 7423 kSCPropUserDefinedName, 7424 CFSTR(BT_PAN_NAME)); 7425 interface = _SCNetworkInterfaceCreateWithEntity(NULL, entity, NULL); 7426 CFRelease(entity); 7427 } 7428 7429 interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 7430 7431 if ((interfacePrivate != NULL) && 7432 (interfacePrivate->address == NULL) && 7433 CFDictionaryGetValueIfPresent(dict, 7434 kInterfaceNamerKey_BT_PAN_Mac, 7435 (const void **)&addr) && 7436 isA_CFData(addr)) { 7437 interfacePrivate->address = CFRetain(addr); 7438 } 7439 7440 CFRelease(dict); 7441 } 7442 7443 return interface; 7444} 7445#endif // TARGET_OS_OSX 7446 7447 7448CFStringRef 7449_SCNetworkInterfaceCopySlashDevPath(SCNetworkInterfaceRef interface) 7450{ 7451 io_registry_entry_t device; 7452 io_iterator_t device_iterator = MACH_PORT_NULL; 7453 CFStringRef device_path = NULL; 7454 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 7455 kern_return_t kr; 7456 CFStringRef match_keys[2]; 7457 CFTypeRef match_vals[2]; 7458 CFDictionaryRef match_dict; 7459 CFDictionaryRef matching; 7460 7461 if (interfacePrivate->entity_device == NULL) { 7462 return NULL; 7463 } 7464 7465 if (interfacePrivate->entity_device_unique == NULL) { 7466 goto done; 7467 } 7468 7469 match_keys[0] = CFSTR(kIOTTYBaseNameKey); 7470 match_vals[0] = interfacePrivate->entity_device; 7471 match_dict = CFDictionaryCreate(NULL, 7472 (const void **)match_keys, 7473 (const void **)match_vals, 7474 1, 7475 &kCFTypeDictionaryKeyCallBacks, 7476 &kCFTypeDictionaryValueCallBacks); 7477 7478 match_keys[0] = CFSTR(kIOProviderClassKey); 7479 match_vals[0] = CFSTR(kIOSerialBSDServiceValue); 7480 match_keys[1] = CFSTR(kIOPropertyMatchKey); 7481 match_vals[1] = match_dict; 7482 matching = CFDictionaryCreate(NULL, 7483 (const void **)match_keys, 7484 (const void **)match_vals, 7485 sizeof(match_keys)/sizeof(match_keys[0]), 7486 &kCFTypeDictionaryKeyCallBacks, 7487 &kCFTypeDictionaryValueCallBacks); 7488 CFRelease(match_dict); 7489 7490 // note: this "matching" dictionary will be consumed by the call to IOServiceGetMatchingServices 7491 kr = IOServiceGetMatchingServices(masterPort, matching, &device_iterator); 7492 if (kr != kIOReturnSuccess) { 7493 SC_log(LOG_INFO, "IOServiceGetMatchingServices() failed, kr = 0x%x", kr); 7494 goto done; 7495 } 7496 7497 while ((device_path == NULL) && 7498 ((device = IOIteratorNext(device_iterator)) != MACH_PORT_NULL)) { 7499 CFDictionaryRef overrides; 7500 7501 overrides = IORegistryEntrySearchCFProperty(device, 7502 kIOServicePlane, 7503 kSCNetworkInterfaceNetworkConfigurationOverridesKey, 7504 NULL, 7505 kIORegistryIterateRecursively | kIORegistryIterateParents); 7506 if (overrides != NULL) { 7507 CFDictionaryRef modemOverrides; 7508 7509 modemOverrides = CFDictionaryGetValue(overrides, kSCEntNetModem); 7510 if (modemOverrides != NULL) { 7511 CFRetain(modemOverrides); 7512 } 7513 CFRelease(overrides); 7514 overrides = modemOverrides; 7515 } 7516 if (overrides == NULL) { 7517 overrides = IORegistryEntrySearchCFProperty(device, 7518 kIOServicePlane, 7519 CFSTR("DeviceModemOverrides"), 7520 NULL, 7521 kIORegistryIterateRecursively | kIORegistryIterateParents); 7522 } 7523 if (overrides != NULL) { 7524 if (isA_CFDictionary(overrides)) { 7525 CFStringRef matchIdentifier; 7526 7527 matchIdentifier = CFDictionaryGetValue(overrides, CFSTR("UniqueIdentifier")); 7528 if (isA_CFString(matchIdentifier) && 7529 CFEqual(interfacePrivate->entity_device_unique, matchIdentifier)) { 7530 device_path = IORegistryEntryCreateCFProperty(device, 7531 CFSTR(kIOTTYDeviceKey), 7532 NULL, 7533 0); 7534 } 7535 } 7536 CFRelease(overrides); 7537 } 7538 IOObjectRelease(device); 7539 } 7540 7541 IOObjectRelease(device_iterator); 7542 7543 done : 7544 7545 if (device_path == NULL) { 7546 // if we haven't found an exact match to our UniqueIdentifier 7547 // so we simply return the base name. 7548 device_path = SCNetworkInterfaceGetBSDName(interface); 7549 if (device_path != NULL) { 7550 CFRetain(device_path); 7551 } 7552 } 7553 7554 return device_path; 7555} 7556 7557 7558#pragma mark - 7559 7560 7561Boolean 7562_SCNetworkInterfaceIsApplePreconfigured(SCNetworkInterfaceRef interface) 7563{ 7564#if TARGET_OS_SIMULATOR 7565#pragma unused(interface) 7566#else // TARGET_OS_SIMULATOR 7567 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 7568 7569 if (!_SCNetworkInterfaceIsHiddenConfiguration(interface)) { 7570 // if not HiddenConfiguration 7571 return FALSE; 7572 } 7573 7574 if ((interfacePrivate->overrides == NULL) || 7575 (!CFDictionaryContainsKey(interfacePrivate->overrides, kSCNetworkProtocolTypeIPv4) && 7576 !CFDictionaryContainsKey(interfacePrivate->overrides, kSCNetworkProtocolTypeIPv6))) { 7577 // if no [IPv4/IPv6] configuration overrides 7578 return FALSE; 7579 } 7580 7581 if (_SCNetworkInterfaceIsBuiltin(interface)) { 7582 // if built-in (and overrides are present) 7583 return TRUE; 7584 } 7585 7586 if (_SCNetworkInterfaceIsCarPlay(interface)) { 7587 // if CarPlay (and overrides are present) 7588 return TRUE; 7589 } 7590 7591 if (isA_CFNumber(interfacePrivate->usb.vid)) { 7592 int vid; 7593 7594 if (CFNumberGetValue(interfacePrivate->usb.vid, kCFNumberIntType, &vid) && 7595 (vid == kIOUSBVendorIDAppleComputer)) { 7596 // if Apple interface (and overrides are present) 7597 return TRUE; 7598 } 7599 } 7600#endif // TARGET_OS_SIMULATOR 7601 7602 return FALSE; 7603} 7604 7605 7606Boolean 7607_SCNetworkInterfaceIsBluetoothPAN(SCNetworkInterfaceRef interface) 7608{ 7609 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 7610 7611 return (interfacePrivate->sort_order == kSortBluetoothPAN_GN); 7612} 7613 7614 7615Boolean 7616_SCNetworkInterfaceIsBluetoothPAN_NAP(SCNetworkInterfaceRef interface) 7617{ 7618 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 7619 7620 return (interfacePrivate->sort_order == kSortBluetoothPAN_NAP); 7621} 7622 7623 7624Boolean 7625_SCNetworkInterfaceIsBluetoothP2P(SCNetworkInterfaceRef interface) 7626{ 7627 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 7628 7629 return (interfacePrivate->sort_order == kSortBluetoothPAN_U); 7630} 7631 7632 7633Boolean 7634_SCNetworkInterfaceIsCarPlay(SCNetworkInterfaceRef interface) 7635{ 7636 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 7637 7638 return (interfacePrivate->sort_order == kSortCarPlay); 7639} 7640 7641 7642Boolean 7643_SCNetworkInterfaceIsHiddenConfiguration(SCNetworkInterfaceRef interface) 7644{ 7645 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 7646 7647 return interfacePrivate->hidden; 7648} 7649 7650 7651Boolean 7652_SCNetworkInterfaceIsTethered(SCNetworkInterfaceRef interface) 7653{ 7654 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 7655 7656 return (interfacePrivate->sort_order == kSortTethered); 7657} 7658 7659 7660Boolean 7661_SCNetworkInterfaceIsThunderbolt(SCNetworkInterfaceRef interface) 7662{ 7663 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 7664 CFStringRef interfaceType; 7665 7666 if (!isA_SCNetworkInterface(interface)) { 7667 return FALSE; 7668 } 7669 7670 interfaceType = SCNetworkInterfaceGetInterfaceType(interface); 7671 if (CFEqual(interfaceType, kSCNetworkInterfaceTypeBridge)) { 7672 CFIndex i; 7673 CFArrayRef members; 7674 CFIndex n; 7675 7676 members = SCBridgeInterfaceGetMemberInterfaces(interface); 7677 n = (members != NULL) ? CFArrayGetCount(members) : 0; 7678 if (n == 0) { 7679 // if an empty bridge 7680 return FALSE; 7681 } 7682 7683 for (i = 0; i < n; i++) { 7684 SCNetworkInterfaceRef member; 7685 SCNetworkInterfacePrivateRef memberPrivate; 7686 7687 member = CFArrayGetValueAtIndex(members, i); 7688 memberPrivate = (SCNetworkInterfacePrivateRef)member; 7689 if (memberPrivate->sort_order != kSortThunderbolt) { 7690 return FALSE; 7691 } 7692 } 7693 7694 // if Ethernet Bridge interface with only Thunderbolt [IP] members 7695 return TRUE; 7696 } 7697 7698 return (interfacePrivate->sort_order == kSortThunderbolt); 7699} 7700 7701 7702#pragma mark - 7703 7704 7705CFDictionaryRef 7706SCNetworkInterfaceGetQoSMarkingPolicy(SCNetworkInterfaceRef interface) 7707{ 7708 CFDictionaryRef policy; 7709 7710 if (!isA_SCNetworkInterface(interface)) { 7711 _SCErrorSet(kSCStatusInvalidArgument); 7712 return NULL; 7713 } 7714 7715 policy = __SCNetworkInterfaceGetConfiguration(interface, kSCEntNetQoSMarkingPolicy); 7716 if (policy == NULL) { 7717 _SCErrorSet(kSCStatusOK); 7718 } 7719 7720 return policy; 7721} 7722 7723Boolean 7724SCNetworkInterfaceSetQoSMarkingPolicy(SCNetworkInterfaceRef interface, CFDictionaryRef policy) 7725{ 7726 Boolean ok; 7727 7728 if (!isA_SCNetworkInterface(interface)) { 7729 _SCErrorSet(kSCStatusInvalidArgument); 7730 return FALSE; 7731 } 7732 7733 ok = __SCNetworkInterfaceSetConfiguration(interface, kSCEntNetQoSMarkingPolicy, policy, FALSE); 7734 if (ok) { 7735 SC_log(LOG_DEBUG, "SCNetworkInterfaceSetQoSMarkingPolicy(): %@ -> %@", 7736 interface, 7737 policy != NULL ? policy : (CFDictionaryRef)CFSTR("NULL")); 7738 } 7739 7740 return ok; 7741} 7742 7743 7744#pragma mark - 7745#pragma mark SCNetworkInterface [internal] SPIs 7746 7747 7748__private_extern__ 7749SCNetworkInterfacePrivateRef 7750__SCNetworkInterfaceCreateCopy(CFAllocatorRef allocator, 7751 SCNetworkInterfaceRef interface, 7752 SCPreferencesRef prefs, 7753 CFStringRef serviceID) 7754{ 7755#pragma unused(allocator) 7756 SCNetworkInterfacePrivateRef oldPrivate = (SCNetworkInterfacePrivateRef)interface; 7757 SCNetworkInterfacePrivateRef newPrivate; 7758 7759 /* initialize runtime (and kSCNetworkInterfaceIPv4) */ 7760 pthread_once(&initialized, __SCNetworkInterfaceInitialize); 7761 7762 if (interface == kSCNetworkInterfaceIPv4) { 7763 return (SCNetworkInterfacePrivateRef)CFRetain(interface); 7764 } 7765 7766 newPrivate = __SCNetworkInterfaceCreatePrivate(NULL, NULL, prefs, serviceID); 7767 newPrivate->interface_type = oldPrivate->interface_type; 7768 if (oldPrivate->interface != NULL) { 7769 newPrivate->interface = (SCNetworkInterfaceRef)__SCNetworkInterfaceCreateCopy(NULL, // allocator 7770 oldPrivate->interface, // interface 7771 prefs, // [new] prefs 7772 serviceID); // [new] serviceID 7773 } 7774 if (oldPrivate->name != NULL) { 7775 newPrivate->name = CFRetain(oldPrivate->name); 7776 } 7777 if (oldPrivate->prefix != NULL) { 7778 newPrivate->prefix = CFRetain(oldPrivate->prefix); 7779 } 7780 if (oldPrivate->localized_name != NULL) { 7781 newPrivate->localized_name = CFRetain(oldPrivate->localized_name); 7782 } 7783 newPrivate->localized_key = oldPrivate->localized_key; 7784 if (oldPrivate->localized_arg1 != NULL) { 7785 newPrivate->localized_arg1 = CFRetain(oldPrivate->localized_arg1); 7786 } 7787 if (oldPrivate->localized_arg2 != NULL) { 7788 newPrivate->localized_arg2 = CFRetain(oldPrivate->localized_arg2); 7789 } 7790 if (oldPrivate->unsaved != NULL) { 7791 newPrivate->unsaved = CFDictionaryCreateMutableCopy(NULL, 0, oldPrivate->unsaved); 7792 } 7793 if (oldPrivate->entity_device != NULL) { 7794 newPrivate->entity_device = CFRetain(oldPrivate->entity_device); 7795 } 7796 if (oldPrivate->entity_device_unique != NULL) { 7797 newPrivate->entity_device_unique = CFRetain(oldPrivate->entity_device_unique); 7798 } 7799 newPrivate->entity_type = oldPrivate->entity_type; 7800 newPrivate->entity_subtype = oldPrivate->entity_subtype; 7801 if (oldPrivate->supported_interface_types != NULL) { 7802 newPrivate->supported_interface_types = CFArrayCreateMutableCopy(NULL, 0, oldPrivate->supported_interface_types); 7803 } 7804 if (oldPrivate->supported_protocol_types != NULL) { 7805 newPrivate->supported_protocol_types = CFArrayCreateMutableCopy(NULL, 0, oldPrivate->supported_protocol_types); 7806 } 7807 if (oldPrivate->address != NULL) { 7808 newPrivate->address = CFRetain(oldPrivate->address); 7809 } 7810 newPrivate->builtin = oldPrivate->builtin; 7811 if (oldPrivate->configurationAction != NULL) { 7812 newPrivate->configurationAction = CFRetain(oldPrivate->configurationAction); 7813 } 7814 newPrivate->hidden = oldPrivate->hidden; 7815#if TARGET_OS_IPHONE 7816 newPrivate->trustRequired = oldPrivate->trustRequired; 7817#endif // TARGET_OS_IPHONE 7818 if (oldPrivate->location != NULL) { 7819 newPrivate->location = CFRetain(oldPrivate->location); 7820 } 7821 if (oldPrivate->path != NULL) { 7822 newPrivate->path = CFRetain(oldPrivate->path); 7823 } 7824 newPrivate->entryID = oldPrivate->entryID; 7825 if (oldPrivate->overrides != NULL) { 7826 newPrivate->overrides = CFDictionaryCreateMutableCopy(NULL, 0, oldPrivate->overrides); 7827 } 7828 if (oldPrivate->type != NULL) { 7829 newPrivate->type = CFRetain(oldPrivate->type); 7830 } 7831 if (oldPrivate->unit != NULL) { 7832 newPrivate->unit = CFRetain(oldPrivate->unit); 7833 } 7834 if (oldPrivate->family != NULL) { 7835 newPrivate->family = CFRetain(oldPrivate->family); 7836 } 7837 if (oldPrivate->subfamily != NULL) { 7838 newPrivate->subfamily = CFRetain(oldPrivate->subfamily); 7839 } 7840 if (oldPrivate->usb.name != NULL) { 7841 newPrivate->usb.name = CFRetain(oldPrivate->usb.name); 7842 } 7843 if (oldPrivate->usb.vid != NULL) { 7844 newPrivate->usb.vid = CFRetain(oldPrivate->usb.vid); 7845 } 7846 if (oldPrivate->usb.pid != NULL) { 7847 newPrivate->usb.pid = CFRetain(oldPrivate->usb.pid); 7848 } 7849 newPrivate->sort_order = oldPrivate->sort_order; 7850 7851 newPrivate->supportsBond = oldPrivate->supportsBond; 7852 if (oldPrivate->bond.interfaces != NULL) { 7853 newPrivate->bond.interfaces = CFRetain(oldPrivate->bond.interfaces); 7854 } 7855 if (oldPrivate->bond.mode != NULL) { 7856 newPrivate->bond.mode = CFRetain(oldPrivate->bond.mode); 7857 } 7858 if (oldPrivate->bond.options != NULL) { 7859 newPrivate->bond.options = CFRetain(oldPrivate->bond.options); 7860 } 7861 7862 newPrivate->supportsBridge = oldPrivate->supportsBridge; 7863 if (oldPrivate->bridge.interfaces != NULL) { 7864 newPrivate->bridge.interfaces = CFRetain(oldPrivate->bridge.interfaces); 7865 } 7866 if (oldPrivate->bridge.options != NULL) { 7867 newPrivate->bridge.options = CFRetain(oldPrivate->bridge.options); 7868 } 7869 7870 newPrivate->supportsVLAN = oldPrivate->supportsVLAN; 7871 if (oldPrivate->vlan.interface != NULL) { 7872 newPrivate->vlan.interface = CFRetain(oldPrivate->vlan.interface); 7873 } 7874 if (oldPrivate->vlan.tag != NULL) { 7875 newPrivate->vlan.tag = CFRetain(oldPrivate->vlan.tag); 7876 } 7877 if (oldPrivate->vlan.options != NULL) { 7878 newPrivate->vlan.options = CFRetain(oldPrivate->vlan.options); 7879 } 7880 7881 return newPrivate; 7882} 7883 7884 7885__private_extern__ 7886CFArrayRef 7887__SCNetworkInterfaceCopyDeepConfiguration(SCNetworkSetRef set, SCNetworkInterfaceRef interface) 7888{ 7889 CFMutableArrayRef configs; 7890 7891 configs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 7892 7893 while (interface != NULL) { 7894 CFStringRef defaultType; 7895 CFMutableDictionaryRef interfaceConfiguration; 7896 7897 interfaceConfiguration = CFDictionaryCreateMutable(NULL, 7898 0, 7899 &kCFTypeDictionaryKeyCallBacks, 7900 &kCFTypeDictionaryValueCallBacks); 7901 7902 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface); 7903 if (defaultType != NULL) { 7904 CFDictionaryRef config; 7905 CFArrayRef extendedTypes; 7906 7907 if (set == NULL) { 7908 config = __SCNetworkInterfaceGetConfiguration(interface, defaultType); 7909 } else { 7910 config = __SCNetworkInterfaceGetDefaultConfiguration(set, interface); 7911 } 7912 if (config == NULL) { 7913 config = (CFDictionaryRef)kCFNull; 7914 } 7915 CFDictionarySetValue(interfaceConfiguration, defaultType, config); 7916 7917 extendedTypes = extendedConfigurationTypes(interface); 7918 if (extendedTypes != NULL) { 7919 CFIndex i; 7920 CFIndex n; 7921 7922 n = CFArrayGetCount(extendedTypes); 7923 for (i = 0; i < n; i++) { 7924 CFStringRef extendedType; 7925 7926 extendedType = CFArrayGetValueAtIndex(extendedTypes, i); 7927 config = __SCNetworkInterfaceGetConfiguration(interface, extendedType); 7928 if (config == NULL) { 7929 config = (CFDictionaryRef)kCFNull; 7930 } 7931 CFDictionarySetValue(interfaceConfiguration, extendedType, config); 7932 } 7933 7934 CFRelease(extendedTypes); 7935 } 7936 } 7937 7938 CFArrayAppendValue(configs, interfaceConfiguration); 7939 CFRelease(interfaceConfiguration); 7940 7941 interface = SCNetworkInterfaceGetInterface(interface); 7942 } 7943 7944 return configs; 7945} 7946 7947 7948__private_extern__ Boolean 7949__SCNetworkInterfaceIsMember(SCPreferencesRef prefs, SCNetworkInterfaceRef interface) 7950{ 7951 CFArrayRef interfaces; 7952 Boolean match = FALSE; 7953 CFMutableSetRef members; 7954 7955 members = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks); 7956 7957#if !TARGET_OS_IPHONE 7958 // add Bond [member] interfaces 7959 interfaces = SCBondInterfaceCopyAll(prefs); 7960 if (interfaces != NULL) { 7961 __SCBondInterfaceListCollectMembers(interfaces, members); 7962 CFRelease(interfaces); 7963 } 7964#endif // !TARGET_OS_IPHONE 7965 7966 // add Bridge [member] interfaces 7967 interfaces = SCBridgeInterfaceCopyAll(prefs); 7968 if (interfaces != NULL) { 7969 __SCBridgeInterfaceListCollectMembers(interfaces, members); 7970 CFRelease(interfaces); 7971 } 7972 7973 if (CFSetGetCount(members) == 0) { 7974 goto done; 7975 } 7976 7977 while (interface != NULL) { 7978 match = CFSetContainsValue(members, interface); 7979 if (match) { 7980 // if the interface is a member of an 7981 // Ethernet Bond or Bridge 7982 break; 7983 } 7984 7985 interface = SCNetworkInterfaceGetInterface(interface); 7986 } 7987 7988 done : 7989 7990 CFRelease(members); 7991 return match; 7992} 7993 7994 7995__private_extern__ 7996void 7997__SCNetworkInterfaceSetDeepConfiguration(SCNetworkSetRef set, SCNetworkInterfaceRef interface, CFArrayRef configs) 7998{ 7999 CFIndex i; 8000 8001 for (i = 0; interface != NULL; i++) { 8002 CFStringRef defaultType; 8003 CFDictionaryRef interfaceConfiguration; 8004 Boolean ok; 8005 8006 interfaceConfiguration = (configs != NULL) ? CFArrayGetValueAtIndex(configs, i) : NULL; 8007 8008 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface); 8009 if (defaultType != NULL) { 8010 CFDictionaryRef config; 8011 CFArrayRef extendedTypes; 8012 8013 config = (interfaceConfiguration != NULL) ? CFDictionaryGetValue(interfaceConfiguration, defaultType) 8014 : NULL; 8015 if (config == (CFDictionaryRef)kCFNull) { 8016 config = NULL; 8017 } 8018 if (set == NULL) { 8019 // if service is not associated with the set 8020 ok = __SCNetworkInterfaceSetConfiguration(interface, defaultType, config, TRUE); 8021 } else { 8022 // apply default configuration to this set 8023 ok = __SCNetworkInterfaceSetDefaultConfiguration(set, interface, defaultType, config, TRUE); 8024 } 8025 if (ok) { 8026 SC_log(LOG_DEBUG, "__SCNetworkInterfaceSetDeepConfiguration(): %@, %@ -> %@", 8027 interface, 8028 defaultType, 8029 config != NULL ? config : (CFDictionaryRef)CFSTR("NULL")); 8030 } else { 8031 SC_log(LOG_INFO, "__SCNetworkInterfaceSetDeepConfiguration() failed, interface=%@, type=%@", 8032 interface, 8033 defaultType); 8034 } 8035 8036 extendedTypes = extendedConfigurationTypes(interface); 8037 if (extendedTypes != NULL) { 8038 CFIndex j; 8039 CFIndex n; 8040 8041 n = CFArrayGetCount(extendedTypes); 8042 for (j = 0; j < n; j++) { 8043 CFStringRef extendedType; 8044 8045 extendedType = CFArrayGetValueAtIndex(extendedTypes, j); 8046 config = (interfaceConfiguration != NULL) ? CFDictionaryGetValue(interfaceConfiguration, extendedType) 8047 : NULL; 8048 if (config == (CFDictionaryRef)kCFNull) { 8049 config = NULL; 8050 } 8051 ok = __SCNetworkInterfaceSetConfiguration(interface, extendedType, config, TRUE); 8052 if (ok) { 8053 SC_log(LOG_DEBUG, "__SCNetworkInterfaceSetDeepConfiguration(): %@, %@ -> %@", 8054 interface, 8055 extendedType, 8056 config != NULL ? config : (CFDictionaryRef)CFSTR("NULL")); 8057 } else { 8058 SC_log(LOG_INFO, "__SCNetworkInterfaceSetDeepConfiguration() failed, interface=%@, type=%@", 8059 interface, 8060 extendedType); 8061 } 8062 } 8063 8064 CFRelease(extendedTypes); 8065 } 8066 } 8067 8068 interface = SCNetworkInterfaceGetInterface(interface); 8069 } 8070 8071 return; 8072} 8073 8074 8075SCNetworkInterfaceRef 8076_SCNetworkInterfaceCopyActive(SCDynamicStoreRef store, CFStringRef bsdName) 8077{ 8078 SCNetworkInterfaceRef interface; 8079 8080 interface = _SCNetworkInterfaceCreateWithBSDName(NULL, bsdName, kIncludeAllVirtualInterfaces); 8081 if (interface == NULL) { 8082 return NULL; 8083 } 8084 8085 if (store != NULL) { 8086 SCNetworkInterfacePrivateRef interfacePrivate = 8087 (SCNetworkInterfacePrivateRef)interface; 8088 8089 CFRetain(store); 8090 interfacePrivate->store = store; 8091 } 8092 8093 return interface; 8094} 8095 8096 8097#if !TARGET_OS_SIMULATOR 8098SCNetworkServicePrimaryRank 8099SCNetworkInterfaceGetPrimaryRank(SCNetworkInterfaceRef interface) 8100{ 8101 IPMonitorControlRef control; 8102 SCNetworkInterfacePrivateRef interfacePrivate = 8103 (SCNetworkInterfacePrivateRef)interface; 8104 SCNetworkServicePrimaryRank rank = kSCNetworkServicePrimaryRankDefault; 8105 8106 control = interfacePrivate->IPMonitorControl; 8107 if (control != NULL) { 8108 CFStringRef ifName; 8109 8110 ifName = SCNetworkInterfaceGetBSDName(interface); 8111 if (ifName != NULL) { 8112 rank = IPMonitorControlGetInterfacePrimaryRank(control, 8113 ifName); 8114 } 8115 else { 8116 _SCErrorSet(kSCStatusInvalidArgument); 8117 } 8118 } 8119 return rank; 8120} 8121 8122Boolean 8123SCNetworkInterfaceSetPrimaryRank(SCNetworkInterfaceRef interface, 8124 SCNetworkServicePrimaryRank newRank) 8125{ 8126 IPMonitorControlRef control; 8127 SCNetworkInterfacePrivateRef interfacePrivate = 8128 (SCNetworkInterfacePrivateRef)interface; 8129 CFStringRef ifName; 8130 8131 ifName = SCNetworkInterfaceGetBSDName(interface); 8132 if (ifName == NULL) { 8133 _SCErrorSet(kSCStatusInvalidArgument); 8134 return (FALSE); 8135 } 8136 control = interfacePrivate->IPMonitorControl; 8137 if (control == NULL) { 8138 control = IPMonitorControlCreate(); 8139 if (control == NULL) { 8140 _SCErrorSet(kSCStatusFailed); 8141 return (FALSE); 8142 } 8143 interfacePrivate->IPMonitorControl = control; 8144 } 8145 return IPMonitorControlSetInterfacePrimaryRank(control, 8146 ifName, 8147 newRank); 8148} 8149 8150Boolean 8151SCNetworkInterfaceGetDisableUntilNeeded(SCNetworkInterfaceRef interface) 8152{ 8153 Boolean disable_until_needed = FALSE; 8154 CFNumberRef disable_prop = NULL; 8155 CFIndex interfaceIndex; 8156 SCNetworkInterfacePrivateRef interfacePrivate 8157 = (SCNetworkInterfacePrivateRef)interface; 8158 CFArrayRef path_list; 8159 8160 if (interfacePrivate->prefs == NULL) { 8161 _SCErrorSet(kSCStatusInvalidArgument); 8162 return (FALSE); 8163 } 8164 interfaceIndex = findPerInterfaceConfiguration(interface); 8165 if (interfaceIndex == kCFNotFound) { 8166 _SCErrorSet(kSCStatusInvalidArgument); 8167 return (FALSE); 8168 } 8169 path_list = copyPerInterfaceConfigurationPaths(interfacePrivate, NULL); 8170 if (path_list != NULL) { 8171 CFDictionaryRef config; 8172 CFStringRef path = CFArrayGetValueAtIndex(path_list, 0); 8173 8174 config = __getPrefsConfiguration(interfacePrivate->prefs, path); 8175 CFRelease(path_list); 8176 if (config != NULL) { 8177 int disable = 0; 8178 8179 disable_prop = CFDictionaryGetValue(config, kSCPropDisableUntilNeeded); 8180 disable_prop = isA_CFNumber(disable_prop); 8181 if (disable_prop != NULL) { 8182 if (CFNumberGetValue(disable_prop, kCFNumberIntType, &disable)) { 8183 disable_until_needed = (disable != 0) ? TRUE : FALSE; 8184 } 8185 else { 8186 /* invalid property, ignore it */ 8187 disable_prop = NULL; 8188 } 8189 } 8190 } 8191 } 8192 if (disable_prop == NULL) { 8193 disable_until_needed 8194 = _SCNetworkInterfaceIsTethered(interface); 8195 } 8196 _SCErrorSet(kSCStatusOK); 8197 return (disable_until_needed); 8198} 8199 8200Boolean 8201__SCNetworkInterfaceSetDisableUntilNeededValue(SCNetworkInterfaceRef interface, CFTypeRef disable) 8202{ 8203 CFIndex count; 8204 CFIndex i; 8205 CFIndex interfaceIndex; 8206 SCNetworkInterfacePrivateRef interfacePrivate 8207 = (SCNetworkInterfacePrivateRef)interface; 8208 Boolean ok = TRUE; 8209 CFArrayRef path_list; 8210 8211 if (interfacePrivate->prefs == NULL) { 8212 _SCErrorSet(kSCStatusInvalidArgument); 8213 return (FALSE); 8214 } 8215 if ((disable != NULL) && !isA_CFNumber(disable)) { 8216 _SCErrorSet(kSCStatusInvalidArgument); 8217 return (FALSE); 8218 } 8219 interfaceIndex = findPerInterfaceConfiguration(interface); 8220 if (interfaceIndex == kCFNotFound) { 8221 _SCErrorSet(kSCStatusInvalidArgument); 8222 return (FALSE); 8223 } 8224 path_list = copyPerInterfaceConfigurationPaths(interfacePrivate, NULL); 8225 if (path_list == NULL) { 8226 _SCErrorSet(kSCStatusInvalidArgument); 8227 return (FALSE); 8228 } 8229 count = CFArrayGetCount(path_list); 8230 for (i = 0; i < count; i++) { 8231 CFDictionaryRef config; 8232 CFMutableDictionaryRef new_config; 8233 CFStringRef path = CFArrayGetValueAtIndex(path_list, i); 8234 8235 config = __getPrefsConfiguration(interfacePrivate->prefs, path); 8236 if (config != NULL) { 8237 new_config 8238 = CFDictionaryCreateMutableCopy(NULL, 0, config); 8239 } else { 8240 new_config 8241 = CFDictionaryCreateMutable(NULL, 0, 8242 &kCFTypeDictionaryKeyCallBacks, 8243 &kCFTypeDictionaryValueCallBacks); 8244 } 8245 if (disable != NULL) { 8246 CFDictionarySetValue(new_config, kSCPropDisableUntilNeeded, disable); 8247 } else { 8248 CFDictionaryRemoveValue(new_config, kSCPropDisableUntilNeeded); 8249 } 8250 ok = __setPrefsConfiguration(interfacePrivate->prefs, 8251 path, 8252 (CFDictionaryGetCount(new_config) > 0) ? new_config : NULL, 8253 FALSE); 8254 CFRelease(new_config); 8255 if (!ok) { 8256 break; 8257 } 8258 } 8259 CFRelease(path_list); 8260 return (ok); 8261} 8262 8263Boolean 8264SCNetworkInterfaceSetDisableUntilNeeded(SCNetworkInterfaceRef interface, Boolean disable) 8265{ 8266 Boolean ok; 8267 const int one = 1; 8268 CFNumberRef num; 8269 const int zero = 0; 8270 8271 num = CFNumberCreate(NULL, kCFNumberIntType, disable ? &one : &zero); 8272 ok = __SCNetworkInterfaceSetDisableUntilNeededValue(interface, num); 8273 CFRelease(num); 8274 8275 return ok; 8276} 8277 8278#else // !TARGET_OS_SIMULATOR 8279 8280SCNetworkServicePrimaryRank 8281SCNetworkInterfaceGetPrimaryRank(SCNetworkInterfaceRef interface) 8282{ 8283#pragma unused(interface) 8284 return (kSCNetworkServicePrimaryRankDefault); 8285} 8286 8287Boolean 8288SCNetworkInterfaceSetPrimaryRank(SCNetworkInterfaceRef interface, 8289 SCNetworkServicePrimaryRank newRank) 8290{ 8291#pragma unused(interface) 8292#pragma unused(newRank) 8293 _SCErrorSet(kSCStatusInvalidArgument); 8294 return (FALSE); 8295} 8296 8297Boolean 8298SCNetworkInterfaceGetDisableUntilNeeded(SCNetworkInterfaceRef interface) 8299{ 8300#pragma unused(interface) 8301 return (FALSE); 8302} 8303 8304Boolean 8305__SCNetworkInterfaceSetDisableUntilNeededValue(SCNetworkInterfaceRef interface, CFTypeRef disable) 8306{ 8307#pragma unused(interface) 8308#pragma unused(disable) 8309 return (FALSE); 8310} 8311 8312Boolean 8313SCNetworkInterfaceSetDisableUntilNeeded(SCNetworkInterfaceRef interface, Boolean disable) 8314{ 8315#pragma unused(interface) 8316#pragma unused(disable) 8317 _SCErrorSet(kSCStatusInvalidArgument); 8318 return (FALSE); 8319} 8320 8321#endif // !TARGET_OS_SIMULATOR 8322 8323 8324__private_extern__ 8325CFArrayRef // SCNetworkInterfaceRef 8326__SCNetworkInterfaceCopyStoredWithPreferences(SCPreferencesRef ni_prefs) 8327{ 8328 CFStringRef defaultNetworkInterfacePath = NULL; 8329 CFArrayRef if_list; 8330 CFMutableArrayRef interfaceList = NULL; 8331 SCNetworkInterfaceRef interfaceNamer = NULL; 8332 8333 /* initialize runtime */ 8334 pthread_once(&initialized, __SCNetworkInterfaceInitialize); 8335 8336 if (ni_prefs == NULL) { 8337 defaultNetworkInterfacePath = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@/%@"), PREFS_DEFAULT_DIR, NETWORK_INTERFACES_PREFS); 8338 assert(defaultNetworkInterfacePath != NULL); 8339 ni_prefs = SCPreferencesCreate(NULL, CFSTR("SCNetworkInterface"), defaultNetworkInterfacePath); 8340 } 8341 8342 if_list = SCPreferencesGetValue(ni_prefs, INTERFACES); 8343 if (isA_CFArray(if_list)) { 8344 CFIndex i; 8345 CFIndex n = CFArrayGetCount(if_list); 8346 8347 interfaceList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 8348 for (i = 0; i < n; i++) { 8349 CFDictionaryRef dict; 8350 8351 dict = CFArrayGetValueAtIndex(if_list, i); 8352 if (isA_CFDictionary(dict) != NULL) { 8353 interfaceNamer = __SCNetworkInterfaceCreateWithStorageEntity(NULL, dict); 8354 8355 if (interfaceNamer != NULL) { 8356 CFArrayAppendValue(interfaceList, interfaceNamer); 8357 CFRelease(interfaceNamer); 8358 } 8359 } 8360 } 8361 } 8362 8363 if (defaultNetworkInterfacePath != NULL) { 8364 CFRelease(defaultNetworkInterfacePath); 8365 // prefs were created in the function, and hence need to be released 8366 CFRelease(ni_prefs); 8367 } 8368 return interfaceList; 8369} 8370 8371 8372__private_extern__ 8373Boolean 8374__SCNetworkInterfaceSaveStoredWithPreferences(SCPreferencesRef prefs, CFArrayRef interfacesToSave) 8375{ 8376 CFStringRef defaultNetworkInterfacePath = NULL; 8377 Boolean success = FALSE; 8378 8379 if (prefs == NULL) { // TODO: Get the default preferences on the system 8380 defaultNetworkInterfacePath = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), PREFS_DEFAULT_DIR, NETWORK_INTERFACES_PREFS); 8381 assert(defaultNetworkInterfacePath != NULL); 8382 prefs = SCPreferencesCreate(NULL, CFSTR("SCNetworkInterface"), defaultNetworkInterfacePath); 8383 } 8384 8385 if (isA_CFArray(interfacesToSave) == NULL) { 8386 SC_log(LOG_INFO, "No interfaces to save"); 8387 goto done; 8388 } 8389 SCPreferencesSetValue(prefs, INTERFACES, interfacesToSave); 8390 success = TRUE; 8391done: 8392 if (defaultNetworkInterfacePath != NULL) { 8393 CFRelease(defaultNetworkInterfacePath); 8394 // prefs were created in the function, and hence need to be released 8395 CFRelease(prefs); 8396 } 8397 8398 return success; 8399} 8400 8401__private_extern__ 8402SCNetworkInterfaceRef 8403__SCNetworkInterfaceCreateWithNIPreferencesUsingBSDName(CFAllocatorRef allocator, SCPreferencesRef ni_prefs, CFStringRef bsdName) 8404{ 8405 CFArrayRef if_list; 8406 SCNetworkInterfaceRef interface = NULL; 8407 CFStringRef defaultNetworkInterfacePath; 8408 8409 /* initialize runtime */ 8410 pthread_once(&initialized, __SCNetworkInterfaceInitialize); 8411 8412 if (ni_prefs == NULL) { 8413 defaultNetworkInterfacePath = CFStringCreateWithFormat(allocator, NULL, CFSTR("%@/%@"), PREFS_DEFAULT_DIR, NETWORK_INTERFACES_PREFS); 8414 ni_prefs = SCPreferencesCreate(allocator, CFSTR("SCNetworkInterface"), defaultNetworkInterfacePath); 8415 CFRelease(defaultNetworkInterfacePath); 8416 } 8417 else { 8418 CFRetain(ni_prefs); 8419 } 8420 8421 if_list = SCPreferencesGetValue(ni_prefs, INTERFACES); 8422 8423 if (isA_CFArray(if_list) != NULL) { 8424 CFIndex idx; 8425 CFIndex count = CFArrayGetCount(if_list); 8426 8427 for (idx = 0; idx < count; idx++) { 8428 CFDictionaryRef dict; 8429 CFStringRef tmp_bsdName; 8430 8431 dict = CFArrayGetValueAtIndex(if_list, idx); 8432 if (isA_CFDictionary(dict) == NULL) { 8433 continue; 8434 } 8435 8436 tmp_bsdName = CFDictionaryGetValue(dict, CFSTR(kSCNetworkInterfaceBSDName)); 8437 if (tmp_bsdName == NULL) { 8438 continue; 8439 } 8440 if (CFEqual(bsdName, tmp_bsdName)) { 8441 interface = __SCNetworkInterfaceCreateWithStorageEntity(allocator, dict); 8442 break; 8443 } 8444 } 8445 } 8446 8447 CFRelease(ni_prefs); 8448 return interface; 8449} 8450 8451__private_extern__ 8452CFDictionaryRef 8453__SCNetworkInterfaceCreateMappingUsingBSDName(CFArrayRef interfaces) 8454{ 8455 CFMutableDictionaryRef mappingBSDToInterface = NULL; 8456 CFStringRef bsdName = NULL; 8457 SCNetworkInterfaceRef interface = NULL; 8458 CFIndex count; 8459 8460 count = CFArrayGetCount(interfaces); 8461 if (count == 0) { 8462 SC_log(LOG_INFO, "No interfaces"); 8463 return NULL; 8464 } 8465 mappingBSDToInterface = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 8466 8467 for (CFIndex idx = 0; idx < count; idx++) { 8468 interface = (SCNetworkInterfaceRef) CFArrayGetValueAtIndex(interfaces, idx); 8469 8470 bsdName = SCNetworkInterfaceGetBSDName(interface); 8471 if (isA_CFString(bsdName) == NULL) { 8472 SC_log(LOG_INFO, "No BSD name"); 8473 continue; 8474 } 8475 CFDictionaryAddValue(mappingBSDToInterface, bsdName, interface); 8476 } 8477 if (CFDictionaryGetCount(mappingBSDToInterface) == 0) { 8478 CFRelease(mappingBSDToInterface); 8479 mappingBSDToInterface = NULL; 8480 SC_log(LOG_INFO, "No mappings"); 8481 } 8482 8483 return mappingBSDToInterface; 8484} 8485 8486__private_extern__ Boolean 8487__SCNetworkInterfaceEntityIsPPTP(CFDictionaryRef entity) 8488{ 8489 CFStringRef intfSubtype; 8490 8491 if (entity == NULL) { 8492 return FALSE; 8493 } 8494 8495 intfSubtype = CFDictionaryGetValue(entity, kSCPropNetInterfaceSubType); 8496#pragma GCC diagnostic push 8497#pragma GCC diagnostic ignored "-Wdeprecated" 8498 if (intfSubtype != NULL && CFEqual(intfSubtype, kSCValNetInterfaceSubTypePPTP)) { 8499 return TRUE; 8500 } 8501#pragma GCC diagnostic pop 8502 8503 return FALSE; 8504}