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