2 * Copyright (c) 2004-2012 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 * Modification History
27 * May 13, 2004 Allan Nathanson <ajn@apple.com>
29 * which includes code originally authored by
30 * Robert Ulrich <rulrich@apple.com>
31 * Elizabeth Douglas <elizabeth@apple.com>
32 * Quinn <eskimo1@apple.com>
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"
48 #include <EAP8021X/EAPClientProperties.h>
49 #else // !TARGET_OS_IPHONE
50 #ifndef kEAPClientPropUserName
51 #define kEAPClientPropUserName CFSTR("UserName")
53 #ifndef kEAPClientPropUserPasswordKeychainItemID
54 #define kEAPClientPropUserPasswordKeychainItemID CFSTR("UserPasswordKeychainItemID")
56 #endif // !TARGET_OS_IPHONE
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 #include <IOKit/usb/USB.h>
68 #include "dy_framework.h"
70 #ifndef kIODeviceSupportsHoldKey
71 #define kIODeviceSupportsHoldKey "V92Modem"
74 #ifndef kPCIThunderboltString
75 #define kPCIThunderboltString "PCI-Thunderbolt"
78 #ifndef kUSBProductString
79 #define kUSBProductString "USB Product Name"
82 #ifndef kIOUserEthernetInterfaceRoleKey
83 #define kIOUserEthernetInterfaceRoleKey "InterfaceRole"
87 #include <mach/mach.h>
89 #include <net/if_types.h>
90 #include <net/route.h>
91 #include <sys/param.h>
92 #include <sys/types.h>
93 #include <sys/socket.h>
95 #include <sys/sysctl.h>
97 #include <NSSystemDirectories.h>
100 static CFStringRef
copy_interface_string (CFBundleRef bundle
, CFStringRef key
, Boolean localized
);
101 static CFStringRef
__SCNetworkInterfaceCopyDescription (CFTypeRef cf
);
102 static void __SCNetworkInterfaceDeallocate (CFTypeRef cf
);
103 static Boolean
__SCNetworkInterfaceEqual (CFTypeRef cf1
, CFTypeRef cf2
);
104 static CFHashCode
__SCNetworkInterfaceHash (CFTypeRef cf
);
123 kSortBluetoothPAN_GN
,
124 kSortBluetoothPAN_NAP
,
133 const CFStringRef kSCNetworkInterfaceType6to4
= CFSTR("6to4");
134 const CFStringRef kSCNetworkInterfaceTypeBluetooth
= CFSTR("Bluetooth");
135 const CFStringRef kSCNetworkInterfaceTypeBond
= CFSTR("Bond");
136 const CFStringRef kSCNetworkInterfaceTypeBridge
= CFSTR("Bridge");
137 const CFStringRef kSCNetworkInterfaceTypeEthernet
= CFSTR("Ethernet");
138 const CFStringRef kSCNetworkInterfaceTypeFireWire
= CFSTR("FireWire");
139 const CFStringRef kSCNetworkInterfaceTypeIEEE80211
= CFSTR("IEEE80211"); // IEEE 802.11, AirPort
140 const CFStringRef kSCNetworkInterfaceTypeIPSec
= CFSTR("IPSec");
141 const CFStringRef kSCNetworkInterfaceTypeIrDA
= CFSTR("IrDA");
142 const CFStringRef kSCNetworkInterfaceTypeL2TP
= CFSTR("L2TP");
143 const CFStringRef kSCNetworkInterfaceTypeLoopback
= CFSTR("Loopback");
144 const CFStringRef kSCNetworkInterfaceTypeModem
= CFSTR("Modem");
145 const CFStringRef kSCNetworkInterfaceTypePPP
= CFSTR("PPP");
146 const CFStringRef kSCNetworkInterfaceTypePPTP
= CFSTR("PPTP");
147 const CFStringRef kSCNetworkInterfaceTypeSerial
= CFSTR("Serial");
148 const CFStringRef kSCNetworkInterfaceTypeVLAN
= CFSTR("VLAN");
149 const CFStringRef kSCNetworkInterfaceTypeVPN
= CFSTR("VPN");
150 const CFStringRef kSCNetworkInterfaceTypeWWAN
= CFSTR("WWAN");
152 const CFStringRef kSCNetworkInterfaceTypeIPv4
= CFSTR("IPv4");
154 static SCNetworkInterfacePrivate __kSCNetworkInterfaceIPv4
= {
155 INIT_CFRUNTIME_BASE(), // cfBase
156 NULL
, // interface type
158 NULL
, // localized name
159 NULL
, // localization key
160 NULL
, // localization arg1
161 NULL
, // localization arg2
162 NULL
, // [layered] interface
167 NULL
, // entity_device
168 NULL
, // entity_device_unique
170 NULL
, // entity_subtype
171 NULL
, // supported_interface_types
172 NULL
, // supported_protocol_types
174 NULL
, // addressString
176 NULL
, // configurationAction
185 { NULL
, 0, 0 }, // usb { name, vid, pid }
186 kSortUnknown
, // sort_order
187 FALSE
, // supportsBond
188 { NULL
, NULL
, NULL
}, // bond { interfaces, options, mode }
189 FALSE
, // supportsBridge
190 { NULL
, NULL
}, // bridge { interfaces, options }
191 FALSE
, // supportsVLAN
192 { NULL
, NULL
, NULL
} // vlan { interface, tag, options }
195 const SCNetworkInterfaceRef kSCNetworkInterfaceIPv4
= (SCNetworkInterfaceRef
)&__kSCNetworkInterfaceIPv4
;
197 static SCNetworkInterfacePrivate __kSCNetworkInterfaceLoopback
= {
198 INIT_CFRUNTIME_BASE(), // cfBase
199 NULL
, // interface type
201 NULL
, // localized name
202 NULL
, // localization key
203 NULL
, // localization arg1
204 NULL
, // localization arg2
205 NULL
, // [layered] interface
210 NULL
, // entity_device
211 NULL
, // entity_device_unique
213 NULL
, // entity_subtype
214 NULL
, // supported_interface_types
215 NULL
, // supported_protocol_types
217 NULL
, // addressString
219 NULL
, // configurationAction
228 { NULL
, 0, 0 }, // usb { name, vid, pid }
229 kSortUnknown
, // sort_order
230 FALSE
, // supportsBond
231 { NULL
, NULL
, NULL
}, // bond { interfaces, options, mode }
232 FALSE
, // supportsBridge
233 { NULL
, NULL
}, // bridge { interfaces, options }
234 FALSE
, // supportsVLAN
235 { NULL
, NULL
, NULL
} // vlan { interface, tag, options }
238 const SCNetworkInterfaceRef kSCNetworkInterfaceLoopback
= (SCNetworkInterfaceRef
)&__kSCNetworkInterfaceLoopback
;
240 static CFMutableSetRef vendor_interface_types
= NULL
;
243 #pragma mark SCNetworkInterface configuration details
252 #define doOverIP do6to4|doL2TP|doPPTP|doIPSec
257 #define doProxies 1<<4
258 #if !TARGET_OS_IPHONE
260 #else // !TARGET_OS_IPHONE
262 #endif // !TARGET_OS_IPHONE
264 static const struct {
265 const CFStringRef
*interface_type
;
266 const CFStringRef
*entity_hardware
;
267 Boolean per_interface_config
;
268 uint32_t supported_interfaces
;
269 const CFStringRef
*ppp_subtype
;
270 uint32_t supported_protocols
;
271 } configurations
[] = {
272 // interface type entity_hardware if config? interface types PPP sub-type interface protocols
273 // ===================================== ================= ========== =============== ======================================= =========================================
274 { &kSCNetworkInterfaceType6to4
, &kSCEntNet6to4
, FALSE
, doNone
, NULL
, doIPv6
},
275 { &kSCNetworkInterfaceTypeBluetooth
, &kSCEntNetModem
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypePPPSerial
, doNone
},
276 { &kSCNetworkInterfaceTypeBond
, &kSCEntNetEthernet
, TRUE
, doNone
, NULL
, doDNS
|doIPv4
|doIPv6
|doProxies
|doSMB
},
277 { &kSCNetworkInterfaceTypeBridge
, &kSCEntNetEthernet
, TRUE
, doNone
, NULL
, doDNS
|doIPv4
|doIPv6
|doProxies
|doSMB
},
278 { &kSCNetworkInterfaceTypeEthernet
, &kSCEntNetEthernet
, TRUE
, doPPP
, &kSCValNetInterfaceSubTypePPPoE
, doDNS
|doIPv4
|doIPv6
|doProxies
|doSMB
},
279 { &kSCNetworkInterfaceTypeFireWire
, &kSCEntNetFireWire
, TRUE
, doNone
, NULL
, doDNS
|doIPv4
|doIPv6
|doProxies
|doSMB
},
280 { &kSCNetworkInterfaceTypeIEEE80211
, &kSCEntNetAirPort
, TRUE
, doPPP
, &kSCValNetInterfaceSubTypePPPoE
, doDNS
|doIPv4
|doIPv6
|doProxies
|doSMB
},
281 { &kSCNetworkInterfaceTypeIPSec
, &kSCEntNetIPSec
, FALSE
, doNone
, NULL
, doDNS
|doIPv4
|doIPv6
|doProxies
|doSMB
},
282 { &kSCNetworkInterfaceTypeIrDA
, &kSCEntNetModem
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypePPPSerial
, doNone
},
283 { &kSCNetworkInterfaceTypeL2TP
, NULL
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypeL2TP
, doNone
},
284 { &kSCNetworkInterfaceTypeModem
, &kSCEntNetModem
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypePPPSerial
, doNone
},
285 { &kSCNetworkInterfaceTypePPP
, &kSCEntNetPPP
, FALSE
, doNone
, NULL
, doDNS
|doIPv4
|doIPv6
|doProxies
|doSMB
},
286 { &kSCNetworkInterfaceTypePPTP
, NULL
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypePPTP
, doNone
},
287 { &kSCNetworkInterfaceTypeSerial
, &kSCEntNetModem
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypePPPSerial
, doNone
},
288 { &kSCNetworkInterfaceTypeVLAN
, &kSCEntNetEthernet
, TRUE
, doNone
, NULL
, doDNS
|doIPv4
|doIPv6
|doProxies
|doSMB
},
289 { &kSCNetworkInterfaceTypeVPN
, &kSCEntNetVPN
, FALSE
, doNone
, NULL
, doDNS
|doIPv4
|doIPv6
|doProxies
|doSMB
},
290 { &kSCNetworkInterfaceTypeWWAN
, &kSCEntNetModem
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypePPPSerial
, doNone
},
291 // ===================================== ================= ========== =============== ======================================= =========================================
292 { &kSCNetworkInterfaceTypeLoopback
, NULL
, TRUE
, doNone
, NULL
, doIPv4
|doIPv6
},
293 // ===================================== ================= ========== =============== ======================================= =========================================
294 { &kSCNetworkInterfaceTypeIPv4
, NULL
, FALSE
, doOverIP
, NULL
, doNone
}
298 #define NETWORKINTERFACE_LOCALIZATIONS CFSTR("NetworkInterface")
299 static CFBundleRef bundle
= NULL
;
302 static CFTypeID __kSCNetworkInterfaceTypeID
= _kCFRuntimeNotATypeID
;
305 static const CFRuntimeClass __SCNetworkInterfaceClass
= {
307 "SCNetworkInterface", // className
310 __SCNetworkInterfaceDeallocate
, // dealloc
311 __SCNetworkInterfaceEqual
, // equal
312 __SCNetworkInterfaceHash
, // hash
313 NULL
, // copyFormattingDesc
314 __SCNetworkInterfaceCopyDescription
// copyDebugDesc
318 static pthread_once_t initialized
= PTHREAD_ONCE_INIT
;
319 static pthread_once_t iokit_quiet
= PTHREAD_ONCE_INIT
;
322 static mach_port_t masterPort
= MACH_PORT_NULL
;
326 __SCNetworkInterfaceCopyDescription(CFTypeRef cf
)
328 CFAllocatorRef allocator
= CFGetAllocator(cf
);
329 CFMutableStringRef result
;
330 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)cf
;
332 result
= CFStringCreateMutable(allocator
, 0);
333 CFStringAppendFormat(result
, NULL
, CFSTR("<SCNetworkInterface %p [%p]> {"), cf
, allocator
);
334 CFStringAppendFormat(result
, NULL
, CFSTR("type = %@"), interfacePrivate
->interface_type
);
335 CFStringAppendFormat(result
, NULL
, CFSTR(", entity_device = %@"), interfacePrivate
->entity_device
);
336 if (interfacePrivate
->entity_device_unique
!= NULL
) {
337 CFStringAppendFormat(result
, NULL
, CFSTR("+%@"), interfacePrivate
->entity_device_unique
);
339 CFStringAppendFormat(result
, NULL
, CFSTR(", entity_type = %@"), interfacePrivate
->entity_type
);
340 if (interfacePrivate
->entity_subtype
!= NULL
) {
341 CFStringAppendFormat(result
, NULL
, CFSTR(" / %@"), interfacePrivate
->entity_subtype
);
343 if (interfacePrivate
->name
!= NULL
) {
344 CFStringAppendFormat(result
, NULL
, CFSTR(", name = %@"), interfacePrivate
->name
);
346 if (interfacePrivate
->localized_name
!= NULL
) {
347 CFStringAppendFormat(result
, NULL
, CFSTR(", name(l) = %@"), interfacePrivate
->localized_name
);
349 if (interfacePrivate
->localized_key
!= NULL
) {
350 CFStringAppendFormat(result
, NULL
, CFSTR(", name(k) = \"%@\""), interfacePrivate
->localized_key
);
351 if (interfacePrivate
->localized_arg1
!= NULL
) {
352 CFStringAppendFormat(result
, NULL
, CFSTR("+\"%@\""), interfacePrivate
->localized_arg1
);
354 if (interfacePrivate
->localized_arg2
!= NULL
) {
355 CFStringAppendFormat(result
, NULL
, CFSTR("+\"%@\""), interfacePrivate
->localized_arg2
);
359 if (interfacePrivate
->address
!= NULL
) {
364 CFStringAppendFormat(result
, NULL
, CFSTR(", address = 0x"));
366 data
= CFDataGetBytePtr(interfacePrivate
->address
);
367 dataLen
= CFDataGetLength(interfacePrivate
->address
);
368 for (i
= 0; i
< dataLen
; i
++) {
369 CFStringAppendFormat(result
, NULL
, CFSTR("%02x"), data
[i
]);
372 CFStringAppendFormat(result
, NULL
, CFSTR(", builtin = %s"), interfacePrivate
->builtin
? "TRUE" : "FALSE");
373 if (interfacePrivate
->hidden
) {
374 CFStringAppendFormat(result
, NULL
, CFSTR(", hidden = TRUE"));
376 if (interfacePrivate
->modemIsV92
) {
377 CFStringAppendFormat(result
, NULL
, CFSTR(", v.92"));
379 if (interfacePrivate
->location
!= NULL
) {
380 CFStringAppendFormat(result
, NULL
, CFSTR(", location = %@"), interfacePrivate
->location
);
382 if (interfacePrivate
->path
!= NULL
) {
383 CFStringAppendFormat(result
, NULL
, CFSTR(", path = %@"), interfacePrivate
->path
);
385 if (interfacePrivate
->entryID
!= 0) {
386 CFStringAppendFormat(result
, NULL
, CFSTR(", entryID = 0x%llx"), interfacePrivate
->entryID
);
388 if (interfacePrivate
->type
!= NULL
) {
389 CFStringAppendFormat(result
, NULL
, CFSTR(", type = %@"), interfacePrivate
->type
);
391 if (interfacePrivate
->unit
!= NULL
) {
392 CFStringAppendFormat(result
, NULL
, CFSTR(", unit = %@"), interfacePrivate
->unit
);
394 if ((interfacePrivate
->usb
.vid
!= NULL
) || (interfacePrivate
->usb
.pid
!= NULL
)) {
398 if (!isA_CFNumber(interfacePrivate
->usb
.pid
) ||
399 !CFNumberGetValue(interfacePrivate
->usb
.vid
, kCFNumberIntType
, &pid
)) {
402 if (!isA_CFNumber(interfacePrivate
->usb
.vid
) ||
403 !CFNumberGetValue(interfacePrivate
->usb
.vid
, kCFNumberIntType
, &vid
)) {
407 if (interfacePrivate
->usb
.name
!= NULL
) {
408 CFStringAppendFormat(result
, NULL
, CFSTR(", USB name = %@"),
409 interfacePrivate
->usb
.name
);
412 CFStringAppendFormat(result
, NULL
, CFSTR(", USB vid/pid = 0x%0x/0x%0x"),
413 interfacePrivate
->usb
.vid
,
414 interfacePrivate
->usb
.pid
);
416 if (interfacePrivate
->configurationAction
!= NULL
) {
417 CFStringAppendFormat(result
, NULL
, CFSTR(", action = %@"), interfacePrivate
->configurationAction
);
419 if (interfacePrivate
->overrides
!= NULL
) {
420 CFStringAppendFormat(result
, NULL
, CFSTR(", overrides = %p"), interfacePrivate
->overrides
);
422 CFStringAppendFormat(result
, NULL
, CFSTR(", order = %d"), interfacePrivate
->sort_order
);
423 if (interfacePrivate
->prefs
!= NULL
) {
424 CFStringAppendFormat(result
, NULL
, CFSTR(", prefs = %p"), interfacePrivate
->prefs
);
426 if (interfacePrivate
->serviceID
!= NULL
) {
427 CFStringAppendFormat(result
, NULL
, CFSTR(", service = %@"), interfacePrivate
->serviceID
);
429 if (interfacePrivate
->interface
!= NULL
) {
430 CFStringAppendFormat(result
, NULL
, CFSTR(", interface = %@"), interfacePrivate
->interface
);
432 if (interfacePrivate
->unsaved
!= NULL
) {
433 CFStringAppendFormat(result
, NULL
, CFSTR(", unsaved = %@"), interfacePrivate
->unsaved
);
436 if (interfacePrivate
->bond
.interfaces
!= NULL
) {
440 n
= CFArrayGetCount(interfacePrivate
->bond
.interfaces
);
441 for (i
= 0; i
< n
; i
++) {
442 SCNetworkInterfaceRef member
;
444 member
= CFArrayGetValueAtIndex(interfacePrivate
->bond
.interfaces
, i
);
445 CFStringAppendFormat(result
, NULL
,
447 (i
== 0) ? ", interfaces = " : ", ",
448 SCNetworkInterfaceGetBSDName(member
));
451 if (interfacePrivate
->bond
.mode
!= NULL
) {
452 CFStringAppendFormat(result
, NULL
, CFSTR(", mode = %@"), interfacePrivate
->bond
.mode
);
454 if (interfacePrivate
->bond
.options
!= NULL
) {
455 CFStringAppendFormat(result
, NULL
, CFSTR(", options = %@"), interfacePrivate
->bond
.options
);
458 if (interfacePrivate
->bridge
.interfaces
!= NULL
) {
462 n
= CFArrayGetCount(interfacePrivate
->bridge
.interfaces
);
463 for (i
= 0; i
< n
; i
++) {
464 SCNetworkInterfaceRef member
;
466 member
= CFArrayGetValueAtIndex(interfacePrivate
->bridge
.interfaces
, i
);
467 CFStringAppendFormat(result
, NULL
,
469 (i
== 0) ? ", interfaces = " : ", ",
470 SCNetworkInterfaceGetBSDName(member
));
473 if (interfacePrivate
->bridge
.options
!= NULL
) {
474 CFStringAppendFormat(result
, NULL
, CFSTR(", options = %@"), interfacePrivate
->bridge
.options
);
477 if (interfacePrivate
->vlan
.interface
!= NULL
) {
478 CFStringAppendFormat(result
, NULL
,
479 CFSTR(", interface = %@"),
480 SCNetworkInterfaceGetBSDName(interfacePrivate
->vlan
.interface
));
482 if (interfacePrivate
->vlan
.tag
!= NULL
) {
483 CFStringAppendFormat(result
, NULL
, CFSTR(", tag = %@"), interfacePrivate
->vlan
.tag
);
485 if (interfacePrivate
->vlan
.options
!= NULL
) {
486 CFStringAppendFormat(result
, NULL
, CFSTR(", options = %@"), interfacePrivate
->vlan
.options
);
489 CFStringAppendFormat(result
, NULL
, CFSTR("}"));
496 __SCNetworkInterfaceDeallocate(CFTypeRef cf
)
498 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)cf
;
500 /* release resources */
502 if (interfacePrivate
->name
!= NULL
)
503 CFRelease(interfacePrivate
->name
);
505 if (interfacePrivate
->localized_name
!= NULL
)
506 CFRelease(interfacePrivate
->localized_name
);
508 if (interfacePrivate
->localized_arg1
!= NULL
)
509 CFRelease(interfacePrivate
->localized_arg1
);
511 if (interfacePrivate
->localized_arg2
!= NULL
)
512 CFRelease(interfacePrivate
->localized_arg2
);
514 if (interfacePrivate
->interface
!= NULL
)
515 CFRelease(interfacePrivate
->interface
);
517 if (interfacePrivate
->prefs
!= NULL
)
518 CFRelease(interfacePrivate
->prefs
);
520 if (interfacePrivate
->store
!= NULL
)
521 CFRelease(interfacePrivate
->store
);
523 if (interfacePrivate
->serviceID
!= NULL
)
524 CFRelease(interfacePrivate
->serviceID
);
526 if (interfacePrivate
->unsaved
!= NULL
)
527 CFRelease(interfacePrivate
->unsaved
);
529 if (interfacePrivate
->entity_device
!= NULL
)
530 CFRelease(interfacePrivate
->entity_device
);
532 if (interfacePrivate
->entity_device_unique
!= NULL
)
533 CFRelease(interfacePrivate
->entity_device_unique
);
535 if (interfacePrivate
->supported_interface_types
!= NULL
)
536 CFRelease(interfacePrivate
->supported_interface_types
);
538 if (interfacePrivate
->supported_protocol_types
!= NULL
)
539 CFRelease(interfacePrivate
->supported_protocol_types
);
541 if (interfacePrivate
->address
!= NULL
)
542 CFRelease(interfacePrivate
->address
);
544 if (interfacePrivate
->addressString
!= NULL
)
545 CFRelease(interfacePrivate
->addressString
);
547 if (interfacePrivate
->configurationAction
!= NULL
)
548 CFRelease(interfacePrivate
->configurationAction
);
550 if (interfacePrivate
->location
!= NULL
)
551 CFRelease(interfacePrivate
->location
);
553 if (interfacePrivate
->path
!= NULL
)
554 CFRelease(interfacePrivate
->path
);
556 if (interfacePrivate
->overrides
!= NULL
)
557 CFRelease(interfacePrivate
->overrides
);
559 if (interfacePrivate
->type
!= NULL
)
560 CFRelease(interfacePrivate
->type
);
562 if (interfacePrivate
->unit
!= NULL
)
563 CFRelease(interfacePrivate
->unit
);
565 if (interfacePrivate
->usb
.name
!= NULL
)
566 CFRelease(interfacePrivate
->usb
.name
);
568 if (interfacePrivate
->usb
.pid
!= NULL
)
569 CFRelease(interfacePrivate
->usb
.pid
);
571 if (interfacePrivate
->usb
.vid
!= NULL
)
572 CFRelease(interfacePrivate
->usb
.vid
);
574 if (interfacePrivate
->bond
.interfaces
!= NULL
)
575 CFRelease(interfacePrivate
->bond
.interfaces
);
577 if (interfacePrivate
->bond
.mode
!= NULL
)
578 CFRelease(interfacePrivate
->bond
.mode
);
580 if (interfacePrivate
->bond
.options
!= NULL
)
581 CFRelease(interfacePrivate
->bond
.options
);
583 if (interfacePrivate
->bridge
.interfaces
!= NULL
)
584 CFRelease(interfacePrivate
->bridge
.interfaces
);
586 if (interfacePrivate
->bridge
.options
!= NULL
)
587 CFRelease(interfacePrivate
->bridge
.options
);
589 if (interfacePrivate
->vlan
.interface
!= NULL
)
590 CFRelease(interfacePrivate
->vlan
.interface
);
592 if (interfacePrivate
->vlan
.tag
!= NULL
)
593 CFRelease(interfacePrivate
->vlan
.tag
);
595 if (interfacePrivate
->vlan
.options
!= NULL
)
596 CFRelease(interfacePrivate
->vlan
.options
);
603 __SCNetworkInterfaceEqual(CFTypeRef cf1
, CFTypeRef cf2
)
605 SCNetworkInterfacePrivateRef if1
= (SCNetworkInterfacePrivateRef
)cf1
;
606 SCNetworkInterfacePrivateRef if2
= (SCNetworkInterfacePrivateRef
)cf2
;
611 if (!CFEqual(if1
->interface_type
, if2
->interface_type
)) {
612 return FALSE
; // if not the same interface type
615 if (!_SC_CFEqual(if1
->entity_device
, if2
->entity_device
)) {
616 return FALSE
; // if not the same device
619 if ((if1
->entity_device_unique
!= NULL
) && (if2
->entity_device_unique
!= NULL
)) {
620 if (!_SC_CFEqual(if1
->entity_device_unique
, if2
->entity_device_unique
)) {
621 return FALSE
; // if not the same device unique identifier
623 } else if ((if1
->entity_device_unique
!= NULL
) || (if2
->entity_device_unique
!= NULL
)) {
627 name1
= __SCNetworkInterfaceGetNonLocalizedDisplayName((SCNetworkInterfaceRef
)if1
);
628 name2
= __SCNetworkInterfaceGetNonLocalizedDisplayName((SCNetworkInterfaceRef
)if2
);
629 if ((name1
!= NULL
) && (name2
!= NULL
) && !_SC_CFEqual(name1
, name2
)) {
630 return FALSE
; // if same device but not the same display name
634 if (CFEqual(if1
->interface_type
, kSCNetworkInterfaceTypeBond
)) {
635 if (!_SC_CFEqual(if1
->bond
.interfaces
, if2
->bond
.interfaces
)) {
636 return FALSE
; // if not the same interfaces
638 if (!_SC_CFEqual(if1
->bond
.mode
, if2
->bond
.mode
)) {
639 return FALSE
; // if not the same mode
643 if (CFEqual(if1
->interface_type
, kSCNetworkInterfaceTypeBridge
)) {
644 if (!_SC_CFEqual(if1
->bridge
.interfaces
, if2
->bridge
.interfaces
)) {
645 return FALSE
; // if not the same interfaces
649 if (CFEqual(if1
->interface_type
, kSCNetworkInterfaceTypeVLAN
)) {
650 if (!_SC_CFEqual(if1
->vlan
.interface
, if2
->vlan
.interface
)) {
651 return FALSE
; // if not the same physical interface
653 if (!_SC_CFEqual(if1
->vlan
.tag
, if2
->vlan
.tag
)) {
654 return FALSE
; // if not the same tag
658 if (!_SC_CFEqual(if1
->interface
, if2
->interface
)) {
659 return FALSE
; // if not the same layering
667 __SCNetworkInterfaceHash(CFTypeRef cf
)
670 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)cf
;
672 if (interfacePrivate
->entity_device
!= NULL
) {
673 if (interfacePrivate
->entity_device_unique
== NULL
) {
674 hash
= CFHash(interfacePrivate
->entity_device
);
678 str
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@+%@"),
679 interfacePrivate
->entity_device
,
680 interfacePrivate
->entity_device_unique
);
691 __SCNetworkInterfaceInitialize(void)
696 __kSCNetworkInterfaceTypeID
= _CFRuntimeRegisterClass(&__SCNetworkInterfaceClass
);
698 // initialize __kSCNetworkInterfaceIPv4
699 _CFRuntimeInitStaticInstance(&__kSCNetworkInterfaceIPv4
, __kSCNetworkInterfaceTypeID
);
700 __kSCNetworkInterfaceIPv4
.interface_type
= kSCNetworkInterfaceTypeIPv4
;
701 __kSCNetworkInterfaceIPv4
.localized_key
= CFSTR("ipv4");
703 // initialize __kSCNetworkInterfaceLoopback
704 _CFRuntimeInitStaticInstance(&__kSCNetworkInterfaceLoopback
, __kSCNetworkInterfaceTypeID
);
705 __kSCNetworkInterfaceLoopback
.interface_type
= kSCNetworkInterfaceTypeLoopback
;
706 __kSCNetworkInterfaceLoopback
.localized_key
= CFSTR("loopback");
707 __kSCNetworkInterfaceLoopback
.entity_device
= CFRetain(CFSTR("lo0"));
708 __kSCNetworkInterfaceLoopback
.entity_type
= kSCValNetInterfaceTypeLoopback
;
710 // get CFBundleRef for SystemConfiguration.framework
711 bundle
= _SC_CFBundleGet();
713 // get mach port used to communication with IOKit
714 kr
= IOMasterPort(MACH_PORT_NULL
, &masterPort
);
715 if (kr
!= KERN_SUCCESS
) {
716 SCLog(TRUE
, LOG_DEBUG
,
717 CFSTR("__SCNetworkInterfaceInitialize(), could not get IOMasterPort, kr = 0x%x"),
726 SCNetworkInterfacePrivateRef
727 __SCNetworkInterfaceCreatePrivate(CFAllocatorRef allocator
,
728 SCNetworkInterfaceRef interface
,
729 SCPreferencesRef prefs
,
730 CFStringRef serviceID
)
732 SCNetworkInterfacePrivateRef interfacePrivate
;
735 /* initialize runtime */
736 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
738 /* allocate target */
739 size
= sizeof(SCNetworkInterfacePrivate
) - sizeof(CFRuntimeBase
);
740 interfacePrivate
= (SCNetworkInterfacePrivateRef
)_CFRuntimeCreateInstance(allocator
,
741 __kSCNetworkInterfaceTypeID
,
744 if (interfacePrivate
== NULL
) {
748 interfacePrivate
->interface_type
= NULL
;
749 interfacePrivate
->name
= NULL
;
750 interfacePrivate
->localized_name
= NULL
;
751 interfacePrivate
->localized_key
= NULL
;
752 interfacePrivate
->localized_arg1
= NULL
;
753 interfacePrivate
->localized_arg2
= NULL
;
754 interfacePrivate
->interface
= (interface
!= NULL
) ? CFRetain(interface
) : NULL
;
755 interfacePrivate
->prefs
= (prefs
!= NULL
) ? CFRetain(prefs
) : NULL
;
756 interfacePrivate
->store
= NULL
;
757 interfacePrivate
->serviceID
= (serviceID
!= NULL
) ? CFRetain(serviceID
) : NULL
;
758 interfacePrivate
->unsaved
= NULL
;
759 interfacePrivate
->entity_device
= NULL
;
760 interfacePrivate
->entity_device_unique
= NULL
;
761 interfacePrivate
->entity_type
= NULL
;
762 interfacePrivate
->entity_subtype
= NULL
;
763 interfacePrivate
->supported_interface_types
= NULL
;
764 interfacePrivate
->supported_protocol_types
= NULL
;
765 interfacePrivate
->address
= NULL
;
766 interfacePrivate
->addressString
= NULL
;
767 interfacePrivate
->builtin
= FALSE
;
768 interfacePrivate
->configurationAction
= NULL
;
769 interfacePrivate
->hidden
= FALSE
;
770 interfacePrivate
->location
= NULL
;
771 interfacePrivate
->path
= NULL
;
772 interfacePrivate
->entryID
= 0;
773 interfacePrivate
->overrides
= NULL
;
774 interfacePrivate
->modemIsV92
= FALSE
;
775 interfacePrivate
->type
= NULL
;
776 interfacePrivate
->unit
= NULL
;
777 interfacePrivate
->usb
.name
= NULL
;
778 interfacePrivate
->usb
.vid
= NULL
;
779 interfacePrivate
->usb
.pid
= NULL
;
780 interfacePrivate
->sort_order
= kSortUnknown
;
782 interfacePrivate
->supportsBond
= FALSE
;
783 interfacePrivate
->bond
.interfaces
= NULL
;
784 interfacePrivate
->bond
.mode
= NULL
;
785 interfacePrivate
->bond
.options
= NULL
;
787 interfacePrivate
->supportsBridge
= FALSE
;
788 interfacePrivate
->bridge
.interfaces
= NULL
;
789 interfacePrivate
->bridge
.options
= NULL
;
791 interfacePrivate
->supportsVLAN
= FALSE
;
792 interfacePrivate
->vlan
.interface
= NULL
;
793 interfacePrivate
->vlan
.tag
= NULL
;
794 interfacePrivate
->vlan
.options
= NULL
;
796 return interfacePrivate
;
802 __SCNetworkInterfaceSupportsVLAN(CFStringRef bsd_if
)
806 struct if_msghdr
* ifm
;
807 char * if_name
= NULL
;
808 unsigned int if_index
;
810 Boolean vlanOK
= FALSE
;
812 // get the interface index
813 if_name
= _SC_cfstring_to_cstring(bsd_if
, NULL
, 0, kCFStringEncodingASCII
);
814 if (if_name
== NULL
) {
815 return FALSE
; // if conversion error
817 if_index
= if_nametoindex(if_name
);
819 goto done
; // if unknown interface
822 // get information for the specified interface
827 mib
[4] = NET_RT_IFLIST
;
828 mib
[5] = if_index
; /* ask for exactly one interface */
830 if (sysctl(mib
, 6, NULL
, &buf_len
, NULL
, 0) == -1) {
831 SCLog(TRUE
, LOG_ERR
, CFSTR("sysctl() size failed: %s"), strerror(errno
));
834 buf
= CFAllocatorAllocate(NULL
, buf_len
, 0);
835 if (sysctl(mib
, 6, buf
, &buf_len
, NULL
, 0) == -1) {
836 SCLog(TRUE
, LOG_ERR
, CFSTR("sysctl() failed: %s"), strerror(errno
));
840 // check the link type and hwassist flags
841 // ALIGN: buf is aligned
842 ifm
= (struct if_msghdr
*)(void *)buf
;
843 switch (ifm
->ifm_type
) {
845 #if defined(IF_HWASSIST_VLAN_TAGGING) && defined(IF_HWASSIST_VLAN_MTU)
846 struct if_data
*if_data
= &ifm
->ifm_data
;
848 if (if_data
->ifi_hwassist
& (IF_HWASSIST_VLAN_TAGGING
| IF_HWASSIST_VLAN_MTU
)) {
858 if (if_name
!= NULL
) CFAllocatorDeallocate(NULL
, if_name
);
859 if (buf
!= NULL
) CFAllocatorDeallocate(NULL
, buf
);
866 SCNetworkInterfacePrivateRef
867 _SCBondInterfaceCreatePrivate(CFAllocatorRef allocator
,
870 SCNetworkInterfacePrivateRef interfacePrivate
;
872 interfacePrivate
= __SCNetworkInterfaceCreatePrivate(allocator
, NULL
, NULL
, NULL
);
873 if (interfacePrivate
== NULL
) {
877 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeBond
;
878 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeEthernet
;
879 interfacePrivate
->entity_device
= CFStringCreateCopy(allocator
, bond_if
);
880 interfacePrivate
->builtin
= TRUE
;
881 interfacePrivate
->supportsVLAN
= __SCNetworkInterfaceSupportsVLAN(bond_if
);
882 interfacePrivate
->sort_order
= kSortBond
;
884 interfacePrivate
->localized_key
= CFSTR("bond");
885 interfacePrivate
->localized_arg1
= CFRetain(interfacePrivate
->entity_device
);
887 interfacePrivate
->bond
.interfaces
= CFArrayCreate(NULL
, NULL
, 0, &kCFTypeArrayCallBacks
);
888 // interfacePrivate->bond.mode = NULL;
889 // interfacePrivate->bond.options = NULL;
891 return interfacePrivate
;
896 SCNetworkInterfacePrivateRef
897 _SCBridgeInterfaceCreatePrivate(CFAllocatorRef allocator
,
898 CFStringRef bridge_if
)
900 SCNetworkInterfacePrivateRef interfacePrivate
;
902 interfacePrivate
= __SCNetworkInterfaceCreatePrivate(allocator
, NULL
, NULL
, NULL
);
903 if (interfacePrivate
== NULL
) {
907 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeBridge
;
908 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeEthernet
;
909 interfacePrivate
->entity_device
= CFStringCreateCopy(allocator
, bridge_if
);
910 interfacePrivate
->builtin
= TRUE
;
911 interfacePrivate
->supportsVLAN
= __SCNetworkInterfaceSupportsVLAN(bridge_if
);
912 interfacePrivate
->sort_order
= kSortBridge
;
914 interfacePrivate
->localized_key
= CFSTR("bridge");
915 interfacePrivate
->localized_arg1
= CFRetain(interfacePrivate
->entity_device
);
917 interfacePrivate
->bridge
.interfaces
= CFArrayCreate(NULL
, NULL
, 0, &kCFTypeArrayCallBacks
);
918 // interfacePrivate->bridge.options = NULL;
920 return interfacePrivate
;
925 SCNetworkInterfacePrivateRef
926 _SCVLANInterfaceCreatePrivate(CFAllocatorRef allocator
,
929 SCNetworkInterfacePrivateRef interfacePrivate
;
931 interfacePrivate
= __SCNetworkInterfaceCreatePrivate(allocator
, NULL
, NULL
, NULL
);
932 if (interfacePrivate
== NULL
) {
936 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeVLAN
;
937 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeEthernet
;
938 interfacePrivate
->entity_device
= CFStringCreateCopy(allocator
, vlan_if
);
939 interfacePrivate
->builtin
= TRUE
;
940 interfacePrivate
->sort_order
= kSortVLAN
;
942 interfacePrivate
->localized_key
= CFSTR("vlan");
943 interfacePrivate
->localized_arg1
= CFRetain(interfacePrivate
->entity_device
);
945 // interfacePrivate->vlan.interface = NULL;
946 // interfacePrivate->vlan.tag = NULL;
947 // interfacePrivate->vlan.options = NULL;
949 return interfacePrivate
;
954 #pragma mark Interface ordering
957 static CF_RETURNS_RETAINED CFArrayRef
958 split_path(CFStringRef path
)
960 CFArrayRef components
;
961 CFMutableStringRef nPath
;
963 // turn '@'s into '/'s
964 nPath
= CFStringCreateMutableCopy(NULL
, 0, path
);
965 (void) CFStringFindAndReplace(nPath
,
968 CFRangeMake(0, CFStringGetLength(nPath
)),
971 // split path into components to be compared
972 components
= CFStringCreateArrayBySeparatingStrings(NULL
, nPath
, CFSTR("/"));
980 _SCNetworkInterfaceCompare(const void *val1
, const void *val2
, void *context
)
982 SCNetworkInterfacePrivateRef dev1
= (SCNetworkInterfacePrivateRef
)val1
;
983 SCNetworkInterfacePrivateRef dev2
= (SCNetworkInterfacePrivateRef
)val2
;
984 CFComparisonResult res
= kCFCompareEqualTo
;
986 /* sort by interface type */
987 if (dev1
->sort_order
!= dev2
->sort_order
) {
988 if (dev1
->sort_order
< dev2
->sort_order
) {
989 res
= kCFCompareLessThan
;
991 res
= kCFCompareGreaterThan
;
996 /* built-in interfaces sort first */
997 if (dev1
->builtin
!= dev2
->builtin
) {
999 res
= kCFCompareLessThan
;
1001 res
= kCFCompareGreaterThan
;
1006 /* ... and then, sort built-in interfaces by "location" */
1007 if (dev1
->builtin
) {
1008 if (dev1
->location
!= dev2
->location
) {
1009 if (isA_CFString(dev1
->location
)) {
1010 if (isA_CFString(dev2
->location
)) {
1011 res
= CFStringCompare(dev1
->location
, dev2
->location
, 0);
1013 res
= kCFCompareLessThan
;
1016 res
= kCFCompareGreaterThan
;
1019 if (res
!= kCFCompareEqualTo
) {
1025 /* ... and, then sort by IOPathMatch */
1026 if ((dev1
->path
!= NULL
) && (dev2
->path
!= NULL
)) {
1027 CFArrayRef elements1
;
1028 CFArrayRef elements2
;
1034 elements1
= split_path(dev1
->path
);
1035 n1
= CFArrayGetCount(elements1
);
1037 elements2
= split_path(dev2
->path
);
1038 n2
= CFArrayGetCount(elements2
);
1040 n
= (n1
<= n2
) ? n1
: n2
;
1041 for (i
= 0; i
< n
; i
++) {
1050 e1
= CFArrayGetValueAtIndex(elements1
, i
);
1051 e2
= CFArrayGetValueAtIndex(elements2
, i
);
1053 str
= _SC_cfstring_to_cstring(e1
, NULL
, 0, kCFStringEncodingUTF8
);
1055 q1
= strtoq(str
, &end
, 16);
1056 isNum
= ((*str
!= '\0') && (*end
== '\0') && (errno
== 0));
1057 CFAllocatorDeallocate(NULL
, str
);
1060 // if e1 is a valid numeric string
1061 str
= _SC_cfstring_to_cstring(e2
, NULL
, 0, kCFStringEncodingUTF8
);
1063 q2
= strtoq(str
, &end
, 16);
1064 isNum
= ((*str
!= '\0') && (*end
== '\0') && (errno
== 0));
1065 CFAllocatorDeallocate(NULL
, str
);
1068 // if e2 is also a valid numeric string
1071 res
= kCFCompareEqualTo
;
1073 } else if (q1
< q2
) {
1074 res
= kCFCompareLessThan
;
1076 res
= kCFCompareGreaterThan
;
1082 res
= CFStringCompare(e1
, e2
, 0);
1083 if (res
!= kCFCompareEqualTo
) {
1088 if (res
== kCFCompareEqualTo
) {
1090 res
= kCFCompareLessThan
;
1091 } else if (n1
< n2
) {
1092 res
= kCFCompareGreaterThan
;
1096 CFRelease(elements1
);
1097 CFRelease(elements2
);
1099 if (res
!= kCFCompareEqualTo
) {
1104 /* ... and, then sort by BSD interface name */
1105 if ((dev1
->entity_device
!= NULL
) && (dev2
->entity_device
!= NULL
)) {
1106 res
= CFStringCompare(dev1
->entity_device
, dev2
->entity_device
, 0);
1107 if (res
!= kCFCompareEqualTo
) {
1112 /* ... and lastly, sort by BSD interface unique identifier */
1113 if ((dev1
->entity_device_unique
!= NULL
) && (dev2
->entity_device_unique
!= NULL
)) {
1114 res
= CFStringCompare(dev1
->entity_device_unique
, dev2
->entity_device_unique
, 0);
1115 // if (res != kCFCompareEqualTo) {
1125 sort_interfaces(CFMutableArrayRef all_interfaces
)
1127 int n
= CFArrayGetCount(all_interfaces
);
1133 CFArraySortValues(all_interfaces
, CFRangeMake(0, n
), _SCNetworkInterfaceCompare
, NULL
);
1140 __SCNetworkInterfaceOrder(SCNetworkInterfaceRef interface
)
1142 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
1144 return interfacePrivate
->sort_order
;
1149 #pragma mark Interface details
1153 IOCopyCFStringValue(CFTypeRef ioVal
)
1155 if (isA_CFString(ioVal
)) {
1156 return CFStringCreateCopy(NULL
, ioVal
);
1159 if (isA_CFData(ioVal
)) {
1160 return CFStringCreateWithCString(NULL
,
1161 (const char *)CFDataGetBytePtr(ioVal
),
1162 kCFStringEncodingUTF8
);
1170 IODictionaryCopyCFStringValue(CFDictionaryRef io_dict
, CFStringRef io_key
)
1174 ioVal
= CFDictionaryGetValue(io_dict
, io_key
);
1175 return IOCopyCFStringValue(ioVal
);
1180 IOStringValueHasPrefix(CFTypeRef ioVal
, CFStringRef prefix
)
1182 Boolean match
= FALSE
;
1183 CFIndex prefixLen
= CFStringGetLength(prefix
);
1184 CFStringRef str
= NULL
;
1186 if (!isA_CFString(ioVal
)) {
1187 if (isA_CFData(ioVal
)) {
1188 str
= CFStringCreateWithCStringNoCopy(NULL
,
1189 (const char *)CFDataGetBytePtr(ioVal
),
1190 kCFStringEncodingUTF8
,
1198 if ((ioVal
!= NULL
) &&
1199 (CFStringGetLength(ioVal
) >= prefixLen
) &&
1200 (CFStringCompareWithOptions(ioVal
,
1202 CFRangeMake(0, prefixLen
),
1203 kCFCompareCaseInsensitive
) == kCFCompareEqualTo
)) {
1207 if (str
!= NULL
) CFRelease(str
);
1212 static const struct {
1213 const CFStringRef name
;
1214 const CFStringRef slot
;
1215 } slot_mappings
[] = {
1217 { CFSTR("A1") , CFSTR("1") },
1218 { CFSTR("B1") , CFSTR("2") },
1219 { CFSTR("C1") , CFSTR("3") },
1221 // Blue&White G3, Yikes G4
1222 { CFSTR("J12"), CFSTR("1") },
1223 { CFSTR("J11"), CFSTR("2") },
1224 { CFSTR("J10"), CFSTR("3") },
1225 { CFSTR("J9"), CFSTR("4") },
1228 { CFSTR("A") , CFSTR("1") },
1229 { CFSTR("B") , CFSTR("2") },
1230 { CFSTR("C") , CFSTR("3") },
1231 { CFSTR("D") , CFSTR("4") },
1233 // Digital Audio G4 (and later models)
1234 { CFSTR("1") , CFSTR("1") },
1235 { CFSTR("2") , CFSTR("2") },
1236 { CFSTR("3") , CFSTR("3") },
1237 { CFSTR("4") , CFSTR("4") },
1238 { CFSTR("5") , CFSTR("5") }
1242 static const CFStringRef slot_prefixes
[] = {
1243 CFSTR("thunderbolt slot "),
1249 static CF_RETURNS_RETAINED CFStringRef
1250 pci_slot(io_registry_entry_t interface
, CFTypeRef
*pci_slot_name
)
1253 io_registry_entry_t parent
;
1254 CFMutableStringRef slot
;
1255 CFTypeRef slot_name
;
1258 if (pci_slot_name
!= NULL
) *pci_slot_name
= NULL
;
1260 slot_name
= IORegistryEntryCreateCFProperty(interface
, CFSTR("AAPL,slot-name"), NULL
, 0);
1261 if (slot_name
!= NULL
) {
1264 slot
= CFStringCreateMutable(NULL
, 0);
1265 if (isA_CFString(slot_name
)) {
1266 if (pci_slot_name
!= NULL
) *pci_slot_name
= CFStringCreateCopy(NULL
, slot_name
);
1267 CFStringAppend(slot
, slot_name
);
1268 } else if (isA_CFData(slot_name
)) {
1269 if (pci_slot_name
!= NULL
) *pci_slot_name
= CFDataCreateCopy(NULL
, slot_name
);
1270 CFStringAppendCString(slot
,
1271 (const char *)CFDataGetBytePtr(slot_name
),
1272 kCFStringEncodingUTF8
);
1275 for (i
= 0; i
< sizeof(slot_prefixes
)/sizeof(slot_prefixes
[0]); i
++) {
1278 len
= CFStringGetLength(slot_prefixes
[i
]);
1279 if (CFStringGetLength(slot
) > len
) {
1280 (void) CFStringFindAndReplace(slot
,
1283 CFRangeMake(0, len
),
1284 kCFCompareCaseInsensitive
|kCFCompareAnchored
);
1288 for (i
= 0; i
< sizeof(slot_mappings
)/sizeof(slot_mappings
[0]); i
++) {
1289 if (CFStringCompare(slot
,
1290 slot_mappings
[i
].name
,
1291 kCFCompareCaseInsensitive
) == kCFCompareEqualTo
) {
1293 slot
= (CFMutableStringRef
)CFRetain(slot_mappings
[i
].slot
);
1298 CFRelease(slot_name
);
1301 kr
= IORegistryEntryGetParentEntry(interface
, kIOServicePlane
, &parent
);
1303 case kIOReturnSuccess
: {
1304 CFTypeRef parent_pci_slot_name
= NULL
;
1305 CFStringRef parent_slot
;
1307 parent_slot
= pci_slot(parent
, &parent_pci_slot_name
);
1308 if (parent_slot
!= NULL
) {
1309 if (slot
!= NULL
) CFRelease(slot
);
1310 slot
= (CFMutableStringRef
)parent_slot
;
1312 if (pci_slot_name
!= NULL
) {
1313 if (*pci_slot_name
!= NULL
) CFRelease(*pci_slot_name
);
1314 *pci_slot_name
= parent_pci_slot_name
;
1316 CFRelease(parent_pci_slot_name
);
1320 IOObjectRelease(parent
);
1323 case kIOReturnNoDevice
:
1324 // if we have hit the root node
1327 SCLog(TRUE
, LOG_DEBUG
, CFSTR("pci_slot IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr
);
1335 static CFComparisonResult
1336 compare_bsdNames(const void *val1
, const void *val2
, void *context
)
1338 CFStringRef bsd1
= (CFStringRef
)val1
;
1339 CFStringRef bsd2
= (CFStringRef
)val2
;
1341 return CFStringCompare(bsd1
, bsd2
, 0);
1345 static CF_RETURNS_RETAINED CFStringRef
1346 pci_port(CFTypeRef slot_name
, int ift
, CFStringRef bsdName
)
1349 CFStringRef port_name
= NULL
;
1350 CFMutableArrayRef port_names
;
1353 CFStringRef match_keys
[2];
1354 CFTypeRef match_vals
[2];
1355 CFDictionaryRef match_dict
;
1356 CFDictionaryRef matching
;
1357 io_registry_entry_t slot
;
1358 io_iterator_t slot_iterator
= MACH_PORT_NULL
;
1360 match_keys
[0] = CFSTR("AAPL,slot-name");
1361 match_vals
[0] = slot_name
;
1363 match_dict
= CFDictionaryCreate(NULL
,
1364 (const void **)match_keys
,
1365 (const void **)match_vals
,
1367 &kCFTypeDictionaryKeyCallBacks
,
1368 &kCFTypeDictionaryValueCallBacks
);
1370 match_keys
[0] = CFSTR(kIOProviderClassKey
);
1371 match_vals
[0] = CFSTR("IOPCIDevice");
1373 match_keys
[1] = CFSTR(kIOPropertyMatchKey
);
1374 match_vals
[1] = match_dict
;
1376 // note: the "matching" dictionary will be consumed by the following
1377 matching
= CFDictionaryCreate(NULL
,
1378 (const void **)match_keys
,
1379 (const void **)match_vals
,
1380 sizeof(match_keys
)/sizeof(match_keys
[0]),
1381 &kCFTypeDictionaryKeyCallBacks
,
1382 &kCFTypeDictionaryValueCallBacks
);
1383 CFRelease(match_dict
);
1385 kr
= IOServiceGetMatchingServices(masterPort
, matching
, &slot_iterator
);
1386 if (kr
!= kIOReturnSuccess
) {
1387 SCLog(TRUE
, LOG_DEBUG
, CFSTR("pci_port IOServiceGetMatchingServices() failed, kr = 0x%x"), kr
);
1388 return MACH_PORT_NULL
;
1391 port_names
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1393 while ((slot
= IOIteratorNext(slot_iterator
)) != MACH_PORT_NULL
) {
1394 io_registry_entry_t child
;
1395 io_iterator_t child_iterator
= MACH_PORT_NULL
;
1397 kr
= IORegistryEntryCreateIterator(slot
,
1399 kIORegistryIterateRecursively
,
1401 if (kr
!= kIOReturnSuccess
) {
1402 SCLog(TRUE
, LOG_DEBUG
, CFSTR("pci_port IORegistryEntryCreateIterator() failed, kr = 0x%x"), kr
);
1403 CFRelease(port_names
);
1404 return MACH_PORT_NULL
;
1407 while ((child
= IOIteratorNext(child_iterator
)) != MACH_PORT_NULL
) {
1408 if (IOObjectConformsTo(child
, kIONetworkInterfaceClass
)) {
1409 CFNumberRef child_if_type
;
1410 int child_ift
= ift
;
1412 child_if_type
= IORegistryEntryCreateCFProperty(child
,
1413 CFSTR(kIOInterfaceType
),
1416 if (child_if_type
!= NULL
) {
1417 if (!isA_CFNumber(child_if_type
) ||
1418 !CFNumberGetValue(child_if_type
, kCFNumberIntType
, &child_ift
)) {
1419 // assume that it's a match
1422 CFRelease(child_if_type
);
1425 if (ift
== child_ift
) {
1426 CFStringRef if_bsdName
;
1428 if_bsdName
= IORegistryEntryCreateCFProperty(child
,
1429 CFSTR(kIOBSDNameKey
),
1432 if (if_bsdName
!= NULL
) {
1433 CFArrayAppendValue(port_names
, if_bsdName
);
1434 CFRelease(if_bsdName
);
1438 IOObjectRelease(child
);
1440 IOObjectRelease(child_iterator
);
1441 IOObjectRelease(slot
);
1443 IOObjectRelease(slot_iterator
);
1445 n
= CFArrayGetCount(port_names
);
1447 CFArraySortValues(port_names
, CFRangeMake(0, n
), compare_bsdNames
, NULL
);
1448 n
= CFArrayGetFirstIndexOfValue(port_names
, CFRangeMake(0, n
), bsdName
);
1449 if (n
!= kCFNotFound
) {
1450 port_name
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%d"), n
+ 1);
1454 CFRelease(port_names
);
1460 pci_slot_info(io_registry_entry_t interface
, int ift
, CFStringRef
*slot_name
, CFStringRef
*port_name
)
1462 CFStringRef bsd_name
;
1464 CFTypeRef pci_slot_name
;
1469 bsd_name
= IORegistryEntryCreateCFProperty(interface
, CFSTR(kIOBSDNameKey
), NULL
, 0);
1470 if (bsd_name
== NULL
) {
1474 *slot_name
= pci_slot(interface
, &pci_slot_name
);
1475 if (*slot_name
!= NULL
) {
1476 if (pci_slot_name
!= NULL
) {
1477 *port_name
= pci_port(pci_slot_name
, ift
, bsd_name
);
1478 CFRelease(pci_slot_name
);
1483 CFRelease(bsd_name
);
1489 isBuiltin(io_registry_entry_t interface
)
1493 slot
= pci_slot(interface
, NULL
);
1495 // interfaces which have a "slot" are not built-in
1505 isBluetoothBuiltin(Boolean
*haveController
)
1507 Boolean builtin
= FALSE
;
1508 io_object_t hciController
;
1509 io_iterator_t iter
= MACH_PORT_NULL
;
1512 kr
= IOServiceGetMatchingServices(masterPort
,
1513 IOServiceMatching("IOBluetoothHCIController"),
1515 if ((kr
!= kIOReturnSuccess
) || (iter
== MACH_PORT_NULL
)) {
1516 if (kr
!= kIOReturnSuccess
) {
1517 SCLog(TRUE
, LOG_DEBUG
, CFSTR("isBluetoothBuiltin IOServiceGetMatchingServices() failed, kr = 0x%x"), kr
);
1519 *haveController
= FALSE
;
1522 *haveController
= TRUE
;
1524 hciController
= IOIteratorNext(iter
);
1525 IOObjectRelease(iter
);
1526 if(hciController
!= MACH_PORT_NULL
) {
1527 CFNumberRef idVendor
;
1529 idVendor
= IORegistryEntryCreateCFProperty(hciController
, CFSTR(kUSBVendorID
), NULL
, 0);
1530 if (idVendor
!= NULL
) {
1533 if (isA_CFNumber(idVendor
) &&
1534 CFNumberGetValue(idVendor
, kCFNumberIntType
, &idVendorVal
) &&
1535 (idVendorVal
== kIOUSBVendorIDAppleComputer
)) {
1539 CFRelease(idVendor
);
1542 IOObjectRelease(hciController
);
1550 isThunderbolt(io_registry_entry_t interface
)
1554 val
= IORegistryEntrySearchCFProperty(interface
,
1556 CFSTR(kPCIThunderboltString
),
1558 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1569 processUSBInterface(SCNetworkInterfacePrivateRef interfacePrivate
,
1570 io_registry_entry_t interface
,
1571 CFDictionaryRef interface_dict
,
1572 io_registry_entry_t controller
,
1573 CFDictionaryRef controller_dict
,
1574 io_registry_entry_t bus
,
1575 CFDictionaryRef bus_dict
)
1578 interfacePrivate
->usb
.name
= IORegistryEntrySearchCFProperty(interface
,
1580 CFSTR(kUSBProductString
),
1582 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1583 interfacePrivate
->usb
.vid
= IORegistryEntrySearchCFProperty(interface
,
1585 CFSTR(kUSBVendorID
),
1587 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1588 interfacePrivate
->usb
.pid
= IORegistryEntrySearchCFProperty(interface
,
1590 CFSTR(kUSBProductID
),
1592 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1599 update_interface_name(SCNetworkInterfacePrivateRef interfacePrivate
,
1600 io_registry_entry_t interface
,
1603 Boolean updated
= FALSE
;
1606 // check if a "Product Name" has been provided
1607 val
= IORegistryEntrySearchCFProperty(interface
,
1609 CFSTR(kIOPropertyProductNameKey
),
1611 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1612 if ((val
== NULL
) && useUSBInfo
&& (interfacePrivate
->usb
.name
!= NULL
)) {
1613 // else, use "USB Product Name" if available
1614 val
= CFRetain(interfacePrivate
->usb
.name
);
1617 CFStringRef productName
;
1619 productName
= IOCopyCFStringValue(val
);
1622 if (productName
!= NULL
) {
1623 if (CFStringGetLength(productName
) > 0) {
1624 // if we have a [somewhat reasonable?] product name
1625 if (interfacePrivate
->name
!= NULL
) {
1626 CFRelease(interfacePrivate
->name
);
1628 interfacePrivate
->name
= CFRetain(productName
);
1629 if (interfacePrivate
->localized_name
!= NULL
) {
1630 CFRelease(interfacePrivate
->localized_name
);
1632 interfacePrivate
->localized_name
= copy_interface_string(bundle
, productName
, TRUE
);
1637 CFRelease(productName
);
1646 #pragma mark Interface enumeration
1649 typedef Boolean (*processInterface
)(SCNetworkInterfacePrivateRef interfacePrivate
,
1650 io_registry_entry_t interface
,
1651 CFDictionaryRef interface_dict
,
1652 io_registry_entry_t controller
,
1653 CFDictionaryRef controller_dict
,
1654 io_registry_entry_t bus
,
1655 CFDictionaryRef bus_dict
);
1659 merge_override(SCNetworkInterfacePrivateRef interfacePrivate
,
1660 io_registry_entry_t interface
,
1661 CFStringRef override
)
1666 key
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("Device%@Overrides"), override
);
1667 val
= IORegistryEntrySearchCFProperty(interface
,
1671 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1674 if (isA_CFDictionary(val
)) {
1675 if (interfacePrivate
->overrides
== NULL
) {
1676 interfacePrivate
->overrides
= CFDictionaryCreateMutable(NULL
,
1678 &kCFTypeDictionaryKeyCallBacks
,
1679 &kCFTypeDictionaryValueCallBacks
);
1681 CFDictionarySetValue(interfacePrivate
->overrides
, override
, val
);
1691 processNetworkInterface(SCNetworkInterfacePrivateRef interfacePrivate
,
1692 io_registry_entry_t interface
,
1693 CFDictionaryRef interface_dict
,
1694 io_registry_entry_t controller
,
1695 CFDictionaryRef controller_dict
,
1696 io_registry_entry_t bus
,
1697 CFDictionaryRef bus_dict
)
1707 num
= CFDictionaryGetValue(interface_dict
, CFSTR(kIOInterfaceType
));
1708 if (isA_CFNumber(num
) &&
1709 CFNumberGetValue(num
, kCFNumberIntType
, &ift
)) {
1710 interfacePrivate
->type
= CFRetain(num
);
1712 SCLog(TRUE
, LOG_DEBUG
, CFSTR("processNetworkInterface() failed, no interface type"));
1720 if ((IOObjectConformsTo(controller
, "IO80211Controller")) ||
1721 (IOObjectConformsTo(controller
, "AirPortPCI" )) ||
1722 (IOObjectConformsTo(controller
, "AirPortDriver" ))) {
1723 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeIEEE80211
;
1724 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeEthernet
;
1725 interfacePrivate
->sort_order
= kSortAirPort
;
1726 } else if (IOObjectConformsTo(controller
, "IOBluetoothBNEPDriver")) {
1727 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
;
1728 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeEthernet
;
1729 interfacePrivate
->sort_order
= kSortBluetoothPAN_GN
;
1730 } else if (IOObjectConformsTo(controller
, "AppleUSBEthernetHost")) {
1731 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
;
1732 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeEthernet
;
1733 interfacePrivate
->sort_order
= kSortTethered
;
1734 } else if (IOObjectConformsTo(controller
, "AppleUSBCDCECMData")) {
1735 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
;
1736 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeEthernet
;
1737 interfacePrivate
->sort_order
= kSortWWANEthernet
;
1740 if (interfacePrivate
->interface_type
== NULL
) {
1741 val
= IORegistryEntrySearchCFProperty(interface
,
1743 CFSTR(kIOUserEthernetInterfaceRoleKey
),
1745 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1747 if (isA_CFString(val
)) {
1748 if (CFEqual(val
, CFSTR("Bluetooth PAN"))) {
1749 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
;
1750 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeEthernet
;
1751 interfacePrivate
->sort_order
= kSortBluetoothPAN_GN
;
1752 } else if (CFEqual(val
, CFSTR("Bluetooth PAN-NAP"))) {
1753 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
;
1754 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeEthernet
;
1755 interfacePrivate
->sort_order
= kSortBluetoothPAN_NAP
;
1756 } else if (CFEqual(val
, CFSTR("Bluetooth P2P"))) {
1757 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
;
1758 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeEthernet
;
1759 interfacePrivate
->sort_order
= kSortBluetoothPAN_U
;
1767 if (interfacePrivate
->interface_type
== NULL
) {
1768 str
= IODictionaryCopyCFStringValue(bus_dict
, CFSTR("name"));
1770 if (CFEqual(str
, CFSTR("radio"))) {
1771 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
; // ??
1772 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeEthernet
;
1773 interfacePrivate
->sort_order
= kSortOtherWireless
;
1780 if (interfacePrivate
->interface_type
== NULL
) {
1781 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
;
1782 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeEthernet
;
1783 interfacePrivate
->sort_order
= kSortEthernet
;
1785 // BOND support only enabled for ethernet devices
1786 interfacePrivate
->supportsBond
= TRUE
;
1789 // enable Bridge support
1790 interfacePrivate
->supportsBridge
= TRUE
;
1793 val
= isA_CFBoolean(CFDictionaryGetValue(interface_dict
, CFSTR(kIOBuiltin
)));
1795 val
= isA_CFBoolean(CFDictionaryGetValue(interface_dict
, CFSTR(kIOPrimaryInterface
)));
1798 interfacePrivate
->builtin
= CFBooleanGetValue(val
);
1800 interfacePrivate
->builtin
= isBuiltin(interface
);
1803 if (!interfacePrivate
->builtin
&&
1804 CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeIEEE80211
)) {
1805 // always treat AirPort interfaces as built-in
1806 interfacePrivate
->builtin
= TRUE
;
1810 interfacePrivate
->location
= IODictionaryCopyCFStringValue(interface_dict
, CFSTR(kIOLocation
));
1813 num
= CFDictionaryGetValue(controller_dict
, CFSTR(kIOFeatures
));
1814 if (isA_CFNumber(num
) &&
1815 CFNumberGetValue(num
, kCFNumberIntType
, & iVal
)) {
1816 if (iVal
& (kIONetworkFeatureHardwareVlan
| kIONetworkFeatureSoftwareVlan
)) {
1817 interfacePrivate
->supportsVLAN
= TRUE
;
1822 if (CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeIEEE80211
)) {
1823 interfacePrivate
->localized_key
= CFSTR("airport");
1824 } else if (interfacePrivate
->sort_order
== kSortBluetoothPAN_GN
) {
1825 interfacePrivate
->localized_key
= CFSTR("bluetooth-pan-gn");
1826 } else if (interfacePrivate
->sort_order
== kSortBluetoothPAN_NAP
) {
1827 interfacePrivate
->localized_key
= CFSTR("bluetooth-pan-nap");
1828 } else if (interfacePrivate
->sort_order
== kSortBluetoothPAN_U
) {
1829 interfacePrivate
->localized_key
= CFSTR("bluetooth-pan-u");
1830 } else if (interfacePrivate
->sort_order
== kSortOtherWireless
) {
1831 interfacePrivate
->localized_key
= CFSTR("wireless");
1832 interfacePrivate
->localized_arg1
= CFRetain(CFSTR("")); // ??
1833 } else if (interfacePrivate
->builtin
) {
1834 if ((interfacePrivate
->location
== NULL
) ||
1835 (CFStringGetLength(interfacePrivate
->location
) == 0)) {
1836 interfacePrivate
->localized_key
= CFSTR("ether");
1838 interfacePrivate
->localized_key
= CFSTR("multiether");
1839 interfacePrivate
->localized_arg1
= CFRetain(interfacePrivate
->location
);
1842 CFStringRef provider
;
1844 // check provider class
1845 provider
= IORegistryEntrySearchCFProperty(interface
,
1847 CFSTR(kIOProviderClassKey
),
1849 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1850 if (provider
!= NULL
) {
1851 if (CFEqual(provider
, CFSTR("IOPCIDevice"))) {
1852 CFStringRef port_name
;
1853 CFStringRef slot_name
;
1855 // set interface "name"
1856 if (!update_interface_name(interfacePrivate
, interface
, FALSE
) &&
1857 pci_slot_info(interface
, ift
, &slot_name
, &port_name
)) {
1858 if (isThunderbolt(interface
)) {
1859 if (port_name
== NULL
) {
1860 interfacePrivate
->localized_key
= CFSTR("thunderbolt-ether");
1861 interfacePrivate
->localized_arg1
= slot_name
;
1863 interfacePrivate
->localized_key
= CFSTR("thunderbolt-multiether");
1864 interfacePrivate
->localized_arg1
= slot_name
;
1865 interfacePrivate
->localized_arg2
= port_name
;
1869 if (port_name
== NULL
) {
1870 interfacePrivate
->localized_key
= CFSTR("pci-ether");
1871 interfacePrivate
->localized_arg1
= slot_name
;
1873 interfacePrivate
->localized_key
= CFSTR("pci-multiether");
1874 interfacePrivate
->localized_arg1
= slot_name
;
1875 interfacePrivate
->localized_arg2
= port_name
;
1879 } else if (CFEqual(provider
, CFSTR("IOUSBDevice")) ||
1880 CFEqual(provider
, CFSTR("IOUSBInterface"))) {
1881 // get USB info (if available)
1882 processUSBInterface(interfacePrivate
,
1890 // set interface "name"
1891 if (!update_interface_name(interfacePrivate
, interface
, TRUE
)) {
1892 interfacePrivate
->localized_key
= CFSTR("usb-ether");
1893 interfacePrivate
->localized_arg1
= IODictionaryCopyCFStringValue(interface_dict
, CFSTR(kIOBSDNameKey
));
1896 CFRelease(provider
);
1899 if (interfacePrivate
->localized_key
== NULL
) {
1900 // if no provider, not a PCI device, or no slot information
1901 interfacePrivate
->localized_key
= CFSTR("generic-ether");
1902 interfacePrivate
->localized_arg1
= IODictionaryCopyCFStringValue(interface_dict
, CFSTR(kIOBSDNameKey
));
1909 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeFireWire
;
1912 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeFireWire
;
1915 interfacePrivate
->builtin
= isBuiltin(interface
);
1918 interfacePrivate
->sort_order
= kSortFireWire
;
1921 if (interfacePrivate
->builtin
) {
1922 interfacePrivate
->localized_key
= CFSTR("firewire");
1924 CFStringRef port_name
;
1925 CFStringRef slot_name
;
1927 // set interface "name"
1928 if (!update_interface_name(interfacePrivate
, interface
, FALSE
) &&
1929 pci_slot_info(interface
, ift
, &slot_name
, &port_name
)) {
1930 if (isThunderbolt(interface
)) {
1931 if (port_name
== NULL
) {
1932 interfacePrivate
->localized_key
= CFSTR("thunderbolt-firewire");
1933 interfacePrivate
->localized_arg1
= slot_name
;
1935 interfacePrivate
->localized_key
= CFSTR("thunderbolt-multifirewire");
1936 interfacePrivate
->localized_arg1
= slot_name
;
1937 interfacePrivate
->localized_arg2
= port_name
;
1940 if (port_name
== NULL
) {
1941 interfacePrivate
->localized_key
= CFSTR("pci-firewire");
1942 interfacePrivate
->localized_arg1
= slot_name
;
1944 interfacePrivate
->localized_key
= CFSTR("pci-multifirewire");
1945 interfacePrivate
->localized_arg1
= slot_name
;
1946 interfacePrivate
->localized_arg2
= port_name
;
1954 SCLog(TRUE
, LOG_DEBUG
, CFSTR("processNetworkInterface() failed, unknown interface type = %d"), ift
);
1959 interfacePrivate
->entity_device
= IODictionaryCopyCFStringValue(interface_dict
, CFSTR(kIOBSDNameKey
));
1961 // Hardware (MAC) address
1962 data
= CFDictionaryGetValue(controller_dict
, CFSTR(kIOMACAddress
));
1963 if (isA_CFData(data
)) {
1964 interfacePrivate
->address
= CFRetain(data
);
1968 num
= CFDictionaryGetValue(interface_dict
, CFSTR(kIOInterfaceUnit
));
1969 if (isA_CFNumber(num
) &&
1970 CFNumberGetValue(num
, kCFNumberIntType
, & iVal
)) {
1971 interfacePrivate
->unit
= CFRetain(num
);
1974 // configuration [PPP] template override (now deprecated, use NetworkConfigurationOverrides)
1975 merge_override(interfacePrivate
, interface
, kSCNetworkInterfaceTypePPP
);
1982 set_connection_script(SCNetworkInterfacePrivateRef interfacePrivate
, CFStringRef script
)
1984 CFDictionaryRef dict
;
1985 CFMutableDictionaryRef newDict
;
1987 if (interfacePrivate
->overrides
== NULL
) {
1988 interfacePrivate
->overrides
= CFDictionaryCreateMutable(NULL
,
1990 &kCFTypeDictionaryKeyCallBacks
,
1991 &kCFTypeDictionaryValueCallBacks
);
1994 dict
= CFDictionaryGetValue(interfacePrivate
->overrides
, kSCNetworkInterfaceTypeModem
);
1996 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
1998 newDict
= CFDictionaryCreateMutable(NULL
,
2000 &kCFTypeDictionaryKeyCallBacks
,
2001 &kCFTypeDictionaryValueCallBacks
);
2003 if (script
!= NULL
) {
2004 CFDictionarySetValue(newDict
, kSCPropNetModemConnectionScript
, script
);
2006 CFDictionaryRemoveValue(newDict
, kSCPropNetModemConnectionScript
);
2008 if (CFDictionaryGetCount(newDict
) > 0) {
2009 CFDictionarySetValue(interfacePrivate
->overrides
, kSCNetworkInterfaceTypeModem
, newDict
);
2011 CFDictionaryRemoveValue(interfacePrivate
->overrides
, kSCNetworkInterfaceTypeModem
);
2015 if (CFDictionaryGetCount(interfacePrivate
->overrides
) == 0) {
2016 CFRelease(interfacePrivate
->overrides
);
2017 interfacePrivate
->overrides
= NULL
;
2024 is_valid_connection_script(CFStringRef script
)
2026 char ccl
[MAXPATHLEN
];
2027 char path
[MAXPATHLEN
];
2028 NSSearchPathEnumerationState state
;
2030 (void) _SC_cfstring_to_cstring(script
,
2033 kCFStringEncodingUTF8
);
2035 state
= NSStartSearchPathEnumeration(NSLibraryDirectory
,
2036 NSLocalDomainMask
|NSSystemDomainMask
);
2037 while ((state
= NSGetNextSearchPathEnumeration(state
, path
))) {
2039 struct stat statBuf
;
2041 if (ccl
[0] == '/') {
2042 path
[0] = '\0'; // if modemCCL is a full path
2044 strlcat(path
, "/Modem Scripts/", sizeof(path
));
2046 strlcat(path
, ccl
, sizeof(path
));
2048 if (stat(path
, &statBuf
) != 0) {
2049 if (errno
== ENOENT
) {
2053 SCLog(TRUE
, LOG_DEBUG
,
2054 CFSTR("processSerialInterface stat() failed: %s"),
2058 if (S_ISREG(statBuf
.st_mode
)) {
2059 // if we have a valid CCL script
2063 #define BUNDLE_EXT ".ccl"
2064 #define BUNDLE_EXT_LEN sizeof(BUNDLE_EXT) - 1
2069 if ((n
<= BUNDLE_EXT_LEN
) ||
2070 (strstr(&path
[n
- BUNDLE_EXT_LEN
], BUNDLE_EXT
) == NULL
)) {
2071 strlcat(path
, BUNDLE_EXT
, sizeof(path
));
2072 if (stat(path
, &statBuf
) != 0) {
2073 if (errno
== ENOENT
) {
2077 SCLog(TRUE
, LOG_DEBUG
,
2078 CFSTR("processSerialInterface stat() failed: %s"),
2083 if (S_ISDIR(statBuf
.st_mode
)) {
2084 // if we have a valid CCL bundle
2094 processSerialInterface(SCNetworkInterfacePrivateRef interfacePrivate
,
2095 io_registry_entry_t interface
,
2096 CFDictionaryRef interface_dict
,
2097 io_registry_entry_t controller
,
2098 CFDictionaryRef controller_dict
,
2099 io_registry_entry_t bus
,
2100 CFDictionaryRef bus_dict
)
2102 CFStringRef base
= NULL
;
2104 Boolean isModem
= FALSE
;
2105 Boolean isWWAN
= FALSE
;
2106 CFStringRef modemCCL
= NULL
;
2111 val
= IORegistryEntrySearchCFProperty(interface
,
2113 kSCNetworkInterfaceHiddenPortKey
,
2115 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
2118 return FALSE
; // if this interface should not be exposed
2121 // check if initializing
2122 val
= IORegistryEntrySearchCFProperty(interface
,
2124 kSCNetworkInterfaceInitializingKey
,
2126 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
2128 Boolean initializing
;
2130 initializing
= isA_CFBoolean(val
) && CFBooleanGetValue(val
);
2133 return FALSE
; // if this interface is still initializing
2138 val
= IORegistryEntrySearchCFProperty(interface
,
2142 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
2144 isWWAN
= isA_CFBoolean(val
) && CFBooleanGetValue(val
);
2149 interfacePrivate
->entity_device
= IODictionaryCopyCFStringValue(interface_dict
, CFSTR(kIOTTYDeviceKey
));
2150 if (interfacePrivate
->entity_device
== NULL
) {
2154 base
= IODictionaryCopyCFStringValue(interface_dict
, CFSTR(kIOTTYBaseNameKey
));
2156 base
= CFRetain(interfacePrivate
->entity_device
);
2162 * Exclude ports named "irda" because otherwise the IrDA ports on the
2163 * original iMac (rev's A through D) show up as serial ports. Given
2164 * that only the rev A actually had an IrDA port, and Mac OS X doesn't
2165 * even support it, these ports definitely shouldn't be listed.
2167 if (CFStringCompare(base
,
2169 kCFCompareCaseInsensitive
) == kCFCompareEqualTo
) {
2173 if (IOStringValueHasPrefix(base
, CFSTR("bluetooth"))) {
2174 Boolean haveController
= FALSE
;
2177 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeBluetooth
;
2178 interfacePrivate
->sort_order
= kSortBluetooth
;
2179 interfacePrivate
->builtin
= isBluetoothBuiltin(&haveController
);
2180 if (!haveController
) {
2181 // if device with no controller present
2184 } else if (IOStringValueHasPrefix(base
, CFSTR("irda-ircomm"))) {
2186 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeIrDA
;
2187 interfacePrivate
->sort_order
= kSortIrDA
;
2188 } else if (isWWAN
) {
2190 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeWWAN
;
2191 interfacePrivate
->sort_order
= kSortWWAN
;
2194 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeModem
;
2195 interfacePrivate
->sort_order
= kSortModem
;
2198 val
= IORegistryEntrySearchCFProperty(interface
,
2200 CFSTR(kIODeviceSupportsHoldKey
),
2202 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
2206 if (isA_CFNumber(val
) &&
2207 CFNumberGetValue(val
, kCFNumberSInt32Type
, &v92
)) {
2208 interfacePrivate
->modemIsV92
= (v92
== 1);
2215 interfacePrivate
->entity_type
= kSCEntNetModem
;
2217 // Entity (Hardware)
2218 ift
= CFDictionaryGetValue(interface_dict
, CFSTR(kIOSerialBSDTypeKey
));
2219 if (!isA_CFString(ift
)) {
2223 if (CFEqual(ift
, CFSTR(kIOSerialBSDModemType
))) {
2227 if (CFEqual(base
, CFSTR("modem"))) {
2228 interfacePrivate
->builtin
= TRUE
;
2229 interfacePrivate
->sort_order
= kSortInternalModem
;
2230 } else if (CFEqual(base
, CFSTR("usbmodem"))) {
2231 interfacePrivate
->sort_order
= kSortUSBModem
;
2233 } else if (CFEqual(ift
, CFSTR(kIOSerialBSDRS232Type
))) {
2235 interfacePrivate
->sort_order
= kSortSerialPort
;
2240 // configuration [PPP] template override (now deprecated, use NetworkConfigurationOverrides)
2241 merge_override(interfacePrivate
, interface
, kSCNetworkInterfaceTypePPP
);
2243 // configuration [Modem] template override (now deprecated, use NetworkConfigurationOverrides)
2244 merge_override(interfacePrivate
, interface
, kSCNetworkInterfaceTypeModem
);
2246 // look for modem CCL, unique identifier
2247 if (interfacePrivate
->overrides
!= NULL
) {
2248 val
= CFDictionaryGetValue(interfacePrivate
->overrides
, kSCNetworkInterfaceTypeModem
);
2250 CFStringRef uniqueID
;
2252 modemCCL
= CFDictionaryGetValue(val
, kSCPropNetModemConnectionScript
);
2253 modemCCL
= isA_CFString(modemCCL
);
2255 uniqueID
= CFDictionaryGetValue(val
, CFSTR("UniqueIdentifier"));
2256 uniqueID
= isA_CFString(uniqueID
);
2257 if (uniqueID
!= NULL
) {
2258 // retain the device's base name and the unique id
2259 CFRelease(interfacePrivate
->entity_device
);
2260 interfacePrivate
->entity_device
= CFRetain(base
);
2261 interfacePrivate
->entity_device_unique
= CFStringCreateCopy(NULL
, uniqueID
);
2266 // if not part of the NetworkConfigurationOverrides/DeviceModemOverrides, look
2267 // a bit harder for the modem CCL
2268 if (modemCCL
== NULL
) {
2269 val
= IORegistryEntrySearchCFProperty(interface
,
2273 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
2275 modemCCL
= IOCopyCFStringValue(val
);
2276 if (modemCCL
!= NULL
) {
2277 set_connection_script(interfacePrivate
, modemCCL
);
2278 CFRelease(modemCCL
);
2286 if (CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeIrDA
)) {
2287 interfacePrivate
->localized_key
= CFSTR("irda");
2288 } else if (CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeBluetooth
)) {
2289 interfacePrivate
->localized_key
= CFSTR("bluetooth");
2291 CFStringRef localized
= NULL
;
2292 CFStringRef name
= NULL
;
2293 CFMutableStringRef port
;
2295 port
= CFStringCreateMutableCopy(NULL
, 0, base
);
2296 CFStringLowercase(port
, NULL
);
2299 CFStringAppend(port
, CFSTR("-port"));
2302 // set non-localized name
2303 if (bundle
!= NULL
) {
2304 name
= copy_interface_string(bundle
, port
, FALSE
);
2307 if (!CFEqual(port
, name
)) {
2308 // if [English] localization available
2309 interfacePrivate
->name
= name
;
2311 // if no [English] localization available, use TTY base name
2313 interfacePrivate
->name
= CFStringCreateCopy(NULL
, base
);
2316 interfacePrivate
->name
= CFStringCreateCopy(NULL
, base
);
2319 // set localized name
2320 if (bundle
!= NULL
) {
2321 localized
= copy_interface_string(bundle
, port
, TRUE
);
2323 if (localized
!= NULL
) {
2324 if (!CFEqual(port
, localized
)) {
2325 // if localization available
2326 interfacePrivate
->localized_name
= localized
;
2328 // if no localization available, use TTY base name
2329 CFRelease(localized
);
2330 interfacePrivate
->localized_name
= CFStringCreateCopy(NULL
, base
);
2333 interfacePrivate
->localized_name
= CFStringCreateCopy(NULL
, base
);
2336 if (!isModem
|| !CFEqual(base
, CFSTR("modem"))) {
2337 // get USB info (if available)
2338 processUSBInterface(interfacePrivate
,
2346 // set interface "name"
2347 if (update_interface_name(interfacePrivate
, interface
, TRUE
)) {
2348 // if "ModemCCL" not provided, also check if the product/interface
2349 // name matches a CCL script
2350 if ((modemCCL
== NULL
) &&
2351 is_valid_connection_script(interfacePrivate
->name
)) {
2352 set_connection_script(interfacePrivate
, interfacePrivate
->name
);
2364 if (!ok
&& (interfacePrivate
->entity_device
!= NULL
)) {
2365 CFRelease(interfacePrivate
->entity_device
);
2366 interfacePrivate
->entity_device
= NULL
;
2368 if (base
!= NULL
) CFRelease(base
);
2375 __SC_IORegistryEntryCopyPath(io_registry_entry_t entry
, const io_name_t plane
)
2378 * Create a path for a registry entry.
2382 CFStringRef str
= NULL
;
2384 status
= IORegistryEntryGetPath(entry
, plane
, path
);
2385 if (status
== kIOReturnSuccess
) {
2386 str
= CFStringCreateWithCString(NULL
, path
, kCFStringEncodingUTF8
);
2387 } else if (status
== kIOReturnBadArgument
) {
2388 io_registry_entry_t parent
;
2390 status
= IORegistryEntryGetParentEntry(entry
, plane
, &parent
);
2391 if (status
== kIOReturnSuccess
) {
2392 CFStringRef str_parent
;
2394 str_parent
= __SC_IORegistryEntryCopyPath(parent
, plane
);
2395 if (str_parent
!= NULL
) {
2398 status
= IORegistryEntryGetNameInPlane(entry
, plane
, name
);
2399 if (status
== kIOReturnSuccess
) {
2402 status
= IORegistryEntryGetLocationInPlane(entry
, plane
, location
);
2403 if (status
== kIOReturnSuccess
) {
2404 str
= CFStringCreateWithFormat(NULL
,
2411 str
= CFStringCreateWithFormat(NULL
,
2419 CFRelease(str_parent
);
2422 IOObjectRelease(parent
);
2430 static SCNetworkInterfaceRef
2431 createInterface(io_registry_entry_t interface
, processInterface func
)
2433 io_registry_entry_t bus
= MACH_PORT_NULL
;
2434 CFMutableDictionaryRef bus_dict
= NULL
;
2435 io_registry_entry_t controller
= MACH_PORT_NULL
;
2436 CFMutableDictionaryRef controller_dict
= NULL
;
2437 uint64_t entryID
= 0;
2438 SCNetworkInterfacePrivateRef interfacePrivate
= NULL
;
2439 CFMutableDictionaryRef interface_dict
= NULL
;
2443 kr
= IORegistryEntryCreateCFProperties(interface
, &interface_dict
, NULL
, kNilOptions
);
2444 if (kr
!= kIOReturnSuccess
) {
2445 SCLog(TRUE
, LOG_DEBUG
, CFSTR("createInterface IORegistryEntryCreateCFProperties() failed, kr = 0x%x"), kr
);
2449 /* get the controller node */
2450 kr
= IORegistryEntryGetParentEntry(interface
, kIOServicePlane
, &controller
);
2451 if (kr
!= KERN_SUCCESS
) {
2452 SCLog(TRUE
, LOG_DEBUG
, CFSTR("createInterface IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr
);
2456 /* get the dictionary associated with the node */
2457 kr
= IORegistryEntryCreateCFProperties(controller
, &controller_dict
, NULL
, kNilOptions
);
2458 if (kr
!= KERN_SUCCESS
) {
2459 SCLog(TRUE
, LOG_DEBUG
, CFSTR("createInterface IORegistryEntryCreateCFProperties() failed, kr = 0x%x"), kr
);
2463 /* get the bus node */
2464 kr
= IORegistryEntryGetParentEntry(controller
, kIOServicePlane
, &bus
);
2465 if (kr
!= KERN_SUCCESS
) {
2466 SCLog(TRUE
, LOG_DEBUG
, CFSTR("createInterface IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr
);
2470 /* get the dictionary associated with the node */
2471 kr
= IORegistryEntryCreateCFProperties(bus
, &bus_dict
, NULL
, kNilOptions
);
2472 if (kr
!= KERN_SUCCESS
) {
2473 SCLog(TRUE
, LOG_DEBUG
, CFSTR("createInterface IORegistryEntryCreateCFProperties() failed, kr = 0x%x"), kr
);
2477 /* get the registry entry ID */
2478 kr
= IORegistryEntryGetRegistryEntryID(interface
, &entryID
);
2479 if (kr
!= KERN_SUCCESS
) {
2480 SCLog(TRUE
, LOG_DEBUG
, CFSTR("createInterface IORegistryEntryGetRegistryEntryID() failed, kr = 0x%x"), kr
);
2484 interfacePrivate
= __SCNetworkInterfaceCreatePrivate(NULL
, NULL
, NULL
, NULL
);
2485 interfacePrivate
->path
= __SC_IORegistryEntryCopyPath(interface
, kIOServicePlane
);
2486 interfacePrivate
->entryID
= entryID
;
2488 // configuration [PPP, Modem, DNS, IPv4, IPv6, Proxies, SMB] template overrides
2489 val
= IORegistryEntrySearchCFProperty(interface
,
2491 kSCNetworkInterfaceNetworkConfigurationOverridesKey
,
2493 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
2495 if (isA_CFDictionary(val
)) {
2496 interfacePrivate
->overrides
= CFDictionaryCreateMutableCopy(NULL
, 0, val
);
2501 if ((*func
)(interfacePrivate
, interface
, interface_dict
, controller
, controller_dict
, bus
, bus_dict
)) {
2502 /* get user-notification / auto-configuration preference */
2503 val
= IORegistryEntrySearchCFProperty(interface
,
2505 kSCNetworkInterfaceConfigurationActionKey
,
2507 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
2509 if (isA_CFString(val
)) {
2510 interfacePrivate
->configurationAction
= CFRetain(val
);
2515 /* get HiddenConfiguration preference */
2516 val
= IORegistryEntrySearchCFProperty(interface
,
2518 kSCNetworkInterfaceHiddenConfigurationKey
,
2520 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
2522 interfacePrivate
->hidden
= TRUE
;
2526 CFRelease(interfacePrivate
);
2527 interfacePrivate
= NULL
;
2532 if (interface_dict
!= NULL
) CFRelease(interface_dict
);
2534 if (controller
!= MACH_PORT_NULL
) IOObjectRelease(controller
);
2535 if (controller_dict
!= NULL
) CFRelease(controller_dict
);
2537 if (bus
!= MACH_PORT_NULL
) IOObjectRelease(bus
);
2538 if (bus_dict
!= NULL
) CFRelease(bus_dict
);
2540 return (SCNetworkInterfaceRef
)interfacePrivate
;
2544 static CF_RETURNS_RETAINED CFArrayRef
2545 findMatchingInterfaces(CFDictionaryRef matching
, processInterface func
)
2547 CFMutableArrayRef interfaces
;
2548 io_registry_entry_t interface
;
2550 io_iterator_t iterator
= MACH_PORT_NULL
;
2553 * A reference to the "matching" dictionary will be consumed by the
2554 * the call to IOServiceGetMatchingServices so we bump up the retain
2559 kr
= IOServiceGetMatchingServices(masterPort
, matching
, &iterator
);
2560 if (kr
!= kIOReturnSuccess
) {
2561 SCLog(TRUE
, LOG_DEBUG
, CFSTR("findMatchingInterfaces IOServiceGetMatchingServices() failed, kr = 0x%x"), kr
);
2565 interfaces
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
2567 while ((interface
= IOIteratorNext(iterator
)) != MACH_PORT_NULL
) {
2568 SCNetworkInterfaceRef match
;
2570 match
= createInterface(interface
, func
);
2571 if (match
!= NULL
) {
2572 CFArrayAppendValue(interfaces
, match
);
2576 IOObjectRelease(interface
);
2579 IOObjectRelease(iterator
);
2586 #pragma mark helper functions
2590 findConfiguration(CFStringRef interface_type
)
2594 for (i
= 0; i
< sizeof(configurations
)/sizeof(configurations
[0]); i
++) {
2595 if (CFEqual(interface_type
, *configurations
[i
].interface_type
)) {
2606 __SCNetworkInterfaceGetDefaultConfigurationType(SCNetworkInterfaceRef interface
)
2608 CFIndex interfaceIndex
;
2609 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2611 if (interfacePrivate
->serviceID
== NULL
) {
2612 // if not associated with a service (yet)
2613 _SCErrorSet(kSCStatusInvalidArgument
);
2617 interfaceIndex
= findConfiguration(interfacePrivate
->interface_type
);
2618 if (interfaceIndex
== kCFNotFound
) {
2619 // unknown interface type, use per-service configuration preferences
2620 return interfacePrivate
->interface_type
; // entity
2623 if (configurations
[interfaceIndex
].entity_hardware
!= NULL
) {
2624 // if configuration information can be associated with this interface type
2625 return *configurations
[interfaceIndex
].entity_hardware
;
2628 _SCErrorSet(kSCStatusInvalidArgument
);
2635 __SCNetworkInterfaceIsValidExtendedConfigurationType(SCNetworkInterfaceRef interface
,
2636 CFStringRef extendedType
,
2637 Boolean requirePerInterface
)
2639 CFStringRef defaultType
;
2640 CFIndex extendedIndex
;
2641 CFIndex interfaceIndex
;
2642 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2643 Boolean isL2TP
= FALSE
;
2646 defaultType
= __SCNetworkInterfaceGetDefaultConfigurationType(interface
);
2647 if (defaultType
== NULL
) {
2651 if (CFEqual(extendedType
, defaultType
)) {
2652 // extended and default configuration types cannot conflict
2656 interfaceIndex
= findConfiguration(interfacePrivate
->interface_type
);
2657 if (interfaceIndex
== kCFNotFound
) {
2658 // configuration information for unknown interface type's
2659 // are stored along with the service and we don't allow
2660 // per-service extended configurations
2664 if (CFEqual(extendedType
, kSCEntNetIPSec
)) {
2665 CFStringRef interfaceType
;
2667 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
2668 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
)) {
2669 SCNetworkInterfaceRef child
;
2671 child
= SCNetworkInterfaceGetInterface(interface
);
2672 if (child
!= NULL
) {
2673 interfaceType
= SCNetworkInterfaceGetInterfaceType(child
);
2674 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeL2TP
)) {
2681 if (requirePerInterface
&&
2682 !configurations
[interfaceIndex
].per_interface_config
&&
2684 // we don't allow per-service extended configurations (except
2685 // that we do allow IPSec as an extended type for PPP->L2TP)
2689 extendedIndex
= findConfiguration(extendedType
);
2690 if ((extendedIndex
!= kCFNotFound
) && !isL2TP
) {
2691 // extended type cannot match a known interface type (except
2692 // that we do allow IPSec as an extended type for PPP->L2TP)
2698 * Do we match specific/known extended configuration types (e.g. EAPOL)
2699 * and ensure that any non-standard extended configuration types be of
2700 * the form com.myCompany.myType?
2709 _SCErrorSet(kSCStatusInvalidArgument
);
2716 CFStringRef defaultType
;
2717 CFMutableArrayRef types
;
2718 } extendedConfiguration
, *extendedConfigurationRef
;
2722 __addExtendedConfigurationType(const void *key
, const void *value
, void *context
)
2724 CFStringRef extendedType
= (CFStringRef
)key
;
2725 extendedConfigurationRef myContextRef
= (extendedConfigurationRef
)context
;
2727 if (CFEqual(extendedType
, myContextRef
->defaultType
)) {
2728 // do not include the default configuration type
2732 if (CFArrayContainsValue(myContextRef
->types
,
2733 CFRangeMake(0, CFArrayGetCount(myContextRef
->types
)),
2735 // if extendedType already has already been added
2739 CFArrayAppendValue(myContextRef
->types
, extendedType
);
2745 static CF_RETURNS_RETAINED CFArrayRef
2746 extendedConfigurationTypes(SCNetworkInterfaceRef interface
)
2749 CFIndex interfaceIndex
;
2750 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2751 extendedConfiguration myContext
;
2752 SCNetworkServiceRef service
;
2756 myContext
.defaultType
= __SCNetworkInterfaceGetDefaultConfigurationType(interface
);
2757 if (myContext
.defaultType
== NULL
) {
2758 myContext
.types
= NULL
;
2762 myContext
.types
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
2764 if (interfacePrivate
->serviceID
== NULL
) {
2765 // if not associated with a service (yet)
2769 interfaceIndex
= findConfiguration(interfacePrivate
->interface_type
);
2770 if (interfaceIndex
== kCFNotFound
) {
2771 // we don't allow per-service extended configurations
2775 if (!configurations
[interfaceIndex
].per_interface_config
) {
2776 // known interface type but we still don't allow
2777 // per-service extended configurations
2781 service
= (SCNetworkServiceRef
)__SCNetworkServiceCreatePrivate(NULL
,
2782 interfacePrivate
->prefs
,
2783 interfacePrivate
->serviceID
,
2786 sets
= SCNetworkSetCopyAll(interfacePrivate
->prefs
);
2787 n
= (sets
!= NULL
) ? CFArrayGetCount(sets
) : 0;
2789 for (i
= 0; i
< n
; i
++) {
2790 CFDictionaryRef configs
;
2793 CFArrayRef services
;
2794 SCNetworkSetRef set
;
2796 set
= CFArrayGetValueAtIndex(sets
, i
);
2797 services
= SCNetworkSetCopyServices(set
);
2798 found
= CFArrayContainsValue(services
,
2799 CFRangeMake(0, CFArrayGetCount(services
)),
2801 CFRelease(services
);
2807 // add stored extended configuration types
2808 path
= SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL
, // allocator
2809 SCNetworkSetGetSetID(set
), // set
2810 interfacePrivate
->entity_device
, // service
2812 configs
= __getPrefsConfiguration(interfacePrivate
->prefs
, path
);
2814 if (isA_CFDictionary(configs
)) {
2815 CFDictionaryApplyFunction(configs
,
2816 __addExtendedConfigurationType
,
2820 // add not-yet-stored extended configuration types
2821 if (interfacePrivate
->unsaved
!= NULL
) {
2822 CFDictionaryApplyFunction(interfacePrivate
->unsaved
,
2823 __addExtendedConfigurationType
,
2831 if (sets
!= NULL
) CFRelease(sets
);
2835 return myContext
.types
;
2840 copyConfigurationPaths(SCNetworkInterfacePrivateRef interfacePrivate
,
2841 CFStringRef extendedType
)
2843 CFMutableArrayRef array
;
2845 CFIndex interfaceIndex
;
2848 SCNetworkServiceRef service
;
2851 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
2853 interfaceIndex
= findConfiguration(interfacePrivate
->interface_type
);
2854 if (interfaceIndex
== kCFNotFound
) {
2855 // unknown interface type, use per-service configuration preferences
2856 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
2857 interfacePrivate
->serviceID
, // service
2858 extendedType
); // entity
2859 CFArrayAppendValue(array
, path
);
2864 if (!configurations
[interfaceIndex
].per_interface_config
) {
2865 // known interface type, per-service configuration preferences
2866 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
2867 interfacePrivate
->serviceID
, // service
2868 extendedType
); // entity
2869 CFArrayAppendValue(array
, path
);
2874 // known interface type, per-interface configuration preferences
2876 // 1. look for all sets which contain the associated service
2877 // 2. add a per-set path for the interface configuration for
2880 service
= (SCNetworkServiceRef
)__SCNetworkServiceCreatePrivate(NULL
,
2881 interfacePrivate
->prefs
,
2882 interfacePrivate
->serviceID
,
2883 (SCNetworkInterfaceRef
)interfacePrivate
);
2885 sets
= SCNetworkSetCopyAll(interfacePrivate
->prefs
);
2886 n
= (sets
!= NULL
) ? CFArrayGetCount(sets
) : 0;
2888 for (i
= 0; i
< n
; i
++) {
2889 CFArrayRef services
;
2890 SCNetworkSetRef set
;
2892 set
= CFArrayGetValueAtIndex(sets
, i
);
2893 services
= SCNetworkSetCopyServices(set
);
2894 if (CFArrayContainsValue(services
,
2895 CFRangeMake(0, CFArrayGetCount(services
)),
2897 path
= SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL
, // allocator
2898 SCNetworkSetGetSetID(set
), // set
2899 interfacePrivate
->entity_device
, // service
2900 extendedType
); // entity
2901 CFArrayAppendValue(array
, path
);
2904 CFRelease(services
);
2907 if (CFArrayGetCount(array
) == 0) {
2913 if (sets
!= NULL
) CFRelease(sets
);
2919 #pragma mark SCNetworkInterface <--> preferences entity
2924 __SCNetworkInterfaceCopyInterfaceEntity(SCNetworkInterfaceRef interface
)
2926 CFMutableDictionaryRef entity
;
2927 CFIndex interfaceIndex
;
2928 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2930 entity
= CFDictionaryCreateMutable(NULL
,
2932 &kCFTypeDictionaryKeyCallBacks
,
2933 &kCFTypeDictionaryValueCallBacks
);
2934 if (interfacePrivate
->entity_type
!= NULL
) {
2935 CFDictionarySetValue(entity
,
2936 kSCPropNetInterfaceType
,
2937 interfacePrivate
->entity_type
);
2939 if (interfacePrivate
->entity_subtype
!= NULL
) {
2940 CFDictionarySetValue(entity
,
2941 kSCPropNetInterfaceSubType
,
2942 interfacePrivate
->entity_subtype
);
2944 if (interfacePrivate
->entity_device
!= NULL
) {
2945 CFDictionarySetValue(entity
,
2946 kSCPropNetInterfaceDeviceName
,
2947 interfacePrivate
->entity_device
);
2949 if (interfacePrivate
->entity_device_unique
!= NULL
) {
2950 CFDictionarySetValue(entity
,
2951 CFSTR("DeviceUniqueIdentifier"),
2952 interfacePrivate
->entity_device_unique
);
2954 if (interfacePrivate
->hidden
) {
2955 CFDictionarySetValue(entity
,
2956 kSCNetworkInterfaceHiddenConfigurationKey
,
2960 // match the "hardware" with the lowest layer
2962 SCNetworkInterfaceRef nextInterface
;
2964 nextInterface
= SCNetworkInterfaceGetInterface(interface
);
2965 if (nextInterface
== NULL
) {
2969 interface
= nextInterface
;
2971 interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2973 if (CFEqual(interface
, kSCNetworkInterfaceIPv4
)) {
2977 interfaceIndex
= findConfiguration(interfacePrivate
->interface_type
);
2978 if (interfaceIndex
!= kCFNotFound
) {
2979 if (configurations
[interfaceIndex
].entity_hardware
!= NULL
) {
2980 CFDictionarySetValue(entity
,
2981 kSCPropNetInterfaceHardware
,
2982 *configurations
[interfaceIndex
].entity_hardware
);
2985 CFDictionarySetValue(entity
,
2986 kSCPropNetInterfaceHardware
,
2987 interfacePrivate
->interface_type
);
2990 // add the localized display name (which will only be used when/if the
2991 // interface is removed from the system)
2992 CFDictionarySetValue(entity
,
2993 kSCPropUserDefinedName
,
2994 SCNetworkInterfaceGetLocalizedDisplayName(interface
));
2996 // note that this is a V.92 capable modem
2997 if (CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeModem
) &&
2998 interfacePrivate
->modemIsV92
) {
3002 num
= CFNumberCreate(NULL
, kCFNumberIntType
, &one
);
3003 CFDictionarySetValue(entity
,
3004 kSCPropNetInterfaceSupportsModemOnHold
,
3013 static SCNetworkInterfaceRef
3014 findInterface(CFArrayRef interfaces
, CFStringRef match_if
)
3019 n
= CFArrayGetCount(interfaces
);
3020 for (i
= 0; i
< n
; i
++) {
3021 SCNetworkInterfaceRef interface
= CFArrayGetValueAtIndex(interfaces
, i
);
3022 CFStringRef interfaceName
;
3024 interfaceName
= SCNetworkInterfaceGetBSDName(interface
);
3025 if ((interfaceName
!= NULL
) && CFEqual(interfaceName
, match_if
)) {
3026 CFRetain(interface
);
3034 #if !TARGET_OS_IPHONE
3035 static SCNetworkInterfaceRef
3036 findBondInterface(SCPreferencesRef prefs
, CFStringRef ifDevice
)
3039 SCNetworkInterfaceRef interface
= NULL
;
3041 if (prefs
== NULL
) {
3045 // check if the interface is an Ethernet Bond
3046 bonds
= SCBondInterfaceCopyAll(prefs
);
3047 if (bonds
!= NULL
) {
3048 interface
= findInterface(bonds
, ifDevice
);
3053 #endif // !TARGET_OS_IPHONE
3055 static SCNetworkInterfaceRef
3056 findBridgeInterface(SCPreferencesRef prefs
, CFStringRef ifDevice
)
3059 SCNetworkInterfaceRef interface
= NULL
;
3061 if (prefs
== NULL
) {
3065 // check if the interface is an bridge
3066 bridges
= SCBridgeInterfaceCopyAll(prefs
);
3067 if (bridges
!= NULL
) {
3068 interface
= findInterface(bridges
, ifDevice
);
3074 static SCNetworkInterfaceRef
3075 findVLANInterface(SCPreferencesRef prefs
, CFStringRef ifDevice
)
3077 SCNetworkInterfaceRef interface
= NULL
;
3080 if (prefs
== NULL
) {
3084 // check if the interface is a VLAN
3085 vlans
= SCVLANInterfaceCopyAll(prefs
);
3086 if (vlans
!= NULL
) {
3087 interface
= findInterface(vlans
, ifDevice
);
3094 SCNetworkInterfaceRef
3095 _SCNetworkInterfaceCreateWithBSDName(CFAllocatorRef allocator
,
3096 CFStringRef bsdName
,
3099 CFMutableDictionaryRef entity
;
3100 SCNetworkInterfaceRef interface
;
3102 entity
= CFDictionaryCreateMutable(NULL
,
3104 &kCFTypeDictionaryKeyCallBacks
,
3105 &kCFTypeDictionaryValueCallBacks
);
3106 CFDictionarySetValue(entity
, kSCPropNetInterfaceDeviceName
, bsdName
);
3108 #if !TARGET_OS_IPHONE
3109 if ((flags
& kIncludeBondInterfaces
) == 0) {
3110 CFDictionarySetValue(entity
, CFSTR("_NO_BOND_INTERFACES_"), kCFBooleanTrue
);
3112 #endif // !TARGET_OS_IPHONE
3114 if ((flags
& kIncludeBridgeInterfaces
) == 0) {
3115 CFDictionarySetValue(entity
, CFSTR("_NO_BRIDGE_INTERFACES_"), kCFBooleanTrue
);
3118 if ((flags
& kIncludeVLANInterfaces
) == 0) {
3119 CFDictionarySetValue(entity
, CFSTR("_NO_VLAN_INTERFACES_"), kCFBooleanTrue
);
3122 interface
= _SCNetworkInterfaceCreateWithEntity(NULL
, entity
, NULL
);
3130 __SCNetworkInterfaceSetService(SCNetworkInterfaceRef interface
,
3131 SCNetworkServiceRef service
)
3133 SCNetworkInterfacePrivateRef interfacePrivate
;
3134 SCNetworkServicePrivateRef servicePrivate
;
3136 interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
3137 if (interfacePrivate
->prefs
!= NULL
) {
3138 CFRelease(interfacePrivate
->prefs
);
3139 interfacePrivate
->prefs
= NULL
;
3141 if (interfacePrivate
->serviceID
!= NULL
) {
3142 CFRelease(interfacePrivate
->serviceID
);
3143 interfacePrivate
->serviceID
= NULL
;
3146 servicePrivate
= (SCNetworkServicePrivateRef
)service
;
3147 if (servicePrivate
->prefs
!= NULL
) {
3148 interfacePrivate
->prefs
= CFRetain(servicePrivate
->prefs
);
3150 if (servicePrivate
->serviceID
!= NULL
) {
3151 interfacePrivate
->serviceID
= CFRetain(servicePrivate
->serviceID
);
3159 _SCNetworkInterfaceMatchesName(CFStringRef name
, CFStringRef key
)
3164 if (bundle
== NULL
) {
3169 if (!isA_CFString(name
)) {
3170 // if no interface "name"
3174 // check non-localized name for a match
3175 str
= copy_interface_string(bundle
, key
, FALSE
);
3177 match
= CFEqual(name
, str
);
3184 // check localized name for a match
3185 str
= copy_interface_string(bundle
, key
, TRUE
);
3187 match
= CFEqual(name
, str
);
3198 SCNetworkInterfaceRef
3199 _SCNetworkInterfaceCreateWithEntity(CFAllocatorRef allocator
,
3200 CFDictionaryRef interface_entity
,
3201 SCNetworkServiceRef service
)
3203 SCNetworkInterfacePrivateRef interfacePrivate
= NULL
;
3204 CFStringRef ifDevice
;
3205 CFStringRef ifName
= NULL
;
3206 CFStringRef ifSubType
;
3208 CFStringRef ifUnique
;
3209 CFArrayRef matching_interfaces
= NULL
;
3211 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
3212 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
3214 ifType
= CFDictionaryGetValue(interface_entity
, kSCPropNetInterfaceType
);
3215 if (ifType
== NULL
) {
3217 * The interface "Type" was not specified. We'll make an
3218 * assumption that this is an "Ethernet" interface. If a
3219 * real interface exists with the provided interface name
3220 * then the actual type will be set accordingly. If not, we'll
3221 * end up crafting an "Ethernet" SCNetworkInterface which
3222 * will keep the rest of the configuration APIs happy.
3224 ifType
= kSCValNetInterfaceTypeEthernet
;
3227 if (!isA_CFString(ifType
)) {
3231 ifSubType
= CFDictionaryGetValue(interface_entity
, kSCPropNetInterfaceSubType
);
3232 if (CFEqual(ifType
, kSCValNetInterfaceTypePPP
) ||
3233 CFEqual(ifType
, kSCValNetInterfaceTypeVPN
)) {
3234 if (!isA_CFString(ifSubType
)) {
3239 ifDevice
= CFDictionaryGetValue(interface_entity
, kSCPropNetInterfaceDeviceName
);
3240 ifUnique
= CFDictionaryGetValue(interface_entity
, CFSTR("DeviceUniqueIdentifier"));
3242 if (CFEqual(ifType
, kSCValNetInterfaceTypeEthernet
) ||
3243 CFEqual(ifType
, kSCValNetInterfaceTypeFireWire
) ||
3244 (CFEqual(ifType
, kSCValNetInterfaceTypePPP
) && CFEqual(ifSubType
, kSCValNetInterfaceSubTypePPPoE
))) {
3245 char bsdName
[IFNAMSIZ
];
3246 CFMutableDictionaryRef matching
;
3248 if (!isA_CFString(ifDevice
)) {
3252 if (CFEqual(ifDevice
, CFSTR("lo0"))) { // for _SCNetworkInterfaceCreateWithBSDName
3253 interfacePrivate
= __SCNetworkInterfaceCreateCopy(NULL
, kSCNetworkInterfaceLoopback
, NULL
, NULL
);
3257 if (_SC_cfstring_to_cstring(ifDevice
, bsdName
, sizeof(bsdName
), kCFStringEncodingASCII
) == NULL
) {
3261 matching
= IOBSDNameMatching(masterPort
, 0, bsdName
);
3262 if (matching
== NULL
) {
3265 matching_interfaces
= findMatchingInterfaces(matching
, processNetworkInterface
);
3266 CFRelease(matching
);
3267 } else if (CFEqual(ifType
, kSCValNetInterfaceTypePPP
)) {
3268 if (CFEqual(ifSubType
, kSCValNetInterfaceSubTypePPPSerial
)) {
3269 CFDictionaryRef matching
;
3270 CFStringRef match_keys
[2];
3271 CFStringRef match_vals
[2];
3273 if (!isA_CFString(ifDevice
)) {
3277 match_keys
[0] = CFSTR(kIOProviderClassKey
);
3278 match_vals
[0] = CFSTR(kIOSerialBSDServiceValue
);
3280 match_keys
[1] = CFSTR(kIOTTYBaseNameKey
);
3281 match_vals
[1] = ifDevice
;
3283 matching
= CFDictionaryCreate(NULL
,
3284 (const void **)match_keys
,
3285 (const void **)match_vals
,
3286 sizeof(match_keys
)/sizeof(match_keys
[0]),
3287 &kCFTypeDictionaryKeyCallBacks
,
3288 &kCFTypeDictionaryValueCallBacks
);
3289 matching_interfaces
= findMatchingInterfaces(matching
, processSerialInterface
);
3290 CFRelease(matching
);
3292 if (ifUnique
== NULL
) {
3294 Boolean useDeviceName
= TRUE
;
3296 n
= (matching_interfaces
!= NULL
) ? CFArrayGetCount(matching_interfaces
) : 0;
3300 for (i
= 0; i
< n
; i
++) {
3301 SCNetworkInterfacePrivateRef scanPrivate
;
3303 scanPrivate
= (SCNetworkInterfacePrivateRef
)CFArrayGetValueAtIndex(matching_interfaces
, i
);
3304 if (scanPrivate
->entity_device_unique
!= NULL
) {
3305 useDeviceName
= FALSE
;
3311 if (useDeviceName
) {
3312 if (matching_interfaces
!= NULL
) {
3313 CFRelease(matching_interfaces
);
3316 match_keys
[1] = CFSTR(kIOTTYDeviceKey
);
3317 matching
= CFDictionaryCreate(NULL
,
3318 (const void **)match_keys
,
3319 (const void **)match_vals
,
3320 sizeof(match_keys
)/sizeof(match_keys
[0]),
3321 &kCFTypeDictionaryKeyCallBacks
,
3322 &kCFTypeDictionaryValueCallBacks
);
3323 matching_interfaces
= findMatchingInterfaces(matching
, processSerialInterface
);
3324 CFRelease(matching
);
3327 } else if (CFEqual(ifSubType
, kSCValNetInterfaceSubTypeL2TP
)) {
3328 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
3329 kSCNetworkInterfaceTypeL2TP
);
3330 } else if (CFEqual(ifSubType
, kSCValNetInterfaceSubTypePPTP
)) {
3331 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
3332 kSCNetworkInterfaceTypePPTP
);
3334 // XXX do we allow non-Apple variants of PPP??? XXX
3335 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
3338 } else if (CFEqual(ifType
, kSCValNetInterfaceType6to4
)) {
3339 if (!isA_CFString(ifDevice
)) {
3343 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
3344 kSCNetworkInterfaceType6to4
);
3345 } else if (CFEqual(ifType
, kSCValNetInterfaceTypeIPSec
)) {
3346 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
3347 kSCNetworkInterfaceTypeIPSec
);
3348 } else if (CFEqual(ifType
, kSCValNetInterfaceTypeLoopback
)) {
3349 interfacePrivate
= __SCNetworkInterfaceCreateCopy(NULL
, kSCNetworkInterfaceLoopback
, NULL
, NULL
);
3350 } else if (CFEqual(ifType
, kSCValNetInterfaceTypeVPN
)) {
3351 if (CFStringFind(ifSubType
, CFSTR("."), 0).location
!= kCFNotFound
) {
3352 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
3355 } else if ((CFStringFind(ifType
, CFSTR("."), 0).location
!= kCFNotFound
) && (ifDevice
== NULL
)) {
3356 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
3360 if (matching_interfaces
!= NULL
) {
3362 SCPreferencesRef prefs
;
3364 n
= CFArrayGetCount(matching_interfaces
);
3367 interfacePrivate
= (SCNetworkInterfacePrivateRef
)CFArrayGetValueAtIndex(matching_interfaces
, 0);
3368 if (_SC_CFEqual(ifUnique
, interfacePrivate
->entity_device_unique
)) {
3369 // if the unique ID's match
3370 CFRetain(interfacePrivate
);
3374 interfacePrivate
= NULL
;
3377 if (!CFEqual(ifType
, kSCValNetInterfaceTypeEthernet
)) {
3380 prefs
= SCPreferencesCreate(NULL
, CFSTR("SCNetworkInterface"), NULL
);
3381 if (prefs
== NULL
) {
3384 #if !TARGET_OS_IPHONE
3385 if (!CFDictionaryContainsKey(interface_entity
, CFSTR("_NO_BOND_INTERFACES_"))) {
3386 interfacePrivate
= (SCNetworkInterfacePrivateRef
)findBondInterface(prefs
, ifDevice
);
3388 #endif // !TARGET_OS_IPHONE
3389 if ((interfacePrivate
== NULL
)
3390 && !CFDictionaryContainsKey(interface_entity
, CFSTR("_NO_BRIDGE_INTERFACES_"))) {
3391 interfacePrivate
= (SCNetworkInterfacePrivateRef
)findBridgeInterface(prefs
, ifDevice
);
3394 if ((interfacePrivate
== NULL
)
3395 && !CFDictionaryContainsKey(interface_entity
, CFSTR("_NO_VLAN_INTERFACES_"))) {
3396 interfacePrivate
= (SCNetworkInterfacePrivateRef
)findVLANInterface(prefs
, ifDevice
);
3401 if (ifUnique
!= NULL
) {
3404 // we are looking for an interface with a unique ID
3405 // so let's try to focus our choices
3406 for (i
= 0; i
< n
; i
++) {
3407 SCNetworkInterfacePrivateRef scanPrivate
;
3409 scanPrivate
= (SCNetworkInterfacePrivateRef
)CFArrayGetValueAtIndex(matching_interfaces
, i
);
3410 if (_SC_CFEqual(ifUnique
, scanPrivate
->entity_device_unique
)) {
3411 if (interfacePrivate
!= NULL
) {
3412 // if we've matched more than one interface
3413 interfacePrivate
= NULL
;
3416 interfacePrivate
= scanPrivate
;
3419 } else if (CFDictionaryGetValueIfPresent(interface_entity
,
3420 kSCPropUserDefinedName
,
3421 (const void **)&ifName
)) {
3424 // we don't have a unique ID but do have an interface
3425 // name. If the matching interfaces do have IDs than
3426 // we can try to focus our choices using the name
3427 for (i
= 0; i
< n
; i
++) {
3428 SCNetworkInterfacePrivateRef scanPrivate
;
3430 scanPrivate
= (SCNetworkInterfacePrivateRef
)CFArrayGetValueAtIndex(matching_interfaces
, i
);
3431 if (scanPrivate
->entity_device_unique
!= NULL
) {
3432 SCNetworkInterfaceRef scan
= (SCNetworkInterfaceRef
)scanPrivate
;
3433 CFStringRef scanName
;
3435 scanName
= __SCNetworkInterfaceGetNonLocalizedDisplayName(scan
);
3436 if ((scanName
!= NULL
) && !_SC_CFEqual(ifName
, scanName
)) {
3437 continue; // if not the same display name
3441 if (interfacePrivate
!= NULL
) {
3442 // if we've matched more than one interface
3443 interfacePrivate
= NULL
;
3446 interfacePrivate
= scanPrivate
;
3449 if (interfacePrivate
== NULL
) {
3450 SCLog(TRUE
, LOG_ERR
, CFSTR("_SCNetworkInterfaceCreateWithEntity() failed, more than one interface matches %@"), ifDevice
);
3451 interfacePrivate
= (SCNetworkInterfacePrivateRef
)CFArrayGetValueAtIndex(matching_interfaces
, 0);
3453 CFRetain(interfacePrivate
);
3456 CFRelease(matching_interfaces
);
3461 if (interfacePrivate
== NULL
) {
3463 * if device not present on this system
3465 interfacePrivate
= __SCNetworkInterfaceCreatePrivate(NULL
, NULL
, NULL
, NULL
);
3466 interfacePrivate
->entity_type
= ifType
;
3467 interfacePrivate
->entity_subtype
= ifSubType
;
3468 interfacePrivate
->entity_device
= (ifDevice
!= NULL
) ? CFStringCreateCopy(NULL
, ifDevice
) : NULL
;
3469 interfacePrivate
->entity_device_unique
= (ifUnique
!= NULL
) ? CFStringCreateCopy(NULL
, ifUnique
) : NULL
;
3471 if (CFEqual(ifType
, kSCValNetInterfaceTypeEthernet
)) {
3472 CFStringRef entity_hardware
;
3474 entity_hardware
= CFDictionaryGetValue(interface_entity
, kSCPropNetInterfaceHardware
);
3475 if (isA_CFString((entity_hardware
)) &&
3476 CFEqual(entity_hardware
, kSCEntNetAirPort
)) {
3477 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeIEEE80211
;
3478 interfacePrivate
->localized_key
= CFSTR("airport");
3479 interfacePrivate
->sort_order
= kSortAirPort
;
3483 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
;
3485 name
= CFDictionaryGetValue(interface_entity
, kSCPropUserDefinedName
);
3486 if (_SCNetworkInterfaceMatchesName(name
, CFSTR("iPhone"))) {
3487 interfacePrivate
->localized_key
= CFSTR("iPhone");
3488 interfacePrivate
->sort_order
= kSortTethered
;
3489 } else if (_SCNetworkInterfaceMatchesName(name
, CFSTR("bluetooth-pan-gn"))) {
3490 interfacePrivate
->localized_key
= CFSTR("bluetooth-pan-gn");
3491 interfacePrivate
->sort_order
= kSortBluetoothPAN_GN
;
3492 } else if (_SCNetworkInterfaceMatchesName(name
, CFSTR("bluetooth-pan-nap"))) {
3493 interfacePrivate
->localized_key
= CFSTR("bluetooth-pan-nap");
3494 interfacePrivate
->sort_order
= kSortBluetoothPAN_NAP
;
3495 } else if (_SCNetworkInterfaceMatchesName(name
, CFSTR("bluetooth-pan-u"))) {
3496 interfacePrivate
->localized_key
= CFSTR("bluetooth-pan-u");
3497 interfacePrivate
->sort_order
= kSortBluetoothPAN_U
;
3499 interfacePrivate
->sort_order
= kSortEthernet
;
3502 } else if (CFEqual(ifType
, kSCValNetInterfaceTypeFireWire
)) {
3503 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeFireWire
;
3504 interfacePrivate
->sort_order
= kSortFireWire
;
3505 } else if (CFEqual(ifType
, kSCValNetInterfaceTypePPP
)) {
3506 if (CFEqual(ifSubType
, kSCValNetInterfaceSubTypePPPoE
)) {
3507 CFStringRef entity_hardware
;
3509 entity_hardware
= CFDictionaryGetValue(interface_entity
, kSCPropNetInterfaceHardware
);
3510 if (isA_CFString((entity_hardware
)) &&
3511 CFEqual(entity_hardware
, kSCEntNetAirPort
)) {
3512 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeIEEE80211
;
3513 interfacePrivate
->sort_order
= kSortAirPort
;
3515 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
;
3516 interfacePrivate
->sort_order
= kSortEthernet
;
3518 } else if (CFEqual(ifSubType
, kSCValNetInterfaceSubTypePPPSerial
)) {
3519 if (CFStringHasPrefix(ifDevice
, CFSTR("Bluetooth"))) {
3520 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeBluetooth
;
3521 interfacePrivate
->sort_order
= kSortBluetooth
;
3522 } else if (CFStringHasPrefix(ifDevice
, CFSTR("irda"))) {
3523 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeIrDA
;
3524 interfacePrivate
->sort_order
= kSortIrDA
;
3525 } else if (CFStringHasPrefix(ifDevice
, CFSTR("wwan"))) {
3526 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeWWAN
;
3527 interfacePrivate
->sort_order
= kSortWWAN
;
3529 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeModem
;
3530 interfacePrivate
->sort_order
= kSortModem
;
3533 SCNetworkInterfaceRef child
;
3536 CFRelease(interfacePrivate
);
3537 child
= SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
, ifSubType
);
3538 interfacePrivate
= (SCNetworkInterfacePrivateRef
)child
;
3539 if (interfacePrivate
== NULL
) {
3543 } else if (CFEqual(ifType
, kSCValNetInterfaceTypeVPN
)) {
3544 SCNetworkInterfaceRef child
;
3546 CFRelease(interfacePrivate
);
3547 child
= SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
, ifSubType
);
3548 interfacePrivate
= (SCNetworkInterfacePrivateRef
)child
;
3549 if (interfacePrivate
== NULL
) {
3552 } else if (CFStringFind(ifType
, CFSTR("."), 0).location
!= kCFNotFound
) {
3553 // if vendor interface
3554 if (vendor_interface_types
== NULL
) {
3555 vendor_interface_types
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
3557 CFSetAddValue(vendor_interface_types
, ifType
);
3559 interfacePrivate
->interface_type
= CFSetGetValue(vendor_interface_types
, ifType
);
3561 // if unknown interface
3562 CFRelease(interfacePrivate
);
3563 interfacePrivate
= NULL
;
3567 if (CFDictionaryContainsKey(interface_entity
, kSCNetworkInterfaceHiddenConfigurationKey
)) {
3568 interfacePrivate
->hidden
= TRUE
;
3572 if (service
!= NULL
) {
3573 __SCNetworkInterfaceSetService((SCNetworkInterfaceRef
)interfacePrivate
,
3576 #if !TARGET_OS_IPHONE
3577 // set prefs & serviceID to Bond member interfaces
3578 if (CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeBond
)) {
3583 members
= SCBondInterfaceGetMemberInterfaces((SCNetworkInterfaceRef
)interfacePrivate
);
3584 n
= (members
!= NULL
) ? CFArrayGetCount(members
) : 0;
3585 for (i
= 0; i
< n
; i
++) {
3586 SCNetworkInterfaceRef member
;
3588 member
= CFArrayGetValueAtIndex(members
, i
);
3589 __SCNetworkInterfaceSetService(member
, service
);
3592 #endif // !TARGET_OS_IPHONE
3594 // set prefs & serviceID to Bridge member interfaces
3595 if (CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeBridge
)) {
3600 members
= SCBridgeInterfaceGetMemberInterfaces((SCNetworkInterfaceRef
)interfacePrivate
);
3601 n
= (members
!= NULL
) ? CFArrayGetCount(members
) : 0;
3602 for (i
= 0; i
< n
; i
++) {
3603 SCNetworkInterfaceRef member
;
3605 member
= CFArrayGetValueAtIndex(members
, i
);
3606 __SCNetworkInterfaceSetService(member
, service
);
3610 // set prefs & serviceID to VLAN pyhsical interface
3611 if (CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeVLAN
)) {
3612 SCNetworkInterfaceRef vlan_physical
;
3614 vlan_physical
= SCVLANInterfaceGetPhysicalInterface((SCNetworkInterfaceRef
)interfacePrivate
);
3615 if (vlan_physical
!= NULL
) {
3616 __SCNetworkInterfaceSetService(vlan_physical
, service
);
3621 if (CFEqual(ifType
, kSCValNetInterfaceTypePPP
)) {
3622 SCNetworkInterfaceRef parent
;
3625 parent
= SCNetworkInterfaceCreateWithInterface((SCNetworkInterfaceRef
)interfacePrivate
,
3626 kSCNetworkInterfaceTypePPP
);
3627 CFRelease(interfacePrivate
);
3628 interfacePrivate
= (SCNetworkInterfacePrivateRef
)parent
;
3629 } else if (CFEqual(ifType
, kSCValNetInterfaceTypeVPN
)) {
3630 SCNetworkInterfaceRef parent
;
3633 parent
= SCNetworkInterfaceCreateWithInterface((SCNetworkInterfaceRef
)interfacePrivate
,
3634 kSCNetworkInterfaceTypeVPN
);
3635 CFRelease(interfacePrivate
);
3636 interfacePrivate
= (SCNetworkInterfacePrivateRef
)parent
;
3639 return (SCNetworkInterfaceRef
)interfacePrivate
;
3644 #pragma mark SCNetworkInterface APIs
3649 __SCNetworkInterfaceCopyAll_IONetworkInterface(void)
3651 CFDictionaryRef matching
;
3652 CFArrayRef new_interfaces
;
3654 // get Ethernet, Firewire, and AirPort interfaces
3656 matching
= IOServiceMatching(kIONetworkInterfaceClass
);
3657 new_interfaces
= findMatchingInterfaces(matching
, processNetworkInterface
);
3658 CFRelease(matching
);
3660 return new_interfaces
;
3666 __SCNetworkInterfaceCopyAll_Modem()
3668 CFDictionaryRef matching
;
3669 CFStringRef match_keys
[2];
3670 CFStringRef match_vals
[2];
3671 CFArrayRef new_interfaces
;
3673 match_keys
[0] = CFSTR(kIOProviderClassKey
);
3674 match_vals
[0] = CFSTR(kIOSerialBSDServiceValue
);
3676 match_keys
[1] = CFSTR(kIOSerialBSDTypeKey
);
3677 match_vals
[1] = CFSTR(kIOSerialBSDModemType
);
3679 matching
= CFDictionaryCreate(NULL
,
3680 (const void **)match_keys
,
3681 (const void **)match_vals
,
3682 sizeof(match_keys
)/sizeof(match_keys
[0]),
3683 &kCFTypeDictionaryKeyCallBacks
,
3684 &kCFTypeDictionaryValueCallBacks
);
3685 new_interfaces
= findMatchingInterfaces(matching
, processSerialInterface
);
3686 CFRelease(matching
);
3688 return new_interfaces
;
3694 __SCNetworkInterfaceCopyAll_RS232()
3696 CFDictionaryRef matching
;
3697 CFStringRef match_keys
[2];
3698 CFStringRef match_vals
[2];
3699 CFArrayRef new_interfaces
;
3701 match_keys
[0] = CFSTR(kIOProviderClassKey
);
3702 match_vals
[0] = CFSTR(kIOSerialBSDServiceValue
);
3704 match_keys
[1] = CFSTR(kIOSerialBSDTypeKey
);
3705 match_vals
[1] = CFSTR(kIOSerialBSDRS232Type
);
3707 matching
= CFDictionaryCreate(NULL
,
3708 (const void **)match_keys
,
3709 (const void **)match_vals
,
3710 sizeof(match_keys
)/sizeof(match_keys
[0]),
3711 &kCFTypeDictionaryKeyCallBacks
,
3712 &kCFTypeDictionaryValueCallBacks
);
3713 new_interfaces
= findMatchingInterfaces(matching
, processSerialInterface
);
3714 CFRelease(matching
);
3716 return new_interfaces
;
3720 #if !TARGET_OS_IPHONE
3722 addBTPANInterface(SCPreferencesRef prefs
, CFMutableArrayRef all_interfaces
)
3726 CFArrayRef services
;
3728 n
= CFArrayGetCount(all_interfaces
);
3729 for (i
= 0; i
< n
; i
++) {
3730 SCNetworkInterfaceRef interface
;
3732 interface
= CFArrayGetValueAtIndex(all_interfaces
, i
);
3733 if (_SCNetworkInterfaceIsBluetoothPAN(interface
)) {
3734 // if we already have a BT-PAN interface
3739 services
= SCNetworkServiceCopyAll(prefs
);
3740 if (services
!= NULL
) {
3741 n
= CFArrayGetCount(services
);
3742 for (i
= 0; i
< n
; i
++) {
3743 SCNetworkInterfaceRef interface
;
3744 SCNetworkServiceRef service
;
3746 service
= CFArrayGetValueAtIndex(services
, i
);
3747 interface
= SCNetworkServiceGetInterface(service
);
3748 if ((interface
!= NULL
) &&
3749 _SCNetworkInterfaceIsBluetoothPAN(interface
)) {
3750 // include BT-PAN interface
3751 CFArrayAppendValue(all_interfaces
, interface
);
3756 CFRelease(services
);
3761 #endif // !TARGET_OS_IPHONE
3765 add_interfaces(CFMutableArrayRef all_interfaces
, CFArrayRef new_interfaces
)
3770 n
= CFArrayGetCount(new_interfaces
);
3771 for (i
= 0; i
< n
; i
++) {
3772 CFStringRef bsdName
;
3773 SCNetworkInterfaceRef interface
;
3775 interface
= CFArrayGetValueAtIndex(new_interfaces
, i
);
3776 bsdName
= SCNetworkInterfaceGetBSDName(interface
);
3777 if (bsdName
!= NULL
) {
3778 CFArrayAppendValue(all_interfaces
, interface
);
3787 __waitForInterfaces()
3792 SCDynamicStoreRef store
;
3794 store
= SCDynamicStoreCreate(NULL
, CFSTR("SCNetworkInterfaceCopyAll"), NULL
, NULL
);
3795 if (store
== NULL
) {
3799 key
= SCDynamicStoreKeyCreate(NULL
, CFSTR("%@" "InterfaceNamer"), kSCDynamicStoreDomainPlugin
);
3800 keys
= CFArrayCreate(NULL
, (const void **)&key
, 1, &kCFTypeArrayCallBacks
);
3801 ok
= SCDynamicStoreSetNotificationKeys(store
, keys
, NULL
);
3804 SCLog(TRUE
, LOG_ERR
,
3805 CFSTR("SCDynamicStoreSetNotificationKeys() failed: %s"), SCErrorString(SCError()));
3810 CFArrayRef changedKeys
;
3811 CFDictionaryRef dict
;
3812 Boolean quiet
= FALSE
;
3815 dict
= SCDynamicStoreCopyValue(store
, key
);
3817 if (isA_CFDictionary(dict
) &&
3818 (CFDictionaryContainsKey(dict
, CFSTR("*QUIET*")) ||
3819 CFDictionaryContainsKey(dict
, CFSTR("*TIMEOUT*")))) {
3828 ok
= SCDynamicStoreNotifyWait(store
);
3830 SCLog(TRUE
, LOG_ERR
,
3831 CFSTR("SCDynamicStoreNotifyWait() failed: %s"), SCErrorString(SCError()));
3835 changedKeys
= SCDynamicStoreCopyNotifiedKeys(store
);
3836 if (changedKeys
!= NULL
) {
3837 CFRelease(changedKeys
);
3849 CFArrayRef
/* of SCNetworkInterfaceRef's */
3850 _SCNetworkInterfaceCopyAllWithPreferences(SCPreferencesRef prefs
)
3852 CFMutableArrayRef all_interfaces
;
3853 CFArrayRef new_interfaces
;
3854 Boolean temp_preferences
= FALSE
;
3856 /* initialize runtime */
3857 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
3859 /* wait for IOKit to quiesce */
3860 pthread_once(&iokit_quiet
, __waitForInterfaces
);
3862 all_interfaces
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
3864 // get Ethernet, Firewire, and AirPort interfaces
3865 new_interfaces
= __SCNetworkInterfaceCopyAll_IONetworkInterface();
3866 if (new_interfaces
!= NULL
) {
3867 add_interfaces(all_interfaces
, new_interfaces
);
3868 CFRelease(new_interfaces
);
3871 // get Modem interfaces
3872 new_interfaces
= __SCNetworkInterfaceCopyAll_Modem();
3873 if (new_interfaces
!= NULL
) {
3874 add_interfaces(all_interfaces
, new_interfaces
);
3875 CFRelease(new_interfaces
);
3878 // get serial (RS232) interfaces
3879 new_interfaces
= __SCNetworkInterfaceCopyAll_RS232();
3880 if (new_interfaces
!= NULL
) {
3881 add_interfaces(all_interfaces
, new_interfaces
);
3882 CFRelease(new_interfaces
);
3885 // get virtual network interfaces (Bond, Bridge, VLAN)
3886 if (prefs
== NULL
) {
3887 prefs
= SCPreferencesCreate(NULL
, CFSTR("SCNetworkInterfaceCopyAll"), NULL
);
3888 if (prefs
!= NULL
) {
3889 temp_preferences
= TRUE
;
3892 if (prefs
!= NULL
) {
3893 #if !TARGET_OS_IPHONE
3894 new_interfaces
= SCBondInterfaceCopyAll(prefs
);
3895 if (new_interfaces
!= NULL
) {
3896 add_interfaces(all_interfaces
, new_interfaces
);
3897 CFRelease(new_interfaces
);
3899 #endif // !TARGET_OS_IPHONE
3901 new_interfaces
= SCBridgeInterfaceCopyAll(prefs
);
3902 if (new_interfaces
!= NULL
) {
3903 add_interfaces(all_interfaces
, new_interfaces
);
3904 CFRelease(new_interfaces
);
3907 new_interfaces
= SCVLANInterfaceCopyAll(prefs
);
3908 if (new_interfaces
!= NULL
) {
3909 add_interfaces(all_interfaces
, new_interfaces
);
3910 CFRelease(new_interfaces
);
3913 #if !TARGET_OS_IPHONE
3914 // add BT-PAN interface
3915 addBTPANInterface(prefs
, all_interfaces
);
3916 #endif // !TARGET_OS_IPHONE
3918 if (temp_preferences
) CFRelease(prefs
);
3921 // all interfaces have been identified, order and return
3922 sort_interfaces(all_interfaces
);
3924 return all_interfaces
;
3928 CFArrayRef
/* of SCNetworkInterfaceRef's */
3929 SCNetworkInterfaceCopyAll()
3931 CFArrayRef all_interfaces
;
3933 all_interfaces
= _SCNetworkInterfaceCopyAllWithPreferences(NULL
);
3934 return all_interfaces
;
3938 CFArrayRef
/* of kSCNetworkInterfaceTypeXXX CFStringRef's */
3939 SCNetworkInterfaceGetSupportedInterfaceTypes(SCNetworkInterfaceRef interface
)
3942 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
3944 if (!isA_SCNetworkInterface(interface
)) {
3945 _SCErrorSet(kSCStatusInvalidArgument
);
3949 if (interfacePrivate
->supported_interface_types
!= NULL
) {
3953 i
= findConfiguration(interfacePrivate
->interface_type
);
3954 if (i
!= kCFNotFound
) {
3955 if (configurations
[i
].supported_interfaces
!= doNone
) {
3956 interfacePrivate
->supported_interface_types
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
3957 if (configurations
[i
].supported_interfaces
& do6to4
) {
3958 CFArrayAppendValue(interfacePrivate
->supported_interface_types
, kSCNetworkInterfaceType6to4
);
3960 if (configurations
[i
].supported_interfaces
& doL2TP
) {
3961 CFArrayAppendValue(interfacePrivate
->supported_interface_types
, kSCNetworkInterfaceTypeL2TP
);
3963 if (configurations
[i
].supported_interfaces
& doPPP
) {
3964 CFArrayAppendValue(interfacePrivate
->supported_interface_types
, kSCNetworkInterfaceTypePPP
);
3966 if (configurations
[i
].supported_interfaces
& doPPTP
) {
3967 CFArrayAppendValue(interfacePrivate
->supported_interface_types
, kSCNetworkInterfaceTypePPTP
);
3969 if (configurations
[i
].supported_interfaces
& doIPSec
) {
3970 CFArrayAppendValue(interfacePrivate
->supported_interface_types
, kSCNetworkInterfaceTypeIPSec
);
3974 SCNetworkInterfaceRef child
;
3976 child
= SCNetworkInterfaceGetInterface(interface
);
3977 if ((child
!= NULL
) && CFEqual(child
, kSCNetworkInterfaceIPv4
)) {
3978 interfacePrivate
->supported_interface_types
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
3979 CFArrayAppendValue(interfacePrivate
->supported_interface_types
, kSCNetworkInterfaceTypeVPN
);
3985 return interfacePrivate
->supported_interface_types
;
3989 CFArrayRef
/* of kSCNetworkProtocolTypeXXX CFStringRef's */
3990 SCNetworkInterfaceGetSupportedProtocolTypes(SCNetworkInterfaceRef interface
)
3993 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
3995 if (!isA_SCNetworkInterface(interface
)) {
3996 _SCErrorSet(kSCStatusInvalidArgument
);
4000 if (interfacePrivate
->supported_protocol_types
!= NULL
) {
4004 i
= findConfiguration(interfacePrivate
->interface_type
);
4005 if (i
!= kCFNotFound
) {
4006 if (configurations
[i
].supported_protocols
!= doNone
) {
4007 interfacePrivate
->supported_protocol_types
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
4008 if (configurations
[i
].supported_protocols
& doDNS
) {
4009 CFArrayAppendValue(interfacePrivate
->supported_protocol_types
, kSCNetworkProtocolTypeDNS
);
4011 if (configurations
[i
].supported_protocols
& doIPv4
) {
4012 CFArrayAppendValue(interfacePrivate
->supported_protocol_types
, kSCNetworkProtocolTypeIPv4
);
4014 if (configurations
[i
].supported_protocols
& doIPv6
) {
4015 CFArrayAppendValue(interfacePrivate
->supported_protocol_types
, kSCNetworkProtocolTypeIPv6
);
4017 if (configurations
[i
].supported_protocols
& doProxies
) {
4018 CFArrayAppendValue(interfacePrivate
->supported_protocol_types
, kSCNetworkProtocolTypeProxies
);
4020 #if !TARGET_OS_IPHONE
4021 if (configurations
[i
].supported_protocols
& doSMB
) {
4022 CFArrayAppendValue(interfacePrivate
->supported_protocol_types
, kSCNetworkProtocolTypeSMB
);
4024 #endif // !TARGET_OS_IPHONE
4030 return interfacePrivate
->supported_protocol_types
;
4034 SCNetworkInterfaceRef
4035 SCNetworkInterfaceCreateWithInterface(SCNetworkInterfaceRef child
, CFStringRef interfaceType
)
4037 SCNetworkInterfacePrivateRef childPrivate
= (SCNetworkInterfacePrivateRef
)child
;
4039 SCNetworkInterfacePrivateRef parentPrivate
;
4041 if (!isA_SCNetworkInterface(child
)) {
4042 _SCErrorSet(kSCStatusInvalidArgument
);
4046 if (!isA_CFString(interfaceType
)) {
4047 _SCErrorSet(kSCStatusInvalidArgument
);
4051 if (CFEqual(child
, kSCNetworkInterfaceLoopback
)) {
4052 // can't layer on top of loopback
4053 _SCErrorSet(kSCStatusInvalidArgument
);
4057 childIndex
= findConfiguration(childPrivate
->interface_type
);
4059 parentPrivate
= __SCNetworkInterfaceCreatePrivate(NULL
,
4061 childPrivate
->prefs
,
4062 childPrivate
->serviceID
);
4063 if (parentPrivate
== NULL
) {
4064 _SCErrorSet(kSCStatusFailed
);
4068 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
)) {
4069 parentPrivate
->interface_type
= kSCNetworkInterfaceTypePPP
;
4070 parentPrivate
->entity_type
= kSCValNetInterfaceTypePPP
;
4073 if (childIndex
!= kCFNotFound
) {
4074 if (configurations
[childIndex
].ppp_subtype
!= NULL
) {
4075 parentPrivate
->entity_subtype
= *configurations
[childIndex
].ppp_subtype
;
4077 // sorry, the child interface does not support PPP
4081 // if the child's interface type not known, use the child entities "Type"
4082 parentPrivate
->entity_subtype
= childPrivate
->entity_type
;
4085 if (childPrivate
->entity_device
!= NULL
) {
4086 parentPrivate
->entity_device
= CFStringCreateCopy(NULL
, childPrivate
->entity_device
);
4089 if (childPrivate
->entity_device_unique
!= NULL
) {
4090 parentPrivate
->entity_device_unique
= CFStringCreateCopy(NULL
, childPrivate
->entity_device_unique
);
4092 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeL2TP
)) {
4093 if ((childIndex
== kCFNotFound
) ||
4094 ((configurations
[childIndex
].supported_interfaces
& doL2TP
) != doL2TP
)) {
4095 // if the child interface does not support L2TP
4098 parentPrivate
->interface_type
= kSCNetworkInterfaceTypeL2TP
;
4099 parentPrivate
->localized_key
= CFSTR("l2tp");
4100 parentPrivate
->entity_type
= kSCEntNetL2TP
; // interface config goes into "L2TP"
4101 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPTP
)) {
4102 if ((childIndex
== kCFNotFound
) ||
4103 ((configurations
[childIndex
].supported_interfaces
& doPPTP
) != doPPTP
)) {
4104 // if the child interface does not support PPTP
4107 parentPrivate
->interface_type
= kSCNetworkInterfaceTypePPTP
;
4108 parentPrivate
->localized_key
= CFSTR("pptp");
4109 parentPrivate
->entity_type
= kSCEntNetPPTP
; // interface config goes into "PPTP"
4110 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceType6to4
)) {
4111 if ((childIndex
== kCFNotFound
) ||
4112 ((configurations
[childIndex
].supported_interfaces
& do6to4
) != do6to4
)) {
4113 // if the child interface does not support 6to4
4117 parentPrivate
->interface_type
= kSCNetworkInterfaceType6to4
;
4118 parentPrivate
->localized_key
= CFSTR("6to4");
4119 parentPrivate
->entity_type
= kSCValNetInterfaceType6to4
;
4120 parentPrivate
->entity_device
= CFRetain(CFSTR("stf0"));
4121 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeIPSec
)) {
4122 if ((childIndex
== kCFNotFound
) ||
4123 ((configurations
[childIndex
].supported_interfaces
& doIPSec
) != doIPSec
)) {
4124 // if the child interface does not support IPSec
4127 parentPrivate
->interface_type
= kSCNetworkInterfaceTypeIPSec
;
4128 parentPrivate
->localized_key
= CFSTR("ipsec");
4129 parentPrivate
->entity_type
= kSCValNetInterfaceTypeIPSec
;
4130 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeVPN
)) {
4131 if (childIndex
!= kCFNotFound
) {
4132 // if not a "vendor" child interface
4136 parentPrivate
->interface_type
= kSCNetworkInterfaceTypeVPN
;
4137 parentPrivate
->localized_key
= CFSTR("vpn");
4138 parentPrivate
->localized_arg1
= CFRetain(childPrivate
->entity_type
);
4139 parentPrivate
->entity_type
= kSCValNetInterfaceTypeVPN
;
4140 parentPrivate
->entity_subtype
= childPrivate
->entity_type
;
4141 if (childPrivate
->entity_device
!= NULL
) {
4142 parentPrivate
->entity_device
= CFStringCreateCopy(NULL
, childPrivate
->entity_device
);
4144 if (parentPrivate
->entity_subtype
!= NULL
) {
4145 CFArrayRef components
;
4147 CFStringRef vpnType
;
4150 // the "default" interface name is derived from the VPN type
4153 // com.apple.Apple-VPN.vpnplugin --> "Apple VPN"
4156 vpnType
= parentPrivate
->entity_subtype
;
4157 components
= CFStringCreateArrayBySeparatingStrings(NULL
, vpnType
, CFSTR("."));
4158 n
= CFArrayGetCount(components
);
4160 CFEqual(CFArrayGetValueAtIndex(components
, n
- 1), CFSTR("vpnplugin"))) {
4161 CFMutableStringRef str
;
4163 str
= CFStringCreateMutableCopy(NULL
,
4165 CFArrayGetValueAtIndex(components
, n
- 2));
4166 (void) CFStringFindAndReplace(str
,
4169 CFRangeMake(0, CFStringGetLength(str
)),
4171 parentPrivate
->localized_name
= str
;
4173 CFRelease(components
);
4175 } else if (CFStringFind(interfaceType
, CFSTR("."), 0).location
!= kCFNotFound
) {
4176 // if custom interface type
4177 if (vendor_interface_types
== NULL
) {
4178 vendor_interface_types
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
4180 CFSetAddValue(vendor_interface_types
, interfaceType
);
4182 parentPrivate
->interface_type
= CFSetGetValue(vendor_interface_types
, interfaceType
);
4183 parentPrivate
->entity_type
= parentPrivate
->interface_type
; // interface config goes into a
4184 // a dictionary with the same
4185 // name as the interfaceType
4187 // unknown interface type
4191 parentPrivate
->hidden
= childPrivate
->hidden
;
4193 if (childPrivate
->overrides
!= NULL
) {
4194 parentPrivate
->overrides
= CFDictionaryCreateMutableCopy(NULL
, 0, childPrivate
->overrides
);
4197 // The following change handles the case where a user has both an Ethernet and
4198 // PPPoE network service. Because a PPPoE service is typically associated with
4199 // an ISP we want it to be sorted higher in the service order.
4200 if ((parentPrivate
->entity_subtype
!= NULL
) &&
4201 (CFEqual(parentPrivate
->entity_subtype
, kSCValNetInterfaceSubTypePPPoE
))) {
4202 if ((childPrivate
->interface_type
!= NULL
) &&
4203 (CFEqual(childPrivate
->interface_type
, kSCNetworkInterfaceTypeIEEE80211
))) {
4204 parentPrivate
->sort_order
= kSortAirportPPP
;
4206 parentPrivate
->sort_order
= kSortEthernetPPP
;
4209 // set sort order of the parent to match the child interface
4210 parentPrivate
->sort_order
= childPrivate
->sort_order
;
4213 return (SCNetworkInterfaceRef
)parentPrivate
;
4217 CFRelease(parentPrivate
);
4218 _SCErrorSet(kSCStatusInvalidArgument
);
4225 __SCNetworkInterfaceGetDefaultConfiguration(SCNetworkSetRef set
, SCNetworkInterfaceRef interface
)
4227 CFDictionaryRef config
= NULL
;
4228 CFStringRef defaultType
;
4229 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
4231 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
4232 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
4234 defaultType
= __SCNetworkInterfaceGetDefaultConfigurationType(interface
);
4235 if (defaultType
!= NULL
) {
4239 path
= SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL
, // allocator
4240 SCNetworkSetGetSetID(set
), // set
4241 interfacePrivate
->entity_device
, // interface
4242 defaultType
); // entity
4244 config
= __getPrefsConfiguration(interfacePrivate
->prefs
, path
);
4247 if (config
== NULL
) {
4248 // if the "set" does not have a saved configuration, use
4249 // the [template] "interface" configuration
4250 if (interfacePrivate
->unsaved
!= NULL
) {
4251 config
= CFDictionaryGetValue(interfacePrivate
->unsaved
, defaultType
);
4252 if (config
== (CFDictionaryRef
)kCFNull
) {
4257 if (isA_CFDictionary(config
) && (CFDictionaryGetCount(config
) == 0)) {
4268 static CFDictionaryRef
4269 __SCNetworkInterfaceGetConfiguration(SCNetworkInterfaceRef interface
,
4270 CFStringRef extendedType
)
4272 CFDictionaryRef config
= NULL
;
4273 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
4276 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
4277 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
4279 paths
= copyConfigurationPaths(interfacePrivate
, extendedType
);
4280 if (paths
!= NULL
) {
4283 path
= CFArrayGetValueAtIndex(paths
, 0);
4284 config
= __getPrefsConfiguration(interfacePrivate
->prefs
, path
);
4288 if (interfacePrivate
->unsaved
!= NULL
) {
4289 config
= CFDictionaryGetValue(interfacePrivate
->unsaved
, extendedType
);
4290 if (config
== (CFDictionaryRef
)kCFNull
) {
4296 if (isA_CFDictionary(config
) && (CFDictionaryGetCount(config
) == 0)) {
4305 SCNetworkInterfaceGetConfiguration(SCNetworkInterfaceRef interface
)
4307 CFDictionaryRef config
;
4308 CFStringRef defaultType
;
4310 if (!isA_SCNetworkInterface(interface
)) {
4311 _SCErrorSet(kSCStatusInvalidArgument
);
4315 defaultType
= __SCNetworkInterfaceGetDefaultConfigurationType(interface
);
4316 if (defaultType
== NULL
) {
4320 config
= __SCNetworkInterfaceGetConfiguration(interface
, defaultType
);
4321 if (config
== NULL
) {
4322 if (CFEqual(defaultType
, kSCEntNetAirPort
)) {
4323 SCNetworkInterfacePrivateRef interfacePrivate
;
4326 // if AirPort interface, check for a per-service config
4327 interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
4328 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
4329 interfacePrivate
->serviceID
, // service
4330 kSCEntNetAirPort
); // entity
4331 config
= __getPrefsConfiguration(interfacePrivate
->prefs
, path
);
4335 if (config
== NULL
) {
4336 _SCErrorSet(kSCStatusOK
);
4344 SCNetworkInterfaceGetExtendedConfiguration(SCNetworkInterfaceRef interface
,
4345 CFStringRef extendedType
)
4347 CFDictionaryRef config
;
4349 if (!isA_SCNetworkInterface(interface
)) {
4350 _SCErrorSet(kSCStatusInvalidArgument
);
4354 if (!__SCNetworkInterfaceIsValidExtendedConfigurationType(interface
, extendedType
, TRUE
)) {
4355 _SCErrorSet(kSCStatusInvalidArgument
);
4359 config
= __SCNetworkInterfaceGetConfiguration(interface
, extendedType
);
4360 if (config
== NULL
) {
4361 _SCErrorSet(kSCStatusOK
);
4369 SCNetworkInterfaceGetBSDName(SCNetworkInterfaceRef interface
)
4371 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
4373 if (!isA_SCNetworkInterface(interface
)) {
4374 _SCErrorSet(kSCStatusInvalidArgument
);
4378 if ((interfacePrivate
->interface
!= NULL
) &&
4379 (interfacePrivate
->interface
!= kSCNetworkInterfaceIPv4
)) {
4380 _SCErrorSet(kSCStatusOK
);
4384 return interfacePrivate
->entity_device
;
4389 SCNetworkInterfaceGetHardwareAddressString(SCNetworkInterfaceRef interface
)
4391 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
4393 if (!isA_SCNetworkInterface(interface
)) {
4394 _SCErrorSet(kSCStatusInvalidArgument
);
4398 if ((interfacePrivate
->address
!= NULL
) &&
4399 (interfacePrivate
->addressString
== NULL
)) {
4403 char mac
[sizeof("xx:xx:xx:xx:xx:xx:xx:xx")];
4406 bp
= (uint8_t *)CFDataGetBytePtr(interfacePrivate
->address
);
4407 n
= CFDataGetLength(interfacePrivate
->address
) * 3;
4409 if (n
> sizeof(mac
)) {
4410 mac_p
= CFAllocatorAllocate(NULL
, 0, n
);
4413 for (cp
= mac_p
; n
> 0; n
-= 3) {
4414 cp
+= snprintf(cp
, n
, "%2.2x:", *bp
++);
4417 interfacePrivate
->addressString
= CFStringCreateWithCString(NULL
, mac_p
, kCFStringEncodingUTF8
);
4418 if (mac_p
!= mac
) CFAllocatorDeallocate(NULL
, mac_p
);
4421 return interfacePrivate
->addressString
;
4425 SCNetworkInterfaceRef
4426 SCNetworkInterfaceGetInterface(SCNetworkInterfaceRef interface
)
4428 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
4430 if (!isA_SCNetworkInterface(interface
)) {
4431 _SCErrorSet(kSCStatusInvalidArgument
);
4435 return interfacePrivate
->interface
;
4440 SCNetworkInterfaceGetInterfaceType(SCNetworkInterfaceRef interface
)
4442 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
4444 if (!isA_SCNetworkInterface(interface
)) {
4445 _SCErrorSet(kSCStatusInvalidArgument
);
4449 return interfacePrivate
->interface_type
;
4454 copy_interface_string(CFBundleRef bundle
, CFStringRef key
, Boolean localized
)
4456 CFStringRef str
= NULL
;
4459 str
= CFBundleCopyLocalizedString(bundle
,
4462 NETWORKINTERFACE_LOCALIZATIONS
);
4464 str
= _SC_CFBundleCopyNonLocalizedString(bundle
,
4467 NETWORKINTERFACE_LOCALIZATIONS
);
4475 copy_display_name(SCNetworkInterfaceRef interface
, Boolean localized
, Boolean oldLocalization
)
4477 CFMutableStringRef local
;
4480 local
= CFStringCreateMutable(NULL
, 0);
4482 while (interface
!= NULL
) {
4483 Boolean added
= FALSE
;
4484 SCNetworkInterfaceRef child
= NULL
;
4485 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
4487 if ((interfacePrivate
->interface
!= NULL
) &&
4488 (interfacePrivate
->interface
!= kSCNetworkInterfaceIPv4
) &&
4489 !CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeVPN
)) {
4490 child
= interfacePrivate
->interface
;
4493 if ((bundle
!= NULL
) && (interfacePrivate
->localized_key
!= NULL
)) {
4495 CFStringRef key
= interfacePrivate
->localized_key
;
4497 if (oldLocalization
) {
4498 key
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("X-%@"),
4499 interfacePrivate
->localized_key
);
4501 fmt
= copy_interface_string(bundle
, key
, localized
);
4503 CFStringAppendFormat(local
,
4506 interfacePrivate
->localized_arg1
,
4507 interfacePrivate
->localized_arg2
);
4511 if (oldLocalization
) {
4517 (interfacePrivate
->prefs
!= NULL
) &&
4518 (interfacePrivate
->serviceID
!= NULL
) &&
4520 CFDictionaryRef entity
;
4523 // check for (and use) the name of the interface when it
4524 // was last available
4525 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
,
4526 interfacePrivate
->serviceID
,
4527 kSCEntNetInterface
);
4528 entity
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
4530 if (isA_CFDictionary(entity
)) {
4533 name
= CFDictionaryGetValue(entity
, kSCPropUserDefinedName
);
4534 if (isA_CFString(name
)) {
4535 CFStringAppend(local
, name
);
4542 // create (non-)localized name based on the interface type
4543 CFStringAppend(local
, interfacePrivate
->interface_type
);
4545 // ... and, if this is a leaf node, the interface device
4546 if ((interfacePrivate
->entity_device
!= NULL
) && (child
== NULL
)) {
4547 CFStringAppendFormat(local
, NULL
, CFSTR(" (%@)"), interfacePrivate
->entity_device
);
4551 if (child
!= NULL
) {
4552 // if this interface is layered over another
4553 CFStringAppend(local
, CFSTR(" --> "));
4559 name
= CFStringCreateCopy(NULL
, local
);
4566 #if !TARGET_OS_EMBEDDED && !TARGET_IPHONE_SIMULATOR
4569 __SCNetworkInterfaceCopyXLocalizedDisplayName(SCNetworkInterfaceRef interface
)
4573 if (!isA_SCNetworkInterface(interface
)) {
4574 _SCErrorSet(kSCStatusInvalidArgument
);
4578 name
= copy_display_name(interface
, TRUE
, TRUE
);
4585 __SCNetworkInterfaceCopyXNonLocalizedDisplayName(SCNetworkInterfaceRef interface
)
4587 CFStringRef localized_name
;
4589 if (!isA_SCNetworkInterface(interface
)) {
4590 _SCErrorSet(kSCStatusInvalidArgument
);
4594 localized_name
= copy_display_name(interface
, FALSE
, TRUE
);
4595 return localized_name
;
4597 #endif // !TARGET_OS_EMBEDDED && !TARGET_IPHONE_SIMULATOR
4602 __SCNetworkInterfaceGetNonLocalizedDisplayName(SCNetworkInterfaceRef interface
)
4604 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
4606 if (!isA_SCNetworkInterface(interface
)) {
4607 _SCErrorSet(kSCStatusInvalidArgument
);
4611 if (interfacePrivate
->name
== NULL
) {
4612 interfacePrivate
->name
= copy_display_name(interface
, FALSE
, FALSE
);
4615 return interfacePrivate
->name
;
4620 SCNetworkInterfaceGetLocalizedDisplayName(SCNetworkInterfaceRef interface
)
4622 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
4624 if (!isA_SCNetworkInterface(interface
)) {
4625 _SCErrorSet(kSCStatusInvalidArgument
);
4629 if (interfacePrivate
->localized_name
== NULL
) {
4630 interfacePrivate
->localized_name
= copy_display_name(interface
, TRUE
, FALSE
);
4633 return interfacePrivate
->localized_name
;
4639 __SCNetworkInterfaceGetTemplateOverrides(SCNetworkInterfaceRef interface
, CFStringRef overrideType
)
4641 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
4642 CFDictionaryRef overrides
= NULL
;
4644 if (interfacePrivate
->overrides
!= NULL
) {
4645 overrides
= CFDictionaryGetValue(interfacePrivate
->overrides
, overrideType
);
4653 SCNetworkInterfaceGetTypeID(void)
4655 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
); /* initialize runtime */
4656 return __kSCNetworkInterfaceTypeID
;
4662 __SCNetworkInterfaceSetDefaultConfiguration(SCNetworkSetRef set
,
4663 SCNetworkInterfaceRef interface
,
4664 CFStringRef defaultType
,
4665 CFDictionaryRef config
,
4668 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
4671 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
4672 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
4674 if (defaultType
== NULL
) {
4675 defaultType
= __SCNetworkInterfaceGetDefaultConfigurationType(interface
);
4676 if (defaultType
== NULL
) {
4681 if (isA_CFDictionary(config
) && (CFDictionaryGetCount(config
) == 0)) {
4688 path
= SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL
, // allocator
4689 SCNetworkSetGetSetID(set
), // set
4690 interfacePrivate
->entity_device
, // interface
4691 defaultType
); // entity
4693 ok
= __setPrefsConfiguration(interfacePrivate
->prefs
, path
, config
, FALSE
);
4696 // if configuration has been saved
4697 if (interfacePrivate
->unsaved
!= NULL
) {
4698 CFDictionaryRemoveValue(interfacePrivate
->unsaved
, defaultType
);
4699 if (CFDictionaryGetCount(interfacePrivate
->unsaved
) == 0) {
4700 CFRelease(interfacePrivate
->unsaved
);
4701 interfacePrivate
->unsaved
= NULL
;
4707 if (config
== NULL
) {
4708 // remember that we are clearing the configuration
4709 config
= (CFDictionaryRef
)kCFNull
;
4712 if (interfacePrivate
->unsaved
== NULL
) {
4713 interfacePrivate
->unsaved
= CFDictionaryCreateMutable(NULL
,
4715 &kCFTypeDictionaryKeyCallBacks
,
4716 &kCFTypeDictionaryValueCallBacks
);
4718 CFDictionarySetValue(interfacePrivate
->unsaved
, defaultType
, config
);
4721 _SCErrorSet(kSCStatusNoKey
);
4732 __SCNetworkInterfaceSetConfiguration(SCNetworkInterfaceRef interface
,
4733 CFStringRef extendedType
,
4734 CFDictionaryRef config
,
4737 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
4741 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
4742 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
4744 if (extendedType
== NULL
) {
4745 extendedType
= __SCNetworkInterfaceGetDefaultConfigurationType(interface
);
4746 if (extendedType
== NULL
) {
4751 if (isA_CFDictionary(config
) && (CFDictionaryGetCount(config
) == 0)) {
4755 paths
= copyConfigurationPaths(interfacePrivate
, extendedType
);
4756 if (paths
!= NULL
) {
4760 n
= CFArrayGetCount(paths
);
4761 for (i
= 0; i
< n
; i
++) {
4764 path
= CFArrayGetValueAtIndex(paths
, i
);
4765 ok
= __setPrefsConfiguration(interfacePrivate
->prefs
, path
, config
, FALSE
);
4772 // if configuration has been saved
4773 if (interfacePrivate
->unsaved
!= NULL
) {
4774 CFDictionaryRemoveValue(interfacePrivate
->unsaved
, extendedType
);
4775 if (CFDictionaryGetCount(interfacePrivate
->unsaved
) == 0) {
4776 CFRelease(interfacePrivate
->unsaved
);
4777 interfacePrivate
->unsaved
= NULL
;
4785 if (config
== NULL
) {
4786 // remember that we are clearing the configuration
4787 config
= (CFDictionaryRef
)kCFNull
;
4790 if (interfacePrivate
->unsaved
== NULL
) {
4791 interfacePrivate
->unsaved
= CFDictionaryCreateMutable(NULL
,
4793 &kCFTypeDictionaryKeyCallBacks
,
4794 &kCFTypeDictionaryValueCallBacks
);
4796 CFDictionarySetValue(interfacePrivate
->unsaved
, extendedType
, config
);
4799 _SCErrorSet(kSCStatusNoKey
);
4808 SCNetworkInterfaceSetConfiguration(SCNetworkInterfaceRef interface
, CFDictionaryRef config
)
4810 CFStringRef defaultType
;
4812 if (!isA_SCNetworkInterface(interface
)) {
4813 _SCErrorSet(kSCStatusInvalidArgument
);
4817 defaultType
= __SCNetworkInterfaceGetDefaultConfigurationType(interface
);
4818 if (defaultType
== NULL
) {
4822 return __SCNetworkInterfaceSetConfiguration(interface
, defaultType
, config
, FALSE
);
4827 SCNetworkInterfaceSetExtendedConfiguration(SCNetworkInterfaceRef interface
,
4828 CFStringRef extendedType
,
4829 CFDictionaryRef config
)
4831 if (!isA_SCNetworkInterface(interface
)) {
4832 _SCErrorSet(kSCStatusInvalidArgument
);
4836 if (!__SCNetworkInterfaceIsValidExtendedConfigurationType(interface
, extendedType
, TRUE
)) {
4840 return __SCNetworkInterfaceSetConfiguration(interface
, extendedType
, config
, FALSE
);
4845 #pragma mark SCNetworkInterface [Refresh Configuration] API
4848 #ifndef kSCEntNetRefreshConfiguration
4849 #define kSCEntNetRefreshConfiguration CFSTR("RefreshConfiguration")
4850 #endif // kSCEntNetRefreshConfiguration
4853 _SCNetworkInterfaceForceConfigurationRefresh(CFStringRef ifName
)
4858 if (!isA_CFString(ifName
)) {
4859 _SCErrorSet(kSCStatusInvalidArgument
);
4863 key
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
,
4864 kSCDynamicStoreDomainState
,
4866 kSCEntNetRefreshConfiguration
);
4867 ok
= SCDynamicStoreNotifyValue(NULL
, key
);
4874 __SCNetworkInterfaceForceConfigurationRefresh_helper(SCPreferencesRef prefs
, CFStringRef ifName
)
4876 CFDataRef data
= NULL
;
4878 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
4879 uint32_t status
= kSCStatusOK
;
4880 CFDataRef reply
= NULL
;
4882 if (prefsPrivate
->helper_port
== MACH_PORT_NULL
) {
4883 ok
= __SCPreferencesCreate_helper(prefs
);
4889 // serialize the interface name
4890 ok
= _SCSerializeString(ifName
, &data
, NULL
, NULL
);
4895 // have the helper "refresh" the configuration
4896 status
= kSCStatusOK
;
4898 ok
= _SCHelperExec(prefsPrivate
->helper_port
,
4899 SCHELPER_MSG_INTERFACE_REFRESH
,
4903 if (data
!= NULL
) CFRelease(data
);
4908 if (status
!= kSCStatusOK
) {
4917 if (prefsPrivate
->helper_port
!= MACH_PORT_NULL
) {
4918 _SCHelperClose(&prefsPrivate
->helper_port
);
4921 status
= kSCStatusAccessError
;
4926 _SCErrorSet(status
);
4932 SCNetworkInterfaceForceConfigurationRefresh(SCNetworkInterfaceRef interface
)
4935 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
4937 if (!isA_SCNetworkInterface(interface
)) {
4938 _SCErrorSet(kSCStatusInvalidArgument
);
4942 ifName
= SCNetworkInterfaceGetBSDName(interface
);
4943 if (ifName
== NULL
) {
4944 _SCErrorSet(kSCStatusInvalidArgument
);
4948 if (interfacePrivate
->prefs
!= NULL
) {
4949 SCPreferencesRef prefs
= interfacePrivate
->prefs
;
4950 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
4952 if (prefsPrivate
->authorizationData
!= NULL
) {
4953 return __SCNetworkInterfaceForceConfigurationRefresh_helper(prefs
, ifName
);
4957 return _SCNetworkInterfaceForceConfigurationRefresh(ifName
);
4962 SCNetworkInterfaceRefreshConfiguration(CFStringRef ifName
)
4964 return _SCNetworkInterfaceForceConfigurationRefresh(ifName
);
4969 #pragma mark SCNetworkInterface Password APIs
4973 getPasswordID(CFDictionaryRef config
, CFStringRef serviceID
)
4975 CFStringRef unique_id
= NULL
;
4977 if (config
!= NULL
) {
4978 CFStringRef encryption
;
4980 encryption
= CFDictionaryGetValue(config
, kSCPropNetPPPAuthPasswordEncryption
);
4981 if (isA_CFString(encryption
) &&
4982 CFEqual(encryption
, kSCValNetPPPAuthPasswordEncryptionKeychain
)) {
4983 unique_id
= CFDictionaryGetValue(config
, kSCPropNetPPPAuthPassword
);
4986 if (unique_id
== NULL
) {
4987 unique_id
= serviceID
;
4995 copySharedSecretID(CFDictionaryRef config
, CFStringRef serviceID
)
4997 CFMutableStringRef shared_id
= NULL
;
4999 if (config
!= NULL
) {
5000 CFStringRef encryption
;
5002 encryption
= CFDictionaryGetValue(config
, kSCPropNetIPSecSharedSecretEncryption
);
5003 if (isA_CFString(encryption
) &&
5004 CFEqual(encryption
, kSCValNetIPSecSharedSecretEncryptionKeychain
)) {
5005 shared_id
= (CFMutableStringRef
)CFDictionaryGetValue(config
, kSCPropNetIPSecSharedSecret
);
5006 if (shared_id
!= NULL
) {
5007 CFRetain(shared_id
);
5012 if (shared_id
== NULL
) {
5013 CFStringRef unique_id
;
5015 unique_id
= getPasswordID(config
, serviceID
);
5016 shared_id
= CFStringCreateMutableCopy(NULL
, 0, unique_id
);
5017 CFStringAppend(shared_id
, CFSTR(".SS"));
5025 copyXAuthID(CFDictionaryRef config
, CFStringRef serviceID
)
5027 CFMutableStringRef xauth_id
= NULL
;
5029 if (config
!= NULL
) {
5030 CFStringRef encryption
;
5032 encryption
= CFDictionaryGetValue(config
, kSCPropNetIPSecXAuthPasswordEncryption
);
5033 if (isA_CFString(encryption
) &&
5034 CFEqual(encryption
, kSCValNetIPSecXAuthPasswordEncryptionKeychain
)) {
5035 xauth_id
= (CFMutableStringRef
)CFDictionaryGetValue(config
, kSCPropNetIPSecXAuthPassword
);
5036 if (xauth_id
!= NULL
) {
5042 if (xauth_id
== NULL
) {
5043 CFStringRef unique_id
;
5045 unique_id
= getPasswordID(config
, serviceID
);
5046 xauth_id
= CFStringCreateMutableCopy(NULL
, 0, unique_id
);
5047 CFStringAppend(xauth_id
, CFSTR(".XAUTH"));
5055 checkInterfacePassword(SCNetworkInterfaceRef interface
,
5056 SCNetworkInterfacePasswordType passwordType
,
5057 SCPreferencesRef
*prefs
,
5058 CFStringRef
*serviceID
)
5060 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
5062 if (!isA_SCNetworkInterface(interface
)) {
5066 *serviceID
= interfacePrivate
->serviceID
;
5067 if (*serviceID
== NULL
) {
5071 *prefs
= interfacePrivate
->prefs
;
5072 if (*prefs
== NULL
) {
5076 switch (passwordType
) {
5077 case kSCNetworkInterfacePasswordTypePPP
: {
5078 CFStringRef interfaceType
;
5080 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
5081 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
)) {
5089 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret
: {
5090 CFStringRef interfaceType
;
5092 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
5093 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
)) {
5094 interface
= SCNetworkInterfaceGetInterface(interface
);
5095 if (interface
!= NULL
) {
5096 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
5097 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeL2TP
)) {
5098 // if PPP->L2TP interface
5102 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeIPSec
)) {
5103 // if IPSec interface
5110 case kSCNetworkInterfacePasswordTypeEAPOL
: {
5114 case kSCNetworkInterfacePasswordTypeIPSecXAuth
: {
5115 CFStringRef interfaceType
;
5117 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
5118 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeIPSec
)) {
5119 // if IPSec interface
5126 case kSCNetworkInterfacePasswordTypeVPN
: {
5127 CFStringRef interfaceType
;
5129 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
5130 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeVPN
)) {
5146 _SCErrorSet(kSCStatusInvalidArgument
);
5152 SCNetworkInterfaceCheckPassword(SCNetworkInterfaceRef interface
,
5153 SCNetworkInterfacePasswordType passwordType
)
5155 Boolean exists
= FALSE
;
5156 SCPreferencesRef prefs
= NULL
;
5157 CFStringRef serviceID
= NULL
;
5159 if (!checkInterfacePassword(interface
, passwordType
, &prefs
, &serviceID
)) {
5163 switch (passwordType
) {
5164 case kSCNetworkInterfacePasswordTypePPP
: {
5165 CFDictionaryRef config
;
5166 CFStringRef unique_id
;
5168 // get configuration
5169 config
= SCNetworkInterfaceGetConfiguration(interface
);
5172 unique_id
= getPasswordID(config
, serviceID
);
5175 exists
= __extract_password(prefs
,
5177 kSCPropNetPPPAuthPassword
,
5178 kSCPropNetPPPAuthPasswordEncryption
,
5179 kSCValNetPPPAuthPasswordEncryptionKeychain
,
5185 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret
: {
5186 CFDictionaryRef config
;
5188 CFStringRef shared_id
;
5190 // get configuration
5191 extended
= CFEqual(SCNetworkInterfaceGetInterfaceType(interface
), kSCNetworkInterfaceTypePPP
);
5193 config
= SCNetworkInterfaceGetExtendedConfiguration(interface
, kSCEntNetIPSec
);
5195 config
= SCNetworkInterfaceGetConfiguration(interface
);
5198 // get sharedSecret ID
5199 shared_id
= copySharedSecretID(config
, serviceID
);
5202 exists
= __extract_password(prefs
,
5204 kSCPropNetIPSecSharedSecret
,
5205 kSCPropNetIPSecSharedSecretEncryption
,
5206 kSCValNetIPSecSharedSecretEncryptionKeychain
,
5209 CFRelease(shared_id
);
5213 case kSCNetworkInterfacePasswordTypeEAPOL
: {
5214 CFDictionaryRef config
;
5215 CFStringRef unique_id
= NULL
;
5217 // get configuration
5218 config
= SCNetworkInterfaceGetExtendedConfiguration(interface
, kSCEntNetEAPOL
);
5220 // get 802.1X identifier
5221 if (config
!= NULL
) {
5222 unique_id
= CFDictionaryGetValue(config
, kEAPClientPropUserPasswordKeychainItemID
);
5224 if (!isA_CFString(unique_id
)) {
5229 exists
= _SCPreferencesSystemKeychainPasswordItemExists(prefs
, unique_id
);
5233 case kSCNetworkInterfacePasswordTypeIPSecXAuth
: {
5234 CFDictionaryRef config
;
5235 CFStringRef xauth_id
;
5237 // get configuration
5238 config
= SCNetworkInterfaceGetConfiguration(interface
);
5241 xauth_id
= copyXAuthID(config
, serviceID
);
5244 exists
= __extract_password(prefs
,
5246 kSCPropNetIPSecXAuthPassword
,
5247 kSCPropNetIPSecXAuthPasswordEncryption
,
5248 kSCValNetIPSecXAuthPasswordEncryptionKeychain
,
5251 CFRelease(xauth_id
);
5255 case kSCNetworkInterfacePasswordTypeVPN
: {
5256 CFDictionaryRef config
;
5259 // get configuration
5260 config
= SCNetworkInterfaceGetConfiguration(interface
);
5263 vpn_id
= getPasswordID(config
, serviceID
);
5266 exists
= __extract_password(prefs
,
5268 kSCPropNetVPNAuthPassword
,
5269 kSCPropNetVPNAuthPasswordEncryption
,
5270 kSCValNetVPNAuthPasswordEncryptionKeychain
,
5277 _SCErrorSet(kSCStatusInvalidArgument
);
5286 SCNetworkInterfaceCopyPassword(SCNetworkInterfaceRef interface
,
5287 SCNetworkInterfacePasswordType passwordType
)
5289 CFDataRef password
= NULL
;
5290 SCPreferencesRef prefs
= NULL
;
5291 CFStringRef serviceID
= NULL
;
5293 if (!checkInterfacePassword(interface
, passwordType
, &prefs
, &serviceID
)) {
5297 switch (passwordType
) {
5298 case kSCNetworkInterfacePasswordTypePPP
: {
5299 CFDictionaryRef config
;
5300 CFStringRef unique_id
;
5302 // get configuration
5303 config
= SCNetworkInterfaceGetConfiguration(interface
);
5306 unique_id
= getPasswordID(config
, serviceID
);
5309 (void) __extract_password(prefs
,
5311 kSCPropNetPPPAuthPassword
,
5312 kSCPropNetPPPAuthPasswordEncryption
,
5313 kSCValNetPPPAuthPasswordEncryptionKeychain
,
5319 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret
: {
5320 CFDictionaryRef config
;
5322 CFStringRef shared_id
;
5324 // get configuration
5325 extended
= CFEqual(SCNetworkInterfaceGetInterfaceType(interface
), kSCNetworkInterfaceTypePPP
);
5327 config
= SCNetworkInterfaceGetExtendedConfiguration(interface
, kSCEntNetIPSec
);
5329 config
= SCNetworkInterfaceGetConfiguration(interface
);
5332 // get sharedSecret ID
5333 shared_id
= copySharedSecretID(config
, serviceID
);
5336 (void) __extract_password(prefs
,
5338 kSCPropNetIPSecSharedSecret
,
5339 kSCPropNetIPSecSharedSecretEncryption
,
5340 kSCValNetIPSecSharedSecretEncryptionKeychain
,
5344 CFRelease(shared_id
);
5348 case kSCNetworkInterfacePasswordTypeEAPOL
: {
5349 CFDictionaryRef config
;
5350 CFStringRef unique_id
= NULL
;
5352 // get configuration
5353 config
= SCNetworkInterfaceGetExtendedConfiguration(interface
, kSCEntNetEAPOL
);
5355 // get 802.1X identifier
5356 if (config
!= NULL
) {
5357 unique_id
= CFDictionaryGetValue(config
, kEAPClientPropUserPasswordKeychainItemID
);
5359 if (!isA_CFString(unique_id
)) {
5360 _SCErrorSet(kSCStatusFailed
);
5365 password
= _SCPreferencesSystemKeychainPasswordItemCopy(prefs
, unique_id
);
5369 case kSCNetworkInterfacePasswordTypeIPSecXAuth
: {
5370 CFDictionaryRef config
;
5371 CFStringRef xauth_id
;
5373 // get configuration
5374 config
= SCNetworkInterfaceGetConfiguration(interface
);
5377 xauth_id
= copyXAuthID(config
, serviceID
);
5380 (void) __extract_password(prefs
,
5382 kSCPropNetIPSecXAuthPassword
,
5383 kSCPropNetIPSecXAuthPasswordEncryption
,
5384 kSCValNetIPSecXAuthPasswordEncryptionKeychain
,
5387 CFRelease(xauth_id
);
5391 case kSCNetworkInterfacePasswordTypeVPN
: {
5392 CFDictionaryRef config
;
5395 // get configuration
5396 config
= SCNetworkInterfaceGetConfiguration(interface
);
5399 vpn_id
= getPasswordID(config
, serviceID
);
5402 (void) __extract_password(prefs
,
5404 kSCPropNetVPNAuthPassword
,
5405 kSCPropNetVPNAuthPasswordEncryption
,
5406 kSCValNetVPNAuthPasswordEncryptionKeychain
,
5413 _SCErrorSet(kSCStatusInvalidArgument
);
5422 SCNetworkInterfaceRemovePassword(SCNetworkInterfaceRef interface
,
5423 SCNetworkInterfacePasswordType passwordType
)
5426 SCPreferencesRef prefs
= NULL
;
5427 CFStringRef serviceID
= NULL
;
5429 if (!checkInterfacePassword(interface
, passwordType
, &prefs
, &serviceID
)) {
5433 switch (passwordType
) {
5434 case kSCNetworkInterfacePasswordTypePPP
: {
5435 CFDictionaryRef config
;
5436 CFDictionaryRef newConfig
= NULL
;
5437 CFStringRef unique_id
;
5439 // get configuration
5440 config
= SCNetworkInterfaceGetConfiguration(interface
);
5443 unique_id
= getPasswordID(config
, serviceID
);
5446 ok
= __remove_password(prefs
,
5448 kSCPropNetPPPAuthPassword
,
5449 kSCPropNetPPPAuthPasswordEncryption
,
5450 kSCValNetPPPAuthPasswordEncryptionKeychain
,
5454 ok
= SCNetworkInterfaceSetConfiguration(interface
, newConfig
);
5455 if (newConfig
!= NULL
) CFRelease(newConfig
);
5461 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret
: {
5462 CFDictionaryRef config
;
5464 CFDictionaryRef newConfig
= NULL
;
5465 CFStringRef shared_id
;
5467 // get configuration
5468 extended
= CFEqual(SCNetworkInterfaceGetInterfaceType(interface
), kSCNetworkInterfaceTypePPP
);
5470 config
= SCNetworkInterfaceGetExtendedConfiguration(interface
, kSCEntNetIPSec
);
5472 config
= SCNetworkInterfaceGetConfiguration(interface
);
5475 // get sharedSecret ID
5476 shared_id
= copySharedSecretID(config
, serviceID
);
5479 ok
= __remove_password(prefs
,
5481 kSCPropNetIPSecSharedSecret
,
5482 kSCPropNetIPSecSharedSecretEncryption
,
5483 kSCValNetIPSecSharedSecretEncryptionKeychain
,
5488 ok
= SCNetworkInterfaceSetExtendedConfiguration(interface
,
5492 ok
= SCNetworkInterfaceSetConfiguration(interface
,
5495 if (newConfig
!= NULL
) CFRelease(newConfig
);
5498 CFRelease(shared_id
);
5502 case kSCNetworkInterfacePasswordTypeEAPOL
: {
5503 CFDictionaryRef config
;
5504 CFStringRef unique_id
= NULL
;
5506 // get configuration
5507 config
= SCNetworkInterfaceGetExtendedConfiguration(interface
, kSCEntNetEAPOL
);
5509 // get 802.1X identifier
5510 if (config
!= NULL
) {
5511 unique_id
= CFDictionaryGetValue(config
, kEAPClientPropUserPasswordKeychainItemID
);
5513 if (!isA_CFString(unique_id
)) {
5514 _SCErrorSet(kSCStatusFailed
);
5519 ok
= _SCPreferencesSystemKeychainPasswordItemRemove(prefs
, unique_id
);
5523 case kSCNetworkInterfacePasswordTypeIPSecXAuth
: {
5524 CFDictionaryRef config
;
5525 CFDictionaryRef newConfig
= NULL
;
5526 CFStringRef xauth_id
;
5528 // get configuration
5529 config
= SCNetworkInterfaceGetConfiguration(interface
);
5532 xauth_id
= copyXAuthID(config
, serviceID
);
5535 ok
= __remove_password(prefs
,
5537 kSCPropNetIPSecXAuthPassword
,
5538 kSCPropNetIPSecXAuthPasswordEncryption
,
5539 kSCValNetIPSecXAuthPasswordEncryptionKeychain
,
5543 ok
= SCNetworkInterfaceSetConfiguration(interface
, newConfig
);
5544 if (newConfig
!= NULL
) CFRelease(newConfig
);
5547 CFRelease(xauth_id
);
5551 case kSCNetworkInterfacePasswordTypeVPN
: {
5552 CFDictionaryRef config
;
5553 CFDictionaryRef newConfig
= NULL
;
5556 // get configuration
5557 config
= SCNetworkInterfaceGetConfiguration(interface
);
5560 vpn_id
= getPasswordID(config
, serviceID
);
5563 ok
= __remove_password(prefs
,
5565 kSCPropNetVPNAuthPassword
,
5566 kSCPropNetVPNAuthPasswordEncryption
,
5567 kSCValNetVPNAuthPasswordEncryptionKeychain
,
5571 ok
= SCNetworkInterfaceSetConfiguration(interface
, newConfig
);
5572 if (newConfig
!= NULL
) CFRelease(newConfig
);
5578 _SCErrorSet(kSCStatusInvalidArgument
);
5587 SCNetworkInterfaceSetPassword(SCNetworkInterfaceRef interface
,
5588 SCNetworkInterfacePasswordType passwordType
,
5590 CFDictionaryRef options
)
5592 CFStringRef account
= NULL
;
5593 CFDictionaryRef config
;
5594 CFStringRef description
= NULL
;
5595 CFStringRef label
= NULL
;
5597 SCPreferencesRef prefs
= NULL
;
5598 CFStringRef serviceID
= NULL
;
5600 if (!checkInterfacePassword(interface
, passwordType
, &prefs
, &serviceID
)) {
5604 switch (passwordType
) {
5605 case kSCNetworkInterfacePasswordTypePPP
: {
5606 SCNetworkServiceRef service
= NULL
;
5607 CFStringRef unique_id
;
5609 // get configuration
5610 config
= SCNetworkInterfaceGetConfiguration(interface
);
5613 unique_id
= getPasswordID(config
, serviceID
);
5615 // get "Account", "Name", "Kind"
5616 if (config
!= NULL
) {
5617 // auth name --> keychain "Account"
5618 account
= CFDictionaryGetValue(config
, kSCPropNetPPPAuthName
);
5620 // PPP [user defined] "name" --> keychain "Name"
5621 label
= CFDictionaryGetValue(config
, kSCPropUserDefinedName
);
5624 if (label
== NULL
) {
5625 // service name --> keychain "Name"
5626 service
= (SCNetworkServiceRef
)__SCNetworkServiceCreatePrivate(NULL
,
5631 label
= SCNetworkServiceGetName(service
);
5632 if (label
== NULL
) {
5633 // interface name --> keychain "Name"
5634 label
= SCNetworkInterfaceGetLocalizedDisplayName(interface
);
5638 if (bundle
!= NULL
) {
5639 // "PPP Password" --> keychain "Kind"
5640 description
= CFBundleCopyLocalizedString(bundle
,
5641 CFSTR("KEYCHAIN_KIND_PPP_PASSWORD"),
5642 CFSTR("PPP Password"),
5647 ok
= _SCPreferencesSystemKeychainPasswordItemSet(prefs
,
5649 (label
!= NULL
) ? label
: CFSTR("Network Connection"),
5650 (description
!= NULL
) ? description
: CFSTR("PPP Password"),
5655 CFMutableDictionaryRef newConfig
;
5657 if (config
!= NULL
) {
5658 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
5660 newConfig
= CFDictionaryCreateMutable(NULL
,
5662 &kCFTypeDictionaryKeyCallBacks
,
5663 &kCFTypeDictionaryValueCallBacks
);
5665 CFDictionarySetValue(newConfig
,
5666 kSCPropNetPPPAuthPassword
,
5668 CFDictionarySetValue(newConfig
,
5669 kSCPropNetPPPAuthPasswordEncryption
,
5670 kSCValNetPPPAuthPasswordEncryptionKeychain
);
5671 ok
= SCNetworkInterfaceSetConfiguration(interface
, newConfig
);
5672 CFRelease(newConfig
);
5675 if (description
!= NULL
) CFRelease(description
);
5676 if (service
!= NULL
) CFRelease(service
);
5680 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret
: {
5681 CFDictionaryRef baseConfig
= NULL
;
5683 SCNetworkServiceRef service
= NULL
;
5684 CFStringRef shared_id
;
5686 // get configuration
5687 extended
= CFEqual(SCNetworkInterfaceGetInterfaceType(interface
), kSCNetworkInterfaceTypePPP
);
5688 config
= SCNetworkInterfaceGetConfiguration(interface
);
5690 baseConfig
= config
;
5691 config
= SCNetworkInterfaceGetExtendedConfiguration(interface
, kSCEntNetIPSec
);
5694 // get sharedSecret ID
5695 shared_id
= copySharedSecretID(config
, serviceID
);
5697 // get "Account", "Name", "Kind"
5698 if (config
!= NULL
) {
5699 CFStringRef localIdentifier
;
5700 CFStringRef localIdentifierType
;
5702 if (CFDictionaryGetValueIfPresent(config
,
5703 kSCPropNetIPSecLocalIdentifierType
,
5704 (const void **)&localIdentifierType
)
5705 && CFEqual(localIdentifierType
, kSCValNetIPSecLocalIdentifierTypeKeyID
)
5706 && CFDictionaryGetValueIfPresent(config
,
5707 kSCPropNetIPSecLocalIdentifier
,
5708 (const void **)&localIdentifier
)
5709 && isA_CFString(localIdentifier
)) {
5710 // local identifier --> keychain "Account"
5711 account
= localIdentifier
;
5714 // PPP [user defined] "name" --> keychain "Name"
5716 label
= CFDictionaryGetValue(config
, kSCPropUserDefinedName
);
5718 if (baseConfig
!= NULL
) {
5719 label
= CFDictionaryGetValue(baseConfig
, kSCPropUserDefinedName
);
5724 if (label
== NULL
) {
5725 // service name --> keychain "Name"
5726 service
= (SCNetworkServiceRef
)__SCNetworkServiceCreatePrivate(NULL
,
5731 label
= SCNetworkServiceGetName(service
);
5732 if (label
== NULL
) {
5733 // interface name --> keychain "Name"
5734 label
= SCNetworkInterfaceGetLocalizedDisplayName(interface
);
5738 if (bundle
!= NULL
) {
5739 // "IPSec Shared Secret" --> keychain "Kind"
5740 description
= CFBundleCopyLocalizedString(bundle
,
5741 CFSTR("KEYCHAIN_KIND_IPSEC_SHARED_SECRET"),
5742 CFSTR("IPSec Shared Secret"),
5747 ok
= _SCPreferencesSystemKeychainPasswordItemSet(prefs
,
5749 (label
!= NULL
) ? label
: CFSTR("Network Connection"),
5750 (description
!= NULL
) ? description
: CFSTR("IPSec Shared Secret"),
5755 CFMutableDictionaryRef newConfig
= NULL
;
5757 if (config
!= NULL
) {
5758 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
5760 newConfig
= CFDictionaryCreateMutable(NULL
,
5762 &kCFTypeDictionaryKeyCallBacks
,
5763 &kCFTypeDictionaryValueCallBacks
);
5765 CFDictionarySetValue(newConfig
,
5766 kSCPropNetIPSecSharedSecret
,
5768 CFDictionarySetValue(newConfig
,
5769 kSCPropNetIPSecSharedSecretEncryption
,
5770 kSCValNetIPSecSharedSecretEncryptionKeychain
);
5772 ok
= SCNetworkInterfaceSetExtendedConfiguration(interface
,
5776 ok
= SCNetworkInterfaceSetConfiguration(interface
, newConfig
);
5778 CFRelease(newConfig
);
5781 if (description
!= NULL
) CFRelease(description
);
5782 if (service
!= NULL
) CFRelease(service
);
5783 CFRelease(shared_id
);
5787 case kSCNetworkInterfacePasswordTypeEAPOL
: {
5788 CFStringRef account
= NULL
;
5789 CFStringRef unique_id
= NULL
;
5791 // get configuration
5792 config
= SCNetworkInterfaceGetExtendedConfiguration(interface
, kSCEntNetEAPOL
);
5794 // get 802.1X identifier
5795 if (config
!= NULL
) {
5796 unique_id
= CFDictionaryGetValue(config
, kEAPClientPropUserPasswordKeychainItemID
);
5797 unique_id
= isA_CFString(unique_id
);
5799 if (unique_id
!= NULL
) {
5800 CFRetain(unique_id
);
5804 uuid
= CFUUIDCreate(NULL
);
5805 unique_id
= CFUUIDCreateString(NULL
, uuid
);
5809 // 802.1x UserName --> keychain "Account"
5810 if (config
!= NULL
) {
5811 account
= CFDictionaryGetValue(config
, kEAPClientPropUserName
);
5814 // get "Name", "Kind"
5815 if (bundle
!= NULL
) {
5816 CFStringRef interface_name
;
5818 // "Network Connection (%@)" --> keychain "Name"
5819 interface_name
= SCNetworkInterfaceGetLocalizedDisplayName(interface
);
5820 if (interface_name
!= NULL
) {
5821 CFStringRef label_fmt
;
5823 label_fmt
= CFBundleCopyLocalizedString(bundle
,
5824 CFSTR("KEYCHAIN_DESCRIPTION_EAPOL_INTERFACE"),
5825 CFSTR("Network Connection (%@)"),
5827 label
= CFStringCreateWithFormat(NULL
, NULL
, label_fmt
, interface_name
);
5828 CFRelease(label_fmt
);
5830 label
= CFBundleCopyLocalizedString(bundle
,
5831 CFSTR("KEYCHAIN_DESCRIPTION_EAPOL"),
5832 CFSTR("Network Connection"),
5836 // "802.1X Password" --> keychain "Kind"
5837 description
= CFBundleCopyLocalizedString(bundle
,
5838 CFSTR("KEYCHAIN_KIND_EAPOL"),
5839 CFSTR("802.1X Password"),
5844 ok
= _SCPreferencesSystemKeychainPasswordItemSet(prefs
,
5846 (label
!= NULL
) ? label
: CFSTR("Network Connection"),
5847 (description
!= NULL
) ? description
: CFSTR("802.1X Password"),
5852 CFMutableDictionaryRef newConfig
= NULL
;
5854 if (config
!= NULL
) {
5855 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
5857 newConfig
= CFDictionaryCreateMutable(NULL
,
5859 &kCFTypeDictionaryKeyCallBacks
,
5860 &kCFTypeDictionaryValueCallBacks
);
5862 CFDictionarySetValue(newConfig
,
5863 kEAPClientPropUserPasswordKeychainItemID
,
5865 ok
= SCNetworkInterfaceSetExtendedConfiguration(interface
,
5868 CFRelease(newConfig
);
5871 CFRelease(unique_id
);
5872 if (label
!= NULL
) CFRelease(label
);
5873 if (description
!= NULL
) CFRelease(description
);
5877 case kSCNetworkInterfacePasswordTypeIPSecXAuth
: {
5878 SCNetworkServiceRef service
= NULL
;
5879 CFStringRef xauth_id
;
5881 // get configuration
5882 config
= SCNetworkInterfaceGetConfiguration(interface
);
5885 xauth_id
= copyXAuthID(config
, serviceID
);
5887 // get "Account", "Name", "Kind"
5888 if (config
!= NULL
) {
5889 // auth name --> keychain "Account"
5890 account
= CFDictionaryGetValue(config
, kSCPropNetIPSecXAuthName
);
5892 // IPSec [user defined] "name" --> keychain "Name"
5893 label
= CFDictionaryGetValue(config
, kSCPropUserDefinedName
);
5896 if (label
== NULL
) {
5897 // service name --> keychain "Name"
5898 service
= (SCNetworkServiceRef
)__SCNetworkServiceCreatePrivate(NULL
,
5903 label
= SCNetworkServiceGetName(service
);
5904 if (label
== NULL
) {
5905 // interface name --> keychain "Name"
5906 label
= SCNetworkInterfaceGetLocalizedDisplayName(interface
);
5910 if (bundle
!= NULL
) {
5911 // "IPSec XAuth Password" --> keychain "Kind"
5912 description
= CFBundleCopyLocalizedString(bundle
,
5913 CFSTR("KEYCHAIN_KIND_IPSEC_XAUTH_PASSWORD"),
5914 CFSTR("IPSec XAuth Password"),
5919 ok
= _SCPreferencesSystemKeychainPasswordItemSet(prefs
,
5921 (label
!= NULL
) ? label
: CFSTR("Network Connection"),
5922 (description
!= NULL
) ? description
: CFSTR("IPSec XAuth Password"),
5927 CFMutableDictionaryRef newConfig
;
5929 if (config
!= NULL
) {
5930 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
5932 newConfig
= CFDictionaryCreateMutable(NULL
,
5934 &kCFTypeDictionaryKeyCallBacks
,
5935 &kCFTypeDictionaryValueCallBacks
);
5937 CFDictionarySetValue(newConfig
,
5938 kSCPropNetIPSecXAuthPassword
,
5940 CFDictionarySetValue(newConfig
,
5941 kSCPropNetIPSecXAuthPasswordEncryption
,
5942 kSCValNetIPSecXAuthPasswordEncryptionKeychain
);
5943 ok
= SCNetworkInterfaceSetConfiguration(interface
, newConfig
);
5944 CFRelease(newConfig
);
5947 CFRelease(xauth_id
);
5948 if (description
!= NULL
) CFRelease(description
);
5949 if (service
!= NULL
) CFRelease(service
);
5953 case kSCNetworkInterfacePasswordTypeVPN
: {
5954 SCNetworkServiceRef service
= NULL
;
5957 // get configuration
5958 config
= SCNetworkInterfaceGetConfiguration(interface
);
5961 vpn_id
= getPasswordID(config
, serviceID
);
5963 // get "Account", "Name", "Kind"
5964 if (config
!= NULL
) {
5965 // auth name --> keychain "Account"
5966 account
= CFDictionaryGetValue(config
, kSCPropNetVPNAuthName
);
5968 // VPN [user defined] "name" --> keychain "Name"
5969 label
= CFDictionaryGetValue(config
, kSCPropUserDefinedName
);
5972 if (label
== NULL
) {
5973 // service name --> keychain "Name"
5974 service
= (SCNetworkServiceRef
)__SCNetworkServiceCreatePrivate(NULL
,
5979 label
= SCNetworkServiceGetName(service
);
5980 if (label
== NULL
) {
5981 // interface name --> keychain "Name"
5982 label
= SCNetworkInterfaceGetLocalizedDisplayName(interface
);
5986 if (bundle
!= NULL
) {
5987 // "VPN Password" --> keychain "Kind"
5988 description
= CFBundleCopyLocalizedString(bundle
,
5989 CFSTR("KEYCHAIN_KIND_VPN_PASSWORD"),
5990 CFSTR("VPN Password"),
5995 ok
= _SCPreferencesSystemKeychainPasswordItemSet(prefs
,
5997 (label
!= NULL
) ? label
: CFSTR("Network Connection"),
5998 (description
!= NULL
) ? description
: CFSTR("VPN Password"),
6003 CFMutableDictionaryRef newConfig
;
6005 if (config
!= NULL
) {
6006 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
6008 newConfig
= CFDictionaryCreateMutable(NULL
,
6010 &kCFTypeDictionaryKeyCallBacks
,
6011 &kCFTypeDictionaryValueCallBacks
);
6013 CFDictionarySetValue(newConfig
,
6014 kSCPropNetVPNAuthPassword
,
6016 CFDictionarySetValue(newConfig
,
6017 kSCPropNetVPNAuthPasswordEncryption
,
6018 kSCValNetVPNAuthPasswordEncryptionKeychain
);
6019 ok
= SCNetworkInterfaceSetConfiguration(interface
, newConfig
);
6020 CFRelease(newConfig
);
6023 if (description
!= NULL
) CFRelease(description
);
6024 if (service
!= NULL
) CFRelease(service
);
6029 _SCErrorSet(kSCStatusInvalidArgument
);
6038 #pragma mark SCNetworkInterface [InterfaceNamer] SPIs
6042 _SCNetworkInterfaceCopyInterfaceInfo(SCNetworkInterfaceRef interface
)
6044 CFMutableDictionaryRef info
;
6045 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6048 info
= CFDictionaryCreateMutable(NULL
,
6050 &kCFTypeDictionaryKeyCallBacks
,
6051 &kCFTypeDictionaryValueCallBacks
);
6053 // add non-localized interface name
6054 name
= __SCNetworkInterfaceGetNonLocalizedDisplayName(interface
);
6056 CFDictionaryAddValue(info
, kSCPropUserDefinedName
, name
);
6060 if ((interfacePrivate
->usb
.vid
!= NULL
) || (interfacePrivate
->usb
.pid
!= NULL
)) {
6061 if (interfacePrivate
->usb
.name
!= NULL
) {
6062 CFDictionaryAddValue(info
, CFSTR(kUSBProductString
), interfacePrivate
->usb
.name
);
6064 if (interfacePrivate
->usb
.vid
!= NULL
) {
6065 CFDictionaryAddValue(info
, CFSTR(kUSBVendorID
), interfacePrivate
->usb
.vid
);
6067 if (interfacePrivate
->usb
.pid
!= NULL
) {
6068 CFDictionaryAddValue(info
, CFSTR(kUSBProductID
), interfacePrivate
->usb
.pid
);
6072 if (CFDictionaryGetCount(info
) == 0) {
6073 // do not return an empty dictionary
6082 SCNetworkInterfaceRef
6083 _SCNetworkInterfaceCreateWithIONetworkInterfaceObject(io_object_t if_obj
)
6085 SCNetworkInterfaceRef interface
= NULL
;
6087 /* initialize runtime */
6088 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
6090 if (IOObjectConformsTo(if_obj
, kIONetworkInterfaceClass
)) {
6091 interface
= createInterface(if_obj
, processNetworkInterface
);
6092 } else if (IOObjectConformsTo(if_obj
, kIOSerialBSDServiceValue
)) {
6093 interface
= createInterface(if_obj
, processSerialInterface
);
6101 _SCNetworkInterfaceGetConfigurationAction(SCNetworkInterfaceRef interface
)
6103 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6105 return interfacePrivate
->configurationAction
;
6110 _SCNetworkInterfaceGetHardwareAddress(SCNetworkInterfaceRef interface
)
6112 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6114 return interfacePrivate
->address
;
6119 _SCNetworkInterfaceGetIOInterfaceType(SCNetworkInterfaceRef interface
)
6121 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6123 return interfacePrivate
->type
;
6128 _SCNetworkInterfaceGetIOInterfaceUnit(SCNetworkInterfaceRef interface
)
6130 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6132 return interfacePrivate
->unit
;
6137 _SCNetworkInterfaceGetIOPath(SCNetworkInterfaceRef interface
)
6139 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6141 return interfacePrivate
->path
;
6146 _SCNetworkInterfaceGetIORegistryEntryID(SCNetworkInterfaceRef interface
)
6148 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6150 return interfacePrivate
->entryID
;
6155 _SCNetworkInterfaceIsBuiltin(SCNetworkInterfaceRef interface
)
6157 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6159 return interfacePrivate
->builtin
;
6164 #pragma mark SCNetworkInterface SPIs
6168 _SCNetworkInterfaceCopySlashDevPath(SCNetworkInterfaceRef interface
)
6170 io_registry_entry_t device
;
6171 io_iterator_t device_iterator
= MACH_PORT_NULL
;
6172 CFStringRef device_path
= NULL
;
6173 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6175 CFStringRef match_keys
[2];
6176 CFTypeRef match_vals
[2];
6177 CFDictionaryRef match_dict
;
6178 CFDictionaryRef matching
;
6180 if (interfacePrivate
->entity_device
== NULL
) {
6184 if (interfacePrivate
->entity_device_unique
== NULL
) {
6188 match_keys
[0] = CFSTR(kIOTTYBaseNameKey
);
6189 match_vals
[0] = interfacePrivate
->entity_device
;
6190 match_dict
= CFDictionaryCreate(NULL
,
6191 (const void **)match_keys
,
6192 (const void **)match_vals
,
6194 &kCFTypeDictionaryKeyCallBacks
,
6195 &kCFTypeDictionaryValueCallBacks
);
6197 match_keys
[0] = CFSTR(kIOProviderClassKey
);
6198 match_vals
[0] = CFSTR(kIOSerialBSDServiceValue
);
6199 match_keys
[1] = CFSTR(kIOPropertyMatchKey
);
6200 match_vals
[1] = match_dict
;
6201 matching
= CFDictionaryCreate(NULL
,
6202 (const void **)match_keys
,
6203 (const void **)match_vals
,
6204 sizeof(match_keys
)/sizeof(match_keys
[0]),
6205 &kCFTypeDictionaryKeyCallBacks
,
6206 &kCFTypeDictionaryValueCallBacks
);
6207 CFRelease(match_dict
);
6209 // note: this "matching" dictionary will be consumed by the call to IOServiceGetMatchingServices
6210 kr
= IOServiceGetMatchingServices(masterPort
, matching
, &device_iterator
);
6211 if (kr
!= kIOReturnSuccess
) {
6212 SCLog(TRUE
, LOG_DEBUG
, CFSTR("IOServiceGetMatchingServices() failed, kr = 0x%x"), kr
);
6216 while ((device_path
== NULL
) &&
6217 ((device
= IOIteratorNext(device_iterator
)) != MACH_PORT_NULL
)) {
6218 CFDictionaryRef overrides
;
6220 overrides
= IORegistryEntrySearchCFProperty(device
,
6222 kSCNetworkInterfaceNetworkConfigurationOverridesKey
,
6224 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
6225 if (overrides
!= NULL
) {
6226 CFDictionaryRef modemOverrides
;
6228 modemOverrides
= CFDictionaryGetValue(overrides
, kSCEntNetModem
);
6229 if (modemOverrides
!= NULL
) {
6230 CFRetain(modemOverrides
);
6232 CFRelease(overrides
);
6233 overrides
= modemOverrides
;
6235 if (overrides
== NULL
) {
6236 overrides
= IORegistryEntrySearchCFProperty(device
,
6238 CFSTR("DeviceModemOverrides"),
6240 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
6242 if (overrides
!= NULL
) {
6243 if (isA_CFDictionary(overrides
)) {
6244 CFStringRef matchIdentifier
;
6246 matchIdentifier
= CFDictionaryGetValue(overrides
, CFSTR("UniqueIdentifier"));
6247 if (isA_CFString(matchIdentifier
) &&
6248 CFEqual(interfacePrivate
->entity_device_unique
, matchIdentifier
)) {
6249 device_path
= IORegistryEntryCreateCFProperty(device
,
6250 CFSTR(kIOTTYDeviceKey
),
6255 CFRelease(overrides
);
6257 IOObjectRelease(device
);
6260 IOObjectRelease(device_iterator
);
6264 if (device_path
== NULL
) {
6265 // if we haven't found an exact match to our UniqueIdentifier
6266 // so we simply return the base name.
6267 device_path
= SCNetworkInterfaceGetBSDName(interface
);
6268 if (device_path
!= NULL
) {
6269 CFRetain(device_path
);
6278 _SCNetworkInterfaceIsBluetoothPAN(SCNetworkInterfaceRef interface
)
6280 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6282 return (interfacePrivate
->sort_order
== kSortBluetoothPAN_GN
);
6287 _SCNetworkInterfaceIsBluetoothPAN_NAP(SCNetworkInterfaceRef interface
)
6289 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6291 return (interfacePrivate
->sort_order
== kSortBluetoothPAN_NAP
);
6296 _SCNetworkInterfaceIsBluetoothP2P(SCNetworkInterfaceRef interface
)
6298 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6300 return (interfacePrivate
->sort_order
== kSortBluetoothPAN_U
);
6305 _SCNetworkInterfaceIsHiddenConfiguration(SCNetworkInterfaceRef interface
)
6307 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6309 return interfacePrivate
->hidden
;
6314 _SCNetworkInterfaceIsModemV92(SCNetworkInterfaceRef interface
)
6316 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6318 return interfacePrivate
->modemIsV92
;
6323 _SCNetworkInterfaceIsTethered(SCNetworkInterfaceRef interface
)
6325 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6327 return (interfacePrivate
->sort_order
== kSortTethered
);
6332 #pragma mark SCNetworkInterface [internal] SPIs
6336 SCNetworkInterfacePrivateRef
6337 __SCNetworkInterfaceCreateCopy(CFAllocatorRef allocator
,
6338 SCNetworkInterfaceRef interface
,
6339 SCPreferencesRef prefs
,
6340 CFStringRef serviceID
)
6342 SCNetworkInterfacePrivateRef oldPrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6343 SCNetworkInterfacePrivateRef newPrivate
;
6345 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
6346 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
6348 if (interface
== kSCNetworkInterfaceIPv4
) {
6349 return (SCNetworkInterfacePrivateRef
)CFRetain(interface
);
6352 newPrivate
= __SCNetworkInterfaceCreatePrivate(NULL
, NULL
, prefs
, serviceID
);
6353 newPrivate
->interface_type
= oldPrivate
->interface_type
;
6354 if (oldPrivate
->interface
!= NULL
) {
6355 newPrivate
->interface
= (SCNetworkInterfaceRef
)__SCNetworkInterfaceCreateCopy(NULL
, // allocator
6356 oldPrivate
->interface
, // interface
6357 prefs
, // [new] prefs
6358 serviceID
); // [new] serviceID
6360 if (oldPrivate
->name
!= NULL
) {
6361 newPrivate
->name
= CFRetain(oldPrivate
->name
);
6363 if (oldPrivate
->localized_name
!= NULL
) {
6364 newPrivate
->localized_name
= CFRetain(oldPrivate
->localized_name
);
6366 newPrivate
->localized_key
= oldPrivate
->localized_key
;
6367 if (oldPrivate
->localized_arg1
!= NULL
) {
6368 newPrivate
->localized_arg1
= CFRetain(oldPrivate
->localized_arg1
);
6370 if (oldPrivate
->localized_arg2
!= NULL
) {
6371 newPrivate
->localized_arg2
= CFRetain(oldPrivate
->localized_arg2
);
6373 if (oldPrivate
->unsaved
!= NULL
) {
6374 newPrivate
->unsaved
= CFDictionaryCreateMutableCopy(NULL
, 0, oldPrivate
->unsaved
);
6376 if (oldPrivate
->entity_device
!= NULL
) {
6377 newPrivate
->entity_device
= CFRetain(oldPrivate
->entity_device
);
6379 if (oldPrivate
->entity_device_unique
!= NULL
) {
6380 newPrivate
->entity_device_unique
= CFRetain(oldPrivate
->entity_device_unique
);
6382 newPrivate
->entity_type
= oldPrivate
->entity_type
;
6383 newPrivate
->entity_subtype
= oldPrivate
->entity_subtype
;
6384 if (oldPrivate
->supported_interface_types
!= NULL
) {
6385 newPrivate
->supported_interface_types
= CFArrayCreateMutableCopy(NULL
, 0, oldPrivate
->supported_interface_types
);
6387 if (oldPrivate
->supported_protocol_types
!= NULL
) {
6388 newPrivate
->supported_protocol_types
= CFArrayCreateMutableCopy(NULL
, 0, oldPrivate
->supported_protocol_types
);
6390 if (oldPrivate
->address
!= NULL
) {
6391 newPrivate
->address
= CFRetain(oldPrivate
->address
);
6393 newPrivate
->builtin
= oldPrivate
->builtin
;
6394 if (oldPrivate
->configurationAction
!= NULL
) {
6395 newPrivate
->configurationAction
= CFRetain(oldPrivate
->configurationAction
);
6397 newPrivate
->hidden
= oldPrivate
->hidden
;
6398 if (oldPrivate
->location
!= NULL
) {
6399 newPrivate
->location
= CFRetain(oldPrivate
->location
);
6401 if (oldPrivate
->path
!= NULL
) {
6402 newPrivate
->path
= CFRetain(oldPrivate
->path
);
6404 newPrivate
->entryID
= oldPrivate
->entryID
;
6405 if (oldPrivate
->overrides
!= NULL
) {
6406 newPrivate
->overrides
= CFDictionaryCreateMutableCopy(NULL
, 0, oldPrivate
->overrides
);
6408 newPrivate
->modemIsV92
= oldPrivate
->modemIsV92
;
6409 if (oldPrivate
->type
!= NULL
) {
6410 newPrivate
->type
= CFRetain(oldPrivate
->type
);
6412 if (oldPrivate
->unit
!= NULL
) {
6413 newPrivate
->unit
= CFRetain(oldPrivate
->unit
);
6415 if (oldPrivate
->usb
.name
!= NULL
) {
6416 newPrivate
->usb
.name
= CFRetain(oldPrivate
->usb
.name
);
6418 if (oldPrivate
->usb
.vid
!= NULL
) {
6419 newPrivate
->usb
.vid
= CFRetain(oldPrivate
->usb
.vid
);
6421 if (oldPrivate
->usb
.pid
!= NULL
) {
6422 newPrivate
->usb
.pid
= CFRetain(oldPrivate
->usb
.pid
);
6424 newPrivate
->sort_order
= oldPrivate
->sort_order
;
6426 newPrivate
->supportsBond
= oldPrivate
->supportsBond
;
6427 if (oldPrivate
->bond
.interfaces
!= NULL
) {
6428 newPrivate
->bond
.interfaces
= CFRetain(oldPrivate
->bond
.interfaces
);
6430 if (oldPrivate
->bond
.mode
!= NULL
) {
6431 newPrivate
->bond
.mode
= CFRetain(oldPrivate
->bond
.mode
);
6433 if (oldPrivate
->bond
.options
!= NULL
) {
6434 newPrivate
->bond
.options
= CFRetain(oldPrivate
->bond
.options
);
6437 newPrivate
->supportsBridge
= oldPrivate
->supportsBridge
;
6438 if (oldPrivate
->bridge
.interfaces
!= NULL
) {
6439 newPrivate
->bridge
.interfaces
= CFRetain(oldPrivate
->bridge
.interfaces
);
6441 if (oldPrivate
->bridge
.options
!= NULL
) {
6442 newPrivate
->bridge
.options
= CFRetain(oldPrivate
->bridge
.options
);
6445 newPrivate
->supportsVLAN
= oldPrivate
->supportsVLAN
;
6446 if (oldPrivate
->vlan
.interface
!= NULL
) {
6447 newPrivate
->vlan
.interface
= CFRetain(oldPrivate
->vlan
.interface
);
6449 if (oldPrivate
->vlan
.tag
!= NULL
) {
6450 newPrivate
->vlan
.tag
= CFRetain(oldPrivate
->vlan
.tag
);
6452 if (oldPrivate
->vlan
.options
!= NULL
) {
6453 newPrivate
->vlan
.options
= CFRetain(oldPrivate
->vlan
.options
);
6462 __SCNetworkInterfaceCopyDeepConfiguration(SCNetworkSetRef set
, SCNetworkInterfaceRef interface
)
6464 CFMutableArrayRef configs
;
6466 configs
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
6468 while (interface
!= NULL
) {
6469 CFStringRef defaultType
;
6470 CFMutableDictionaryRef interfaceConfiguration
;
6472 interfaceConfiguration
= CFDictionaryCreateMutable(NULL
,
6474 &kCFTypeDictionaryKeyCallBacks
,
6475 &kCFTypeDictionaryValueCallBacks
);
6477 defaultType
= __SCNetworkInterfaceGetDefaultConfigurationType(interface
);
6478 if (defaultType
!= NULL
) {
6479 CFDictionaryRef config
;
6480 CFArrayRef extendedTypes
;
6483 config
= __SCNetworkInterfaceGetConfiguration(interface
, defaultType
);
6485 config
= __SCNetworkInterfaceGetDefaultConfiguration(set
, interface
);
6487 if (config
== NULL
) {
6488 config
= (CFDictionaryRef
)kCFNull
;
6490 CFDictionarySetValue(interfaceConfiguration
, defaultType
, config
);
6492 extendedTypes
= extendedConfigurationTypes(interface
);
6493 if (extendedTypes
!= NULL
) {
6497 n
= CFArrayGetCount(extendedTypes
);
6498 for (i
= 0; i
< n
; i
++) {
6499 CFStringRef extendedType
;
6501 extendedType
= CFArrayGetValueAtIndex(extendedTypes
, i
);
6502 config
= __SCNetworkInterfaceGetConfiguration(interface
, extendedType
);
6503 if (config
== NULL
) {
6504 config
= (CFDictionaryRef
)kCFNull
;
6506 CFDictionarySetValue(interfaceConfiguration
, extendedType
, config
);
6509 CFRelease(extendedTypes
);
6513 CFArrayAppendValue(configs
, interfaceConfiguration
);
6514 CFRelease(interfaceConfiguration
);
6516 interface
= SCNetworkInterfaceGetInterface(interface
);
6523 __private_extern__ Boolean
6524 __SCNetworkInterfaceIsMember(SCPreferencesRef prefs
, SCNetworkInterfaceRef interface
)
6526 CFArrayRef interfaces
;
6527 Boolean match
= FALSE
;
6528 CFMutableSetRef members
;
6530 members
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
6532 #if !TARGET_OS_IPHONE
6533 // add Bond [member] interfaces
6534 interfaces
= SCBondInterfaceCopyAll(prefs
);
6535 if (interfaces
!= NULL
) {
6536 __SCBondInterfaceListCollectMembers(interfaces
, members
);
6537 CFRelease(interfaces
);
6539 #endif // !TARGET_OS_IPHONE
6541 // add Bridge [member] interfaces
6542 interfaces
= SCBridgeInterfaceCopyAll(prefs
);
6543 if (interfaces
!= NULL
) {
6544 __SCBridgeInterfaceListCollectMembers(interfaces
, members
);
6545 CFRelease(interfaces
);
6548 if (CFSetGetCount(members
) == 0) {
6552 while (interface
!= NULL
) {
6553 match
= CFSetContainsValue(members
, interface
);
6555 // if the interface is a member of an
6556 // Ethernet Bond or Bridge
6560 interface
= SCNetworkInterfaceGetInterface(interface
);
6572 __SCNetworkInterfaceSetDeepConfiguration(SCNetworkSetRef set
, SCNetworkInterfaceRef interface
, CFArrayRef configs
)
6576 for (i
= 0; interface
!= NULL
; i
++) {
6577 CFStringRef defaultType
;
6578 CFDictionaryRef interfaceConfiguration
;
6580 interfaceConfiguration
= (configs
!= NULL
) ? CFArrayGetValueAtIndex(configs
, i
) : NULL
;
6582 defaultType
= __SCNetworkInterfaceGetDefaultConfigurationType(interface
);
6583 if (defaultType
!= NULL
) {
6584 CFDictionaryRef config
;
6585 CFArrayRef extendedTypes
;
6587 config
= (interfaceConfiguration
!= NULL
) ? CFDictionaryGetValue(interfaceConfiguration
, defaultType
)
6589 if (config
== (CFDictionaryRef
)kCFNull
) {
6593 // if service is not associated with the set
6594 if (!__SCNetworkInterfaceSetConfiguration(interface
, defaultType
, config
, TRUE
)) {
6595 SCLog(TRUE
, LOG_DEBUG
,
6596 CFSTR("__SCNetworkInterfaceSetDeepConfiguration __SCNetworkInterfaceSetConfiguration() failed, interface=%@, type=%@"),
6601 // apply default configuration to this set
6602 if (!__SCNetworkInterfaceSetDefaultConfiguration(set
, interface
, defaultType
, config
, TRUE
)) {
6603 SCLog(TRUE
, LOG_DEBUG
,
6604 CFSTR("__SCNetworkInterfaceSetDeepConfiguration __SCNetworkInterfaceSetDefaultConfiguration() failed, interface=%@, type=%@"),
6610 extendedTypes
= extendedConfigurationTypes(interface
);
6611 if (extendedTypes
!= NULL
) {
6615 n
= CFArrayGetCount(extendedTypes
);
6616 for (j
= 0; j
< n
; j
++) {
6617 CFStringRef extendedType
;
6619 extendedType
= CFArrayGetValueAtIndex(extendedTypes
, j
);
6620 config
= (interfaceConfiguration
!= NULL
) ? CFDictionaryGetValue(interfaceConfiguration
, extendedType
)
6622 if (config
== (CFDictionaryRef
)kCFNull
) {
6625 if (!__SCNetworkInterfaceSetConfiguration(interface
, extendedType
, config
, TRUE
)) {
6626 SCLog(TRUE
, LOG_DEBUG
,
6627 CFSTR("__SCNetworkInterfaceSetDeepConfiguration __SCNetworkInterfaceSetConfiguration() failed, interface=%@, type=%@"),
6633 CFRelease(extendedTypes
);
6637 interface
= SCNetworkInterfaceGetInterface(interface
);
6644 SCNetworkInterfaceRef
6645 _SCNetworkInterfaceCopyActive(SCDynamicStoreRef store
, CFStringRef bsdName
)
6647 SCNetworkInterfaceRef interface
;
6649 interface
= _SCNetworkInterfaceCreateWithBSDName(NULL
, bsdName
, kIncludeAllVirtualInterfaces
);
6650 if (interface
== NULL
) {
6654 if (store
!= NULL
) {
6655 SCNetworkInterfacePrivateRef interfacePrivate
=
6656 (SCNetworkInterfacePrivateRef
)interface
;
6659 interfacePrivate
->store
= store
;
6666 SCNetworkServicePrimaryRank
6667 SCNetworkInterfaceGetPrimaryRank(SCNetworkInterfaceRef interface
)
6669 CFDictionaryRef entity
;
6670 SCNetworkInterfacePrivateRef interfacePrivate
=
6671 (SCNetworkInterfacePrivateRef
)interface
;
6675 SCNetworkServicePrimaryRank rank
= kSCNetworkServicePrimaryRankDefault
;
6676 SCDynamicStoreRef session
;
6678 ifName
= SCNetworkInterfaceGetBSDName(interface
);
6679 if ((ifName
== NULL
) || (interfacePrivate
->store
== NULL
)) {
6680 _SCErrorSet(kSCStatusInvalidArgument
);
6684 session
= interfacePrivate
->store
;
6686 path
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
,
6687 kSCDynamicStoreDomainState
,
6690 entity
= SCDynamicStoreCopyValue(session
, path
);
6693 if (entity
!= NULL
) {
6694 if (isA_CFDictionary(entity
)) {
6695 CFStringRef rankStr
=
6696 CFDictionaryGetValue(entity
, kSCPropNetServicePrimaryRank
);
6697 ok
= __str_to_rank(rankStr
, &rank
);
6703 rank
= kSCNetworkServicePrimaryRankDefault
;
6704 _SCErrorSet(kSCStatusInvalidArgument
);
6705 } else if (rank
== kSCNetworkServicePrimaryRankDefault
) {
6706 _SCErrorSet(kSCStatusOK
);
6713 SCNetworkInterfaceSetPrimaryRank(SCNetworkInterfaceRef interface
,
6714 SCNetworkServicePrimaryRank newRank
)
6716 CFDictionaryRef entity
;
6717 SCNetworkInterfacePrivateRef interfacePrivate
=
6718 (SCNetworkInterfacePrivateRef
)interface
;
6720 CFMutableDictionaryRef newEntity
;
6722 CFStringRef path
= NULL
;
6723 CFStringRef rankStr
;
6724 SCDynamicStoreRef session
;
6726 ifName
= SCNetworkInterfaceGetBSDName(interface
);
6727 if ((ifName
== NULL
) || (interfacePrivate
->store
== NULL
)) {
6728 _SCErrorSet(kSCStatusInvalidArgument
);
6732 session
= interfacePrivate
->store
;
6734 ok
= __rank_to_str(newRank
, &rankStr
);
6736 _SCErrorSet(kSCStatusInvalidArgument
);
6740 path
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
,
6741 kSCDynamicStoreDomainState
,
6745 entity
= SCDynamicStoreCopyValue(session
, path
);
6746 if (entity
!= NULL
) {
6747 if (!isA_CFDictionary(entity
)) {
6749 _SCErrorSet(kSCStatusFailed
);
6752 newEntity
= CFDictionaryCreateMutableCopy(NULL
, 0, entity
);
6755 newEntity
= CFDictionaryCreateMutable(NULL
,
6757 &kCFTypeDictionaryKeyCallBacks
,
6758 &kCFTypeDictionaryValueCallBacks
);
6761 if (rankStr
!= NULL
) {
6762 CFDictionarySetValue(newEntity
, kSCPropNetServicePrimaryRank
, rankStr
);
6764 CFDictionaryRemoveValue(newEntity
, kSCPropNetServicePrimaryRank
);
6767 if (CFDictionaryGetCount(newEntity
) > 0) {
6768 ok
= SCDynamicStoreSetValue(session
, path
, newEntity
);
6770 ok
= SCDynamicStoreRemoveValue(session
, path
);
6773 CFRelease(newEntity
);
6777 if (path
!= NULL
) CFRelease(path
);