2 * Copyright (c) 2004-2009 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 kUSBProductString
75 #define kUSBProductString "USB Product Name"
79 #include <mach/mach.h>
81 #include <net/if_types.h>
82 #include <net/route.h>
83 #include <sys/param.h>
84 #include <sys/types.h>
85 #include <sys/socket.h>
87 #include <sys/sysctl.h>
89 #include <NSSystemDirectories.h>
92 static CFStringRef
copy_interface_string (CFBundleRef bundle
, CFStringRef key
, Boolean localized
);
93 static CFStringRef
__SCNetworkInterfaceCopyDescription (CFTypeRef cf
);
94 static void __SCNetworkInterfaceDeallocate (CFTypeRef cf
);
95 static Boolean
__SCNetworkInterfaceEqual (CFTypeRef cf1
, CFTypeRef cf2
);
96 static CFHashCode
__SCNetworkInterfaceHash (CFTypeRef cf
);
116 #if !TARGET_OS_IPHONE
119 #endif // !TARGET_OS_IPHONE
124 const CFStringRef kSCNetworkInterfaceType6to4
= CFSTR("6to4");
125 const CFStringRef kSCNetworkInterfaceTypeBluetooth
= CFSTR("Bluetooth");
126 #if !TARGET_OS_IPHONE
127 const CFStringRef kSCNetworkInterfaceTypeBond
= CFSTR("Bond");
128 #endif // !TARGET_OS_IPHONE
129 const CFStringRef kSCNetworkInterfaceTypeEthernet
= CFSTR("Ethernet");
130 const CFStringRef kSCNetworkInterfaceTypeFireWire
= CFSTR("FireWire");
131 const CFStringRef kSCNetworkInterfaceTypeIEEE80211
= CFSTR("IEEE80211"); // IEEE 802.11, AirPort
132 const CFStringRef kSCNetworkInterfaceTypeIPSec
= CFSTR("IPSec");
133 const CFStringRef kSCNetworkInterfaceTypeIrDA
= CFSTR("IrDA");
134 const CFStringRef kSCNetworkInterfaceTypeL2TP
= CFSTR("L2TP");
135 const CFStringRef kSCNetworkInterfaceTypeModem
= CFSTR("Modem");
136 const CFStringRef kSCNetworkInterfaceTypePPP
= CFSTR("PPP");
137 const CFStringRef kSCNetworkInterfaceTypePPTP
= CFSTR("PPTP");
138 const CFStringRef kSCNetworkInterfaceTypeSerial
= CFSTR("Serial");
139 #if !TARGET_OS_IPHONE
140 const CFStringRef kSCNetworkInterfaceTypeVLAN
= CFSTR("VLAN");
141 #endif // !TARGET_OS_IPHONE
142 const CFStringRef kSCNetworkInterfaceTypeWWAN
= CFSTR("WWAN");
144 const CFStringRef kSCNetworkInterfaceTypeIPv4
= CFSTR("IPv4");
146 static SCNetworkInterfacePrivate __kSCNetworkInterfaceIPv4
= {
147 INIT_CFRUNTIME_BASE(NULL
, 0, 0x0080), // cfBase
148 NULL
, // interface type
150 NULL
, // localized name
151 NULL
, // localization key
152 NULL
, // localization arg1
153 NULL
, // localization arg2
154 NULL
, // [layered] interface
158 NULL
, // entity_device
159 NULL
, // entity_device_unique
161 NULL
, // entity_subtype
162 NULL
, // supported_interface_types
163 NULL
, // supported_protocol_types
165 NULL
, // addressString
167 NULL
, // configurationAction
174 kSortUnknown
, // sort_order
175 #if !TARGET_OS_IPHONE
176 FALSE
, // supportsBond
177 { NULL
, NULL
}, // bond { interfaces, options }
178 FALSE
, // supportsVLAN
179 { NULL
, NULL
, NULL
} // vlan { interface, tag, options }
180 #endif // !TARGET_OS_IPHONE
183 const SCNetworkInterfaceRef kSCNetworkInterfaceIPv4
= (SCNetworkInterfaceRef
)&__kSCNetworkInterfaceIPv4
;
186 #pragma mark SCNetworkInterface configuration details
195 #define doOverIP do6to4|doL2TP|doPPTP|doIPSec
197 #if !TARGET_OS_IPHONE
198 #define doAppleTalk 1<<0
199 #else // !TARGET_OS_IPHONE
200 #define doAppleTalk 0
201 #endif // !TARGET_OS_IPHONE
205 #define doProxies 1<<4
206 #if !TARGET_OS_IPHONE
208 #else // !TARGET_OS_IPHONE
210 #endif // !TARGET_OS_IPHONE
212 static const struct {
213 const CFStringRef
*interface_type
;
214 const CFStringRef
*entity_hardware
;
215 Boolean per_interface_config
;
216 uint32_t supported_interfaces
;
217 const CFStringRef
*ppp_subtype
;
218 uint32_t supported_protocols
;
219 } configurations
[] = {
220 // interface type entity_hardware if config? interface types PPP sub-type interface protocols
221 // ===================================== ================= ========== =============== ======================================= =========================================
222 { &kSCNetworkInterfaceType6to4
, &kSCEntNet6to4
, FALSE
, doNone
, NULL
, doIPv6
},
223 { &kSCNetworkInterfaceTypeBluetooth
, &kSCEntNetModem
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypePPPSerial
, doNone
},
224 #if !TARGET_OS_IPHONE
225 { &kSCNetworkInterfaceTypeBond
, &kSCEntNetEthernet
, TRUE
, doNone
, NULL
, doAppleTalk
|doDNS
|doIPv4
|doIPv6
|doProxies
|doSMB
},
226 #endif // !TARGET_OS_IPHONE
227 { &kSCNetworkInterfaceTypeEthernet
, &kSCEntNetEthernet
, TRUE
, doPPP
, &kSCValNetInterfaceSubTypePPPoE
, doAppleTalk
|doDNS
|doIPv4
|doIPv6
|doProxies
|doSMB
},
228 { &kSCNetworkInterfaceTypeFireWire
, &kSCEntNetFireWire
, TRUE
, doNone
, NULL
, doDNS
|doIPv4
|doIPv6
|doProxies
|doSMB
},
229 { &kSCNetworkInterfaceTypeIEEE80211
, &kSCEntNetAirPort
, TRUE
, doPPP
, &kSCValNetInterfaceSubTypePPPoE
, doAppleTalk
|doDNS
|doIPv4
|doIPv6
|doProxies
|doSMB
},
230 { &kSCNetworkInterfaceTypeIPSec
, &kSCEntNetIPSec
, FALSE
, doNone
, NULL
, doDNS
|doIPv4
|doIPv6
|doProxies
|doSMB
},
231 { &kSCNetworkInterfaceTypeIrDA
, &kSCEntNetModem
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypePPPSerial
, doNone
},
232 { &kSCNetworkInterfaceTypeL2TP
, NULL
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypeL2TP
, doNone
},
233 { &kSCNetworkInterfaceTypeModem
, &kSCEntNetModem
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypePPPSerial
, doNone
},
234 { &kSCNetworkInterfaceTypePPP
, &kSCEntNetPPP
, FALSE
, doNone
, NULL
, doDNS
|doIPv4
|doIPv6
|doProxies
|doSMB
},
235 { &kSCNetworkInterfaceTypePPTP
, NULL
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypePPTP
, doNone
},
236 { &kSCNetworkInterfaceTypeSerial
, &kSCEntNetModem
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypePPPSerial
, doNone
},
237 #if !TARGET_OS_IPHONE
238 { &kSCNetworkInterfaceTypeVLAN
, &kSCEntNetEthernet
, TRUE
, doNone
, NULL
, doAppleTalk
|doDNS
|doIPv4
|doIPv6
|doProxies
|doSMB
},
239 #endif // !TARGET_OS_IPHONE
240 { &kSCNetworkInterfaceTypeWWAN
, &kSCEntNetModem
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypePPPSerial
, doNone
},
241 // ===================================== ================= ========== =============== ======================================= =========================================
242 { &kSCNetworkInterfaceTypeIPv4
, NULL
, FALSE
, doOverIP
, NULL
, doNone
}
246 #define NETWORKINTERFACE_LOCALIZATIONS CFSTR("NetworkInterface")
247 static CFBundleRef bundle
= NULL
;
250 static CFTypeID __kSCNetworkInterfaceTypeID
= _kCFRuntimeNotATypeID
;
253 static const CFRuntimeClass __SCNetworkInterfaceClass
= {
255 "SCNetworkInterface", // className
258 __SCNetworkInterfaceDeallocate
, // dealloc
259 __SCNetworkInterfaceEqual
, // equal
260 __SCNetworkInterfaceHash
, // hash
261 NULL
, // copyFormattingDesc
262 __SCNetworkInterfaceCopyDescription
// copyDebugDesc
266 static pthread_once_t initialized
= PTHREAD_ONCE_INIT
;
267 static pthread_once_t iokit_quiet
= PTHREAD_ONCE_INIT
;
270 static mach_port_t masterPort
= MACH_PORT_NULL
;
274 __SCNetworkInterfaceCopyDescription(CFTypeRef cf
)
276 CFAllocatorRef allocator
= CFGetAllocator(cf
);
277 CFMutableStringRef result
;
278 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)cf
;
280 result
= CFStringCreateMutable(allocator
, 0);
281 CFStringAppendFormat(result
, NULL
, CFSTR("<SCNetworkInterface %p [%p]> {"), cf
, allocator
);
282 CFStringAppendFormat(result
, NULL
, CFSTR("type = %@"), interfacePrivate
->interface_type
);
283 CFStringAppendFormat(result
, NULL
, CFSTR(", entity_device = %@"), interfacePrivate
->entity_device
);
284 if (interfacePrivate
->entity_device_unique
!= NULL
) {
285 CFStringAppendFormat(result
, NULL
, CFSTR("+%@"), interfacePrivate
->entity_device_unique
);
287 CFStringAppendFormat(result
, NULL
, CFSTR(", entity_type = %@"), interfacePrivate
->entity_type
);
288 if (interfacePrivate
->entity_subtype
!= NULL
) {
289 CFStringAppendFormat(result
, NULL
, CFSTR(" / %@"), interfacePrivate
->entity_subtype
);
291 if (interfacePrivate
->name
!= NULL
) {
292 CFStringAppendFormat(result
, NULL
, CFSTR(", name = %@"), interfacePrivate
->name
);
294 if (interfacePrivate
->localized_name
!= NULL
) {
295 CFStringAppendFormat(result
, NULL
, CFSTR(", name(l) = %@"), interfacePrivate
->localized_name
);
297 if (interfacePrivate
->localized_key
!= NULL
) {
298 CFStringAppendFormat(result
, NULL
, CFSTR(", name(k) = \"%@\""), interfacePrivate
->localized_key
);
299 if (interfacePrivate
->localized_arg1
!= NULL
) {
300 CFStringAppendFormat(result
, NULL
, CFSTR("+\"%@\""), interfacePrivate
->localized_arg1
);
302 if (interfacePrivate
->localized_arg2
!= NULL
) {
303 CFStringAppendFormat(result
, NULL
, CFSTR("+\"%@\""), interfacePrivate
->localized_arg2
);
307 if (interfacePrivate
->address
!= NULL
) {
312 CFStringAppendFormat(result
, NULL
, CFSTR(", address = 0x"));
314 data
= CFDataGetBytePtr(interfacePrivate
->address
);
315 dataLen
= CFDataGetLength(interfacePrivate
->address
);
316 for (i
= 0; i
< dataLen
; i
++) {
317 CFStringAppendFormat(result
, NULL
, CFSTR("%02x"), data
[i
]);
320 CFStringAppendFormat(result
, NULL
, CFSTR(", builtin = %s"), interfacePrivate
->builtin
? "TRUE" : "FALSE");
321 if (interfacePrivate
->modemIsV92
) {
322 CFStringAppendFormat(result
, NULL
, CFSTR(", v.92"));
324 if (interfacePrivate
->location
!= NULL
) {
325 CFStringAppendFormat(result
, NULL
, CFSTR(", location = %@"), interfacePrivate
->location
);
327 if (interfacePrivate
->type
!= NULL
) {
328 CFStringAppendFormat(result
, NULL
, CFSTR(", type = %@"), interfacePrivate
->type
);
330 if (interfacePrivate
->unit
!= NULL
) {
331 CFStringAppendFormat(result
, NULL
, CFSTR(", unit = %@"), interfacePrivate
->unit
);
333 if (interfacePrivate
->path
!= NULL
) {
334 CFStringAppendFormat(result
, NULL
, CFSTR(", path = %@"), interfacePrivate
->path
);
336 if (interfacePrivate
->configurationAction
!= NULL
) {
337 CFStringAppendFormat(result
, NULL
, CFSTR(", action = %@"), interfacePrivate
->configurationAction
);
339 if (interfacePrivate
->overrides
!= NULL
) {
340 CFStringAppendFormat(result
, NULL
, CFSTR(", overrides = %p"), interfacePrivate
->overrides
);
342 CFStringAppendFormat(result
, NULL
, CFSTR(", order = %d"), interfacePrivate
->sort_order
);
343 if (interfacePrivate
->prefs
!= NULL
) {
344 CFStringAppendFormat(result
, NULL
, CFSTR(", prefs = %p"), interfacePrivate
->prefs
);
346 if (interfacePrivate
->serviceID
!= NULL
) {
347 CFStringAppendFormat(result
, NULL
, CFSTR(", service = %@"), interfacePrivate
->serviceID
);
349 if (interfacePrivate
->interface
!= NULL
) {
350 CFStringAppendFormat(result
, NULL
, CFSTR(", interface = %@"), interfacePrivate
->interface
);
352 if (interfacePrivate
->unsaved
!= NULL
) {
353 CFStringAppendFormat(result
, NULL
, CFSTR(", unsaved = %@"), interfacePrivate
->unsaved
);
355 #if !TARGET_OS_IPHONE
356 if (interfacePrivate
->bond
.interfaces
!= NULL
) {
360 n
= CFArrayGetCount(interfacePrivate
->bond
.interfaces
);
361 for (i
= 0; i
< n
; i
++) {
362 SCNetworkInterfaceRef member
;
364 member
= CFArrayGetValueAtIndex(interfacePrivate
->bond
.interfaces
, i
);
365 CFStringAppendFormat(result
, NULL
,
367 (i
== 0) ? ", interfaces = " : ", ",
368 SCNetworkInterfaceGetBSDName(member
));
371 if (interfacePrivate
->bond
.mode
!= NULL
) {
372 CFStringAppendFormat(result
, NULL
, CFSTR(", mode = %@"), interfacePrivate
->bond
.mode
);
374 if (interfacePrivate
->bond
.options
!= NULL
) {
375 CFStringAppendFormat(result
, NULL
, CFSTR(", options = %@"), interfacePrivate
->bond
.options
);
377 if (interfacePrivate
->bond
.mode
!= NULL
) {
378 CFStringAppendFormat(result
, NULL
, CFSTR(", mode = %@"), interfacePrivate
->bond
.mode
);
380 if (interfacePrivate
->vlan
.interface
!= NULL
) {
381 CFStringAppendFormat(result
, NULL
,
382 CFSTR(", interface = %@"),
383 SCNetworkInterfaceGetBSDName(interfacePrivate
->vlan
.interface
));
385 if (interfacePrivate
->vlan
.tag
!= NULL
) {
386 CFStringAppendFormat(result
, NULL
, CFSTR(", tag = %@"), interfacePrivate
->vlan
.tag
);
388 if (interfacePrivate
->vlan
.options
!= NULL
) {
389 CFStringAppendFormat(result
, NULL
, CFSTR(", options = %@"), interfacePrivate
->vlan
.options
);
391 #endif // !TARGET_OS_IPHONE
392 CFStringAppendFormat(result
, NULL
, CFSTR("}"));
399 __SCNetworkInterfaceDeallocate(CFTypeRef cf
)
401 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)cf
;
403 /* release resources */
405 if (interfacePrivate
->interface
!= NULL
)
406 CFRelease(interfacePrivate
->interface
);
408 if (interfacePrivate
->name
!= NULL
)
409 CFRelease(interfacePrivate
->name
);
411 if (interfacePrivate
->localized_name
!= NULL
)
412 CFRelease(interfacePrivate
->localized_name
);
414 if (interfacePrivate
->localized_arg1
!= NULL
)
415 CFRelease(interfacePrivate
->localized_arg1
);
417 if (interfacePrivate
->localized_arg2
!= NULL
)
418 CFRelease(interfacePrivate
->localized_arg2
);
420 if (interfacePrivate
->prefs
!= NULL
)
421 CFRelease(interfacePrivate
->prefs
);
423 if (interfacePrivate
->serviceID
!= NULL
)
424 CFRelease(interfacePrivate
->serviceID
);
426 if (interfacePrivate
->unsaved
!= NULL
)
427 CFRelease(interfacePrivate
->unsaved
);
429 if (interfacePrivate
->entity_device
!= NULL
)
430 CFRelease(interfacePrivate
->entity_device
);
432 if (interfacePrivate
->entity_device_unique
!= NULL
)
433 CFRelease(interfacePrivate
->entity_device_unique
);
435 if (interfacePrivate
->supported_interface_types
!= NULL
)
436 CFRelease(interfacePrivate
->supported_interface_types
);
438 if (interfacePrivate
->supported_protocol_types
!= NULL
)
439 CFRelease(interfacePrivate
->supported_protocol_types
);
441 if (interfacePrivate
->address
!= NULL
)
442 CFRelease(interfacePrivate
->address
);
444 if (interfacePrivate
->addressString
!= NULL
)
445 CFRelease(interfacePrivate
->addressString
);
447 if (interfacePrivate
->location
!= NULL
)
448 CFRelease(interfacePrivate
->location
);
450 if (interfacePrivate
->path
!= NULL
)
451 CFRelease(interfacePrivate
->path
);
453 if (interfacePrivate
->configurationAction
!= NULL
)
454 CFRelease(interfacePrivate
->configurationAction
);
456 if (interfacePrivate
->overrides
!= NULL
)
457 CFRelease(interfacePrivate
->overrides
);
459 if (interfacePrivate
->type
!= NULL
)
460 CFRelease(interfacePrivate
->type
);
462 if (interfacePrivate
->unit
!= NULL
)
463 CFRelease(interfacePrivate
->unit
);
465 #if !TARGET_OS_IPHONE
466 if (interfacePrivate
->bond
.interfaces
!= NULL
)
467 CFRelease(interfacePrivate
->bond
.interfaces
);
469 if (interfacePrivate
->bond
.mode
!= NULL
)
470 CFRelease(interfacePrivate
->bond
.mode
);
472 if (interfacePrivate
->bond
.options
!= NULL
)
473 CFRelease(interfacePrivate
->bond
.options
);
475 if (interfacePrivate
->vlan
.interface
!= NULL
)
476 CFRelease(interfacePrivate
->vlan
.interface
);
478 if (interfacePrivate
->vlan
.tag
!= NULL
)
479 CFRelease(interfacePrivate
->vlan
.tag
);
481 if (interfacePrivate
->vlan
.options
!= NULL
)
482 CFRelease(interfacePrivate
->vlan
.options
);
483 #endif // !TARGET_OS_IPHONE
490 __SCNetworkInterfaceEqual(CFTypeRef cf1
, CFTypeRef cf2
)
492 SCNetworkInterfacePrivateRef if1
= (SCNetworkInterfacePrivateRef
)cf1
;
493 SCNetworkInterfacePrivateRef if2
= (SCNetworkInterfacePrivateRef
)cf2
;
498 if (!CFEqual(if1
->interface_type
, if2
->interface_type
)) {
499 return FALSE
; // if not the same interface type
502 if (!_SC_CFEqual(if1
->entity_device
, if2
->entity_device
)) {
503 return FALSE
; // if not the same device
506 if (!_SC_CFEqual(if1
->entity_device_unique
, if2
->entity_device_unique
)) {
507 return FALSE
; // if not the same device unique identifier
510 #if !TARGET_OS_IPHONE
511 if (CFEqual(if1
->interface_type
, kSCNetworkInterfaceTypeBond
)) {
512 if (!_SC_CFEqual(if1
->bond
.interfaces
, if2
->bond
.interfaces
)) {
513 return FALSE
; // if not the same interfaces
515 if (!_SC_CFEqual(if1
->bond
.mode
, if2
->bond
.mode
)) {
516 return FALSE
; // if not the same mode
520 if (CFEqual(if1
->interface_type
, kSCNetworkInterfaceTypeVLAN
)) {
521 if (!_SC_CFEqual(if1
->vlan
.interface
, if2
->vlan
.interface
)) {
522 return FALSE
; // if not the same physical interface
524 if (!_SC_CFEqual(if1
->vlan
.tag
, if2
->vlan
.tag
)) {
525 return FALSE
; // if not the same tag
528 #endif // !TARGET_OS_IPHONE
530 if (!_SC_CFEqual(if1
->interface
, if2
->interface
)) {
531 return FALSE
; // if not the same layering
539 __SCNetworkInterfaceHash(CFTypeRef cf
)
542 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)cf
;
544 if (interfacePrivate
->entity_device
!= NULL
) {
545 if (interfacePrivate
->entity_device_unique
== NULL
) {
546 hash
= CFHash(interfacePrivate
->entity_device
);
550 str
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@+%@"),
551 interfacePrivate
->entity_device
,
552 interfacePrivate
->entity_device_unique
);
563 __SCNetworkInterfaceInitialize(void)
568 __kSCNetworkInterfaceTypeID
= _CFRuntimeRegisterClass(&__SCNetworkInterfaceClass
);
570 // initialize __kSCNetworkInterfaceIPv4
571 _CFRuntimeSetInstanceTypeID(&__kSCNetworkInterfaceIPv4
, __kSCNetworkInterfaceTypeID
);
572 __kSCNetworkInterfaceIPv4
.interface_type
= kSCNetworkInterfaceTypeIPv4
;
573 __kSCNetworkInterfaceIPv4
.localized_key
= CFSTR("ipv4");
575 // get CFBundleRef for SystemConfiguration.framework
576 bundle
= _SC_CFBundleGet();
578 // get mach port used to communication with IOKit
579 kr
= IOMasterPort(MACH_PORT_NULL
, &masterPort
);
580 if (kr
!= KERN_SUCCESS
) {
581 SCLog(TRUE
, LOG_DEBUG
,
582 CFSTR("__SCNetworkInterfaceInitialize(), could not get IOMasterPort, kr = 0x%x"),
591 SCNetworkInterfacePrivateRef
592 __SCNetworkInterfaceCreatePrivate(CFAllocatorRef allocator
,
593 SCNetworkInterfaceRef interface
,
594 SCPreferencesRef prefs
,
595 CFStringRef serviceID
,
598 SCNetworkInterfacePrivateRef interfacePrivate
;
601 /* initialize runtime */
602 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
604 /* allocate target */
605 size
= sizeof(SCNetworkInterfacePrivate
) - sizeof(CFRuntimeBase
);
606 interfacePrivate
= (SCNetworkInterfacePrivateRef
)_CFRuntimeCreateInstance(allocator
,
607 __kSCNetworkInterfaceTypeID
,
610 if (interfacePrivate
== NULL
) {
614 interfacePrivate
->interface_type
= NULL
;
615 interfacePrivate
->name
= NULL
;
616 interfacePrivate
->localized_name
= NULL
;
617 interfacePrivate
->localized_key
= NULL
;
618 interfacePrivate
->localized_arg1
= NULL
;
619 interfacePrivate
->localized_arg2
= NULL
;
620 interfacePrivate
->interface
= (interface
!= NULL
) ? CFRetain(interface
) : NULL
;
621 interfacePrivate
->prefs
= (prefs
!= NULL
) ? CFRetain(prefs
) : NULL
;
622 interfacePrivate
->serviceID
= (serviceID
!= NULL
) ? CFRetain(serviceID
) : NULL
;
623 interfacePrivate
->unsaved
= NULL
;
624 interfacePrivate
->entity_device
= NULL
;
625 interfacePrivate
->entity_device_unique
= NULL
;
626 interfacePrivate
->entity_type
= NULL
;
627 interfacePrivate
->entity_subtype
= NULL
;
628 interfacePrivate
->supported_interface_types
= NULL
;
629 interfacePrivate
->supported_protocol_types
= NULL
;
630 interfacePrivate
->address
= NULL
;
631 interfacePrivate
->addressString
= NULL
;
632 interfacePrivate
->builtin
= FALSE
;
633 interfacePrivate
->configurationAction
= NULL
;
634 interfacePrivate
->path
= (path
!= NULL
) ? CFStringCreateWithCString(NULL
, path
, kCFStringEncodingUTF8
)
636 interfacePrivate
->location
= NULL
;
637 interfacePrivate
->overrides
= NULL
;
638 interfacePrivate
->modemIsV92
= FALSE
;
639 interfacePrivate
->type
= NULL
;
640 interfacePrivate
->unit
= NULL
;
641 interfacePrivate
->sort_order
= kSortUnknown
;
642 #if !TARGET_OS_IPHONE
643 interfacePrivate
->supportsBond
= FALSE
;
644 interfacePrivate
->bond
.interfaces
= NULL
;
645 interfacePrivate
->bond
.mode
= NULL
;
646 interfacePrivate
->bond
.options
= NULL
;
647 interfacePrivate
->supportsVLAN
= FALSE
;
648 interfacePrivate
->vlan
.interface
= NULL
;
649 interfacePrivate
->vlan
.tag
= NULL
;
650 interfacePrivate
->vlan
.options
= NULL
;
651 #endif // !TARGET_OS_IPHONE
653 return interfacePrivate
;
657 #if !TARGET_OS_IPHONE
660 __SCNetworkInterfaceSupportsVLAN(CFStringRef bsd_if
)
664 struct if_msghdr
* ifm
;
665 char * if_name
= NULL
;
666 unsigned int if_index
;
668 Boolean vlanOK
= FALSE
;
670 // get the interface index
671 if_name
= _SC_cfstring_to_cstring(bsd_if
, NULL
, 0, kCFStringEncodingASCII
);
672 if (if_name
== NULL
) {
673 return FALSE
; // if conversion error
675 if_index
= if_nametoindex(if_name
);
677 goto done
; // if unknown interface
680 // get information for the specified interface
685 mib
[4] = NET_RT_IFLIST
;
686 mib
[5] = if_index
; /* ask for exactly one interface */
688 if (sysctl(mib
, 6, NULL
, &buf_len
, NULL
, 0) == -1) {
689 SCLog(TRUE
, LOG_ERR
, CFSTR("sysctl() size failed: %s"), strerror(errno
));
692 buf
= CFAllocatorAllocate(NULL
, buf_len
, 0);
693 if (sysctl(mib
, 6, buf
, &buf_len
, NULL
, 0) == -1) {
694 SCLog(TRUE
, LOG_ERR
, CFSTR("sysctl() failed: %s"), strerror(errno
));
698 // check the link type and hwassist flags
699 ifm
= (struct if_msghdr
*)buf
;
700 switch (ifm
->ifm_type
) {
702 #if defined(IF_HWASSIST_VLAN_TAGGING) && defined(IF_HWASSIST_VLAN_MTU)
703 struct if_data
*if_data
= &ifm
->ifm_data
;
705 if (if_data
->ifi_hwassist
& (IF_HWASSIST_VLAN_TAGGING
| IF_HWASSIST_VLAN_MTU
)) {
715 if (if_name
!= NULL
) CFAllocatorDeallocate(NULL
, if_name
);
716 if (buf
!= NULL
) CFAllocatorDeallocate(NULL
, buf
);
723 SCNetworkInterfacePrivateRef
724 _SCBondInterfaceCreatePrivate(CFAllocatorRef allocator
,
727 SCNetworkInterfacePrivateRef interfacePrivate
;
729 interfacePrivate
= __SCNetworkInterfaceCreatePrivate(allocator
, NULL
, NULL
, NULL
, NULL
);
730 if (interfacePrivate
== NULL
) {
734 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeBond
;
735 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeEthernet
;
736 interfacePrivate
->entity_device
= CFStringCreateCopy(allocator
, bond_if
);
737 interfacePrivate
->builtin
= TRUE
;
738 interfacePrivate
->supportsVLAN
= __SCNetworkInterfaceSupportsVLAN(bond_if
);
739 interfacePrivate
->sort_order
= kSortBond
;
741 interfacePrivate
->localized_key
= CFSTR("bond");
742 interfacePrivate
->localized_arg1
= CFRetain(interfacePrivate
->entity_device
);
744 interfacePrivate
->bond
.interfaces
= CFArrayCreate(NULL
, NULL
, 0, &kCFTypeArrayCallBacks
);
745 // interfacePrivate->bond.mode = NULL;
746 // interfacePrivate->bond.options = NULL;
748 return interfacePrivate
;
753 SCNetworkInterfacePrivateRef
754 _SCVLANInterfaceCreatePrivate(CFAllocatorRef allocator
,
757 SCNetworkInterfacePrivateRef interfacePrivate
;
759 interfacePrivate
= __SCNetworkInterfaceCreatePrivate(allocator
, NULL
, NULL
, NULL
, NULL
);
760 if (interfacePrivate
== NULL
) {
764 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeVLAN
;
765 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeEthernet
;
766 interfacePrivate
->entity_device
= CFStringCreateCopy(allocator
, vlan_if
);
767 interfacePrivate
->builtin
= TRUE
;
768 interfacePrivate
->sort_order
= kSortVLAN
;
770 interfacePrivate
->localized_key
= CFSTR("vlan");
771 interfacePrivate
->localized_arg1
= CFRetain(interfacePrivate
->entity_device
);
773 // interfacePrivate->vlan.interface = NULL;
774 // interfacePrivate->vlan.tag = NULL;
775 // interfacePrivate->vlan.options = NULL;
777 return interfacePrivate
;
779 #endif // !TARGET_OS_IPHONE
783 #pragma mark Interface ordering
787 split_path(CFStringRef path
)
789 CFArrayRef components
;
790 CFMutableStringRef nPath
;
792 // turn '@'s into '/'s
793 nPath
= CFStringCreateMutableCopy(NULL
, 0, path
);
794 (void) CFStringFindAndReplace(nPath
,
797 CFRangeMake(0, CFStringGetLength(nPath
)),
800 // split path into components to be compared
801 components
= CFStringCreateArrayBySeparatingStrings(NULL
, nPath
, CFSTR("/"));
809 _SCNetworkInterfaceCompare(const void *val1
, const void *val2
, void *context
)
811 SCNetworkInterfacePrivateRef dev1
= (SCNetworkInterfacePrivateRef
)val1
;
812 SCNetworkInterfacePrivateRef dev2
= (SCNetworkInterfacePrivateRef
)val2
;
813 CFComparisonResult res
= kCFCompareEqualTo
;
815 /* sort by interface type */
816 if (dev1
->sort_order
!= dev2
->sort_order
) {
817 if (dev1
->sort_order
< dev2
->sort_order
) {
818 res
= kCFCompareLessThan
;
820 res
= kCFCompareGreaterThan
;
825 /* built-in interfaces sort first */
826 if (dev1
->builtin
!= dev2
->builtin
) {
828 res
= kCFCompareLessThan
;
830 res
= kCFCompareGreaterThan
;
835 /* ... and then, sort built-in interfaces by "location" */
837 if (dev1
->location
!= dev2
->location
) {
838 if (isA_CFString(dev1
->location
)) {
839 if (isA_CFString(dev2
->location
)) {
840 res
= CFStringCompare(dev1
->location
, dev2
->location
, 0);
842 res
= kCFCompareLessThan
;
845 res
= kCFCompareGreaterThan
;
848 if (res
!= kCFCompareEqualTo
) {
854 /* ... and, then sort by IOPathMatch */
855 if ((dev1
->path
!= NULL
) && (dev2
->path
!= NULL
)) {
856 CFArrayRef elements1
;
857 CFArrayRef elements2
;
863 elements1
= split_path(dev1
->path
);
864 n1
= CFArrayGetCount(elements1
);
866 elements2
= split_path(dev2
->path
);
867 n2
= CFArrayGetCount(elements2
);
869 n
= (n1
<= n2
) ? n1
: n2
;
870 for (i
= 0; i
< n
; i
++) {
879 e1
= CFArrayGetValueAtIndex(elements1
, i
);
880 e2
= CFArrayGetValueAtIndex(elements2
, i
);
882 str
= _SC_cfstring_to_cstring(e1
, NULL
, 0, kCFStringEncodingUTF8
);
884 q1
= strtoq(str
, &end
, 16);
885 isNum
= ((*str
!= '\0') && (*end
== '\0') && (errno
== 0));
886 CFAllocatorDeallocate(NULL
, str
);
889 // if e1 is a valid numeric string
890 str
= _SC_cfstring_to_cstring(e2
, NULL
, 0, kCFStringEncodingUTF8
);
892 q2
= strtoq(str
, &end
, 16);
893 isNum
= ((*str
!= '\0') && (*end
== '\0') && (errno
== 0));
894 CFAllocatorDeallocate(NULL
, str
);
897 // if e2 is also a valid numeric string
900 res
= kCFCompareEqualTo
;
902 } else if (q1
< q2
) {
903 res
= kCFCompareLessThan
;
905 res
= kCFCompareGreaterThan
;
911 res
= CFStringCompare(e1
, e2
, 0);
912 if (res
!= kCFCompareEqualTo
) {
917 if (res
== kCFCompareEqualTo
) {
919 res
= kCFCompareLessThan
;
920 } else if (n1
< n2
) {
921 res
= kCFCompareGreaterThan
;
925 CFRelease(elements1
);
926 CFRelease(elements2
);
928 if (res
!= kCFCompareEqualTo
) {
933 /* ... and, then sort by BSD interface name */
934 if ((dev1
->entity_device
!= NULL
) && (dev2
->entity_device
!= NULL
)) {
935 res
= CFStringCompare(dev1
->entity_device
, dev2
->entity_device
, 0);
936 if (res
!= kCFCompareEqualTo
) {
941 /* ... and lastly, sort by BSD interface unique identifier */
942 if ((dev1
->entity_device_unique
!= NULL
) && (dev2
->entity_device_unique
!= NULL
)) {
943 res
= CFStringCompare(dev1
->entity_device_unique
, dev2
->entity_device_unique
, 0);
944 // if (res != kCFCompareEqualTo) {
954 sort_interfaces(CFMutableArrayRef all_interfaces
)
956 int n
= CFArrayGetCount(all_interfaces
);
962 CFArraySortValues(all_interfaces
, CFRangeMake(0, n
), _SCNetworkInterfaceCompare
, NULL
);
969 __SCNetworkInterfaceOrder(SCNetworkInterfaceRef interface
)
971 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
973 return interfacePrivate
->sort_order
;
978 #pragma mark Interface details
982 IOCopyCFStringValue(CFTypeRef ioVal
)
984 if (isA_CFString(ioVal
)) {
985 return CFStringCreateCopy(NULL
, ioVal
);
988 if (isA_CFData(ioVal
)) {
989 return CFStringCreateWithCString(NULL
,
990 (const char *)CFDataGetBytePtr(ioVal
),
991 kCFStringEncodingUTF8
);
999 IODictionaryCopyCFStringValue(CFDictionaryRef io_dict
, CFStringRef io_key
)
1003 ioVal
= CFDictionaryGetValue(io_dict
, io_key
);
1004 return IOCopyCFStringValue(ioVal
);
1009 IOStringValueHasPrefix(CFTypeRef ioVal
, CFStringRef prefix
)
1011 Boolean match
= FALSE
;
1012 CFIndex prefixLen
= CFStringGetLength(prefix
);
1013 CFStringRef str
= NULL
;
1015 if (!isA_CFString(ioVal
)) {
1016 if (isA_CFData(ioVal
)) {
1017 str
= CFStringCreateWithCStringNoCopy(NULL
,
1018 (const char *)CFDataGetBytePtr(ioVal
),
1019 kCFStringEncodingUTF8
,
1027 if ((ioVal
!= NULL
) &&
1028 (CFStringGetLength(ioVal
) >= prefixLen
) &&
1029 (CFStringCompareWithOptions(ioVal
,
1031 CFRangeMake(0, prefixLen
),
1032 kCFCompareCaseInsensitive
) == kCFCompareEqualTo
)) {
1036 if (str
!= NULL
) CFRelease(str
);
1041 static const struct {
1042 const CFStringRef name
;
1043 const CFStringRef slot
;
1044 } slot_mappings
[] = {
1046 { CFSTR("A1") , CFSTR("1") },
1047 { CFSTR("B1") , CFSTR("2") },
1048 { CFSTR("C1") , CFSTR("3") },
1050 // Blue&White G3, Yikes G4
1051 { CFSTR("J12"), CFSTR("1") },
1052 { CFSTR("J11"), CFSTR("2") },
1053 { CFSTR("J10"), CFSTR("3") },
1054 { CFSTR("J9"), CFSTR("4") },
1057 { CFSTR("A") , CFSTR("1") },
1058 { CFSTR("B") , CFSTR("2") },
1059 { CFSTR("C") , CFSTR("3") },
1060 { CFSTR("D") , CFSTR("4") },
1062 // Digital Audio G4 (and later models)
1063 { CFSTR("1") , CFSTR("1") },
1064 { CFSTR("2") , CFSTR("2") },
1065 { CFSTR("3") , CFSTR("3") },
1066 { CFSTR("4") , CFSTR("4") },
1067 { CFSTR("5") , CFSTR("5") }
1072 pci_slot(io_registry_entry_t interface
, CFTypeRef
*pci_slot_name
)
1075 io_registry_entry_t parent
;
1076 CFMutableStringRef slot
;
1077 CFTypeRef slot_name
;
1080 if (pci_slot_name
!= NULL
) *pci_slot_name
= NULL
;
1082 slot_name
= IORegistryEntryCreateCFProperty(interface
, CFSTR("AAPL,slot-name"), NULL
, 0);
1083 if (slot_name
!= NULL
) {
1086 slot
= CFStringCreateMutable(NULL
, 0);
1087 if (isA_CFString(slot_name
)) {
1088 if (pci_slot_name
!= NULL
) *pci_slot_name
= CFStringCreateCopy(NULL
, slot_name
);
1089 CFStringAppend(slot
, slot_name
);
1090 } else if (isA_CFData(slot_name
)) {
1091 if (pci_slot_name
!= NULL
) *pci_slot_name
= CFDataCreateCopy(NULL
, slot_name
);
1092 CFStringAppendCString(slot
,
1093 (const char *)CFDataGetBytePtr(slot_name
),
1094 kCFStringEncodingUTF8
);
1097 if (CFStringGetLength(slot
) > 5) {
1098 (void) CFStringFindAndReplace(slot
,
1102 kCFCompareCaseInsensitive
|kCFCompareAnchored
);
1105 for (i
= 0; i
< sizeof(slot_mappings
)/sizeof(slot_mappings
[0]); i
++) {
1106 if (CFStringCompare(slot
,
1107 slot_mappings
[i
].name
,
1108 kCFCompareCaseInsensitive
) == kCFCompareEqualTo
) {
1110 slot
= (CFMutableStringRef
)CFRetain(slot_mappings
[i
].slot
);
1115 CFRelease(slot_name
);
1118 kr
= IORegistryEntryGetParentEntry(interface
, kIOServicePlane
, &parent
);
1120 case kIOReturnSuccess
: {
1121 CFTypeRef parent_pci_slot_name
= NULL
;
1122 CFStringRef parent_slot
;
1124 parent_slot
= pci_slot(parent
, &parent_pci_slot_name
);
1125 if (parent_slot
!= NULL
) {
1126 if (slot
!= NULL
) CFRelease(slot
);
1127 slot
= (CFMutableStringRef
)parent_slot
;
1129 if (pci_slot_name
!= NULL
) {
1130 if (*pci_slot_name
!= NULL
) CFRelease(*pci_slot_name
);
1131 *pci_slot_name
= parent_pci_slot_name
;
1133 CFRelease(parent_pci_slot_name
);
1137 IOObjectRelease(parent
);
1140 case kIOReturnNoDevice
:
1141 // if we have hit the root node
1144 SCLog(TRUE
, LOG_DEBUG
, CFSTR("pci_slot IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr
);
1152 static CFComparisonResult
1153 compare_bsdNames(const void *val1
, const void *val2
, void *context
)
1155 CFStringRef bsd1
= (CFStringRef
)val1
;
1156 CFStringRef bsd2
= (CFStringRef
)val2
;
1158 return CFStringCompare(bsd1
, bsd2
, 0);
1163 pci_port(CFTypeRef slot_name
, CFStringRef bsdName
)
1166 CFStringRef port_name
= NULL
;
1167 CFMutableArrayRef port_names
;
1170 CFStringRef match_keys
[2];
1171 CFTypeRef match_vals
[2];
1172 CFDictionaryRef match_dict
;
1173 CFDictionaryRef matching
;
1174 io_registry_entry_t slot
;
1175 io_iterator_t slot_iterator
= MACH_PORT_NULL
;
1177 match_keys
[0] = CFSTR("AAPL,slot-name");
1178 match_vals
[0] = slot_name
;
1180 match_dict
= CFDictionaryCreate(NULL
,
1181 (const void **)match_keys
,
1182 (const void **)match_vals
,
1184 &kCFTypeDictionaryKeyCallBacks
,
1185 &kCFTypeDictionaryValueCallBacks
);
1187 match_keys
[0] = CFSTR(kIOProviderClassKey
);
1188 match_vals
[0] = CFSTR("IOPCIDevice");
1190 match_keys
[1] = CFSTR(kIOPropertyMatchKey
);
1191 match_vals
[1] = match_dict
;
1193 // note: the "matching" dictionary will be consumed by the following
1194 matching
= CFDictionaryCreate(NULL
,
1195 (const void **)match_keys
,
1196 (const void **)match_vals
,
1197 sizeof(match_keys
)/sizeof(match_keys
[0]),
1198 &kCFTypeDictionaryKeyCallBacks
,
1199 &kCFTypeDictionaryValueCallBacks
);
1200 CFRelease(match_dict
);
1202 kr
= IOServiceGetMatchingServices(masterPort
, matching
, &slot_iterator
);
1203 if (kr
!= kIOReturnSuccess
) {
1204 SCLog(TRUE
, LOG_DEBUG
, CFSTR("pci_port IOServiceGetMatchingServices() failed, kr = 0x%x"), kr
);
1205 return MACH_PORT_NULL
;
1208 port_names
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1210 while ((slot
= IOIteratorNext(slot_iterator
)) != MACH_PORT_NULL
) {
1211 io_registry_entry_t child
;
1212 io_iterator_t child_iterator
= MACH_PORT_NULL
;
1214 kr
= IORegistryEntryCreateIterator(slot
,
1216 kIORegistryIterateRecursively
,
1218 if (kr
!= kIOReturnSuccess
) {
1219 SCLog(TRUE
, LOG_DEBUG
, CFSTR("pci_port IORegistryEntryCreateIterator() failed, kr = 0x%x"), kr
);
1220 CFRelease(port_names
);
1221 return MACH_PORT_NULL
;
1224 while ((child
= IOIteratorNext(child_iterator
)) != MACH_PORT_NULL
) {
1225 if (IOObjectConformsTo(child
, kIONetworkInterfaceClass
)) {
1226 CFStringRef if_bsdName
;
1228 if_bsdName
= IORegistryEntryCreateCFProperty(child
,
1229 CFSTR(kIOBSDNameKey
),
1232 if (if_bsdName
!= NULL
) {
1233 CFArrayAppendValue(port_names
, if_bsdName
);
1234 CFRelease(if_bsdName
);
1237 IOObjectRelease(child
);
1239 IOObjectRelease(child_iterator
);
1240 IOObjectRelease(slot
);
1242 IOObjectRelease(slot_iterator
);
1244 n
= CFArrayGetCount(port_names
);
1246 CFArraySortValues(port_names
, CFRangeMake(0, n
), compare_bsdNames
, NULL
);
1247 n
= CFArrayGetFirstIndexOfValue(port_names
, CFRangeMake(0, n
), bsdName
);
1248 if (n
!= kCFNotFound
) {
1249 port_name
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%d"), n
+ 1);
1253 CFRelease(port_names
);
1259 pci_slot_info(io_registry_entry_t interface
, CFStringRef
*slot_name
, CFStringRef
*port_name
)
1261 CFStringRef bsd_name
;
1263 CFTypeRef pci_slot_name
;
1268 bsd_name
= IORegistryEntryCreateCFProperty(interface
, CFSTR(kIOBSDNameKey
), NULL
, 0);
1269 if (bsd_name
== NULL
) {
1273 *slot_name
= pci_slot(interface
, &pci_slot_name
);
1274 if (*slot_name
!= NULL
) {
1275 if (pci_slot_name
!= NULL
) {
1276 *port_name
= pci_port(pci_slot_name
, bsd_name
);
1277 CFRelease(pci_slot_name
);
1282 CFRelease(bsd_name
);
1288 isBuiltin(io_registry_entry_t interface
)
1292 slot
= pci_slot(interface
, NULL
);
1294 // interfaces which have a "slot" are not built-in
1304 isBluetoothBuiltin(Boolean
*haveController
)
1306 Boolean builtin
= FALSE
;
1307 io_object_t hciController
;
1308 io_iterator_t iter
= MACH_PORT_NULL
;
1311 kr
= IOServiceGetMatchingServices(masterPort
,
1312 IOServiceMatching("IOBluetoothHCIController"),
1314 if ((kr
!= kIOReturnSuccess
) || (iter
== MACH_PORT_NULL
)) {
1315 if (kr
!= kIOReturnSuccess
) {
1316 SCLog(TRUE
, LOG_DEBUG
, CFSTR("isBluetoothBuiltin IOServiceGetMatchingServices() failed, kr = 0x%x"), kr
);
1318 *haveController
= FALSE
;
1321 *haveController
= TRUE
;
1323 hciController
= IOIteratorNext(iter
);
1324 IOObjectRelease(iter
);
1325 if(hciController
!= MACH_PORT_NULL
) {
1326 CFNumberRef idVendor
;
1328 idVendor
= IORegistryEntryCreateCFProperty(hciController
, CFSTR(kUSBVendorID
), NULL
, 0);
1329 if (idVendor
!= NULL
) {
1332 if (isA_CFNumber(idVendor
) &&
1333 CFNumberGetValue(idVendor
, kCFNumberIntType
, &idVendorVal
) &&
1334 (idVendorVal
== kIOUSBVendorIDAppleComputer
)) {
1338 CFRelease(idVendor
);
1341 IOObjectRelease(hciController
);
1349 #pragma mark Interface enumeration
1352 typedef Boolean (*processInterface
)(SCNetworkInterfacePrivateRef interfacePrivate
,
1353 io_registry_entry_t interface
,
1354 CFDictionaryRef interface_dict
,
1355 io_registry_entry_t controller
,
1356 CFDictionaryRef controller_dict
,
1357 io_registry_entry_t bus
,
1358 CFDictionaryRef bus_dict
);
1362 processNetworkInterface(SCNetworkInterfacePrivateRef interfacePrivate
,
1363 io_registry_entry_t interface
,
1364 CFDictionaryRef interface_dict
,
1365 io_registry_entry_t controller
,
1366 CFDictionaryRef controller_dict
,
1367 io_registry_entry_t bus
,
1368 CFDictionaryRef bus_dict
)
1378 num
= CFDictionaryGetValue(interface_dict
, CFSTR(kIOInterfaceType
));
1379 if (isA_CFNumber(num
) &&
1380 CFNumberGetValue(num
, kCFNumberIntType
, &ift
)) {
1381 interfacePrivate
->type
= CFRetain(num
);
1383 SCLog(TRUE
, LOG_DEBUG
, CFSTR("processNetworkInterface() failed, no interface type"));
1391 if ((IOObjectConformsTo(controller
, "IO80211Controller")) ||
1392 (IOObjectConformsTo(controller
, "AirPortPCI" )) ||
1393 (IOObjectConformsTo(controller
, "AirPortDriver" ))) {
1394 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeIEEE80211
;
1395 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeEthernet
;
1396 interfacePrivate
->sort_order
= kSortAirPort
;
1397 } else if (IOObjectConformsTo(controller
, "IOBluetoothBNEPDriver")) {
1398 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
;
1399 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeEthernet
;
1400 interfacePrivate
->sort_order
= kSortBluetoothPAN
;
1402 str
= IODictionaryCopyCFStringValue(bus_dict
, CFSTR("name"));
1403 if ((str
!= NULL
) && CFEqual(str
, CFSTR("radio"))) {
1404 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
; // ??
1405 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeEthernet
;
1406 interfacePrivate
->sort_order
= kSortOtherWireless
;
1408 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
;
1409 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeEthernet
;
1410 interfacePrivate
->sort_order
= kSortEthernet
;
1412 #if !TARGET_OS_IPHONE
1413 // BOND support only enabled for ethernet devices
1414 interfacePrivate
->supportsBond
= TRUE
;
1415 #endif // !TARGET_OS_IPHONE
1418 if (str
!= NULL
) CFRelease(str
);
1421 // check if WWAN Ethernet
1422 if (IOObjectConformsTo(controller
, "AppleUSBEthernetHost")) {
1423 interfacePrivate
->sort_order
= kSortTethered
;
1424 } else if (IOObjectConformsTo(controller
, "AppleUSBCDCECMData")) {
1425 interfacePrivate
->sort_order
= kSortWWANEthernet
;
1429 val
= isA_CFBoolean(CFDictionaryGetValue(interface_dict
, CFSTR(kIOBuiltin
)));
1431 val
= isA_CFBoolean(CFDictionaryGetValue(interface_dict
, CFSTR(kIOPrimaryInterface
)));
1434 interfacePrivate
->builtin
= CFBooleanGetValue(val
);
1436 interfacePrivate
->builtin
= isBuiltin(interface
);
1439 if (!interfacePrivate
->builtin
&&
1440 CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeIEEE80211
)) {
1441 // always treat AirPort interfaces as built-in
1442 interfacePrivate
->builtin
= TRUE
;
1446 interfacePrivate
->location
= IODictionaryCopyCFStringValue(interface_dict
, CFSTR(kIOLocation
));
1448 #if !TARGET_OS_IPHONE
1450 num
= CFDictionaryGetValue(controller_dict
, CFSTR(kIOFeatures
));
1451 if (isA_CFNumber(num
) &&
1452 CFNumberGetValue(num
, kCFNumberIntType
, & iVal
)) {
1453 if (iVal
& (kIONetworkFeatureHardwareVlan
| kIONetworkFeatureSoftwareVlan
)) {
1454 interfacePrivate
->supportsVLAN
= TRUE
;
1457 #endif // !TARGET_OS_IPHONE
1460 if (CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeIEEE80211
)) {
1461 interfacePrivate
->localized_key
= CFSTR("airport");
1462 } else if (interfacePrivate
->sort_order
== kSortBluetoothPAN
) {
1463 interfacePrivate
->localized_key
= CFSTR("bluetooth-pan");
1464 } else if (interfacePrivate
->sort_order
== kSortOtherWireless
) {
1465 interfacePrivate
->localized_key
= CFSTR("wireless");
1466 interfacePrivate
->localized_arg1
= CFRetain(CFSTR("")); // ??
1467 } else if (interfacePrivate
->builtin
) {
1468 if ((interfacePrivate
->location
== NULL
) ||
1469 (CFStringGetLength(interfacePrivate
->location
) == 0)) {
1470 interfacePrivate
->localized_key
= CFSTR("ether");
1472 interfacePrivate
->localized_key
= CFSTR("multiether");
1473 interfacePrivate
->localized_arg1
= CFRetain(interfacePrivate
->location
);
1476 CFStringRef provider
;
1478 // check provider class
1479 provider
= IORegistryEntrySearchCFProperty(interface
,
1481 CFSTR(kIOProviderClassKey
),
1483 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1484 if (provider
!= NULL
) {
1485 if (CFEqual(provider
, CFSTR("IOPCIDevice"))) {
1486 CFStringRef port_name
;
1487 CFStringRef slot_name
;
1489 if (pci_slot_info(interface
, &slot_name
, &port_name
)) {
1490 if (port_name
== NULL
) {
1491 interfacePrivate
->localized_key
= CFSTR("pci-ether");
1492 interfacePrivate
->localized_arg1
= slot_name
;
1494 interfacePrivate
->localized_key
= CFSTR("pci-multiether");
1495 interfacePrivate
->localized_arg1
= slot_name
;
1496 interfacePrivate
->localized_arg2
= port_name
;
1499 } else if (CFEqual(provider
, CFSTR("IOUSBDevice")) ||
1500 CFEqual(provider
, CFSTR("IOUSBInterface"))) {
1501 // check if a "Product Name" has been provided
1502 val
= IORegistryEntrySearchCFProperty(interface
,
1504 CFSTR(kIOPropertyProductNameKey
),
1506 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1508 // check if a "USB Product Name" has been provided
1509 val
= IORegistryEntrySearchCFProperty(interface
,
1511 CFSTR(kUSBProductString
),
1513 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1516 CFStringRef productName
;
1518 productName
= IOCopyCFStringValue(val
);
1521 if (productName
!= NULL
) {
1522 if (CFStringGetLength(productName
) > 0) {
1523 // if we have a [somewhat reasonable?] product name
1524 if (interfacePrivate
->name
!= NULL
) {
1525 CFRelease(interfacePrivate
->name
);
1527 interfacePrivate
->name
= CFRetain(productName
);
1528 if (interfacePrivate
->localized_name
!= NULL
) {
1529 CFRelease(interfacePrivate
->localized_name
);
1531 interfacePrivate
->localized_name
= copy_interface_string(bundle
, productName
, TRUE
);
1534 CFRelease(productName
);
1537 interfacePrivate
->localized_key
= CFSTR("usb-ether");
1538 interfacePrivate
->localized_arg1
= IODictionaryCopyCFStringValue(interface_dict
, CFSTR(kIOBSDNameKey
));
1541 CFRelease(provider
);
1544 if (interfacePrivate
->localized_key
== NULL
) {
1545 // if no provider, not a PCI device, or no slot information
1546 interfacePrivate
->localized_key
= CFSTR("generic-ether");
1547 interfacePrivate
->localized_arg1
= IODictionaryCopyCFStringValue(interface_dict
, CFSTR(kIOBSDNameKey
));
1554 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeFireWire
;
1557 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeFireWire
;
1560 interfacePrivate
->builtin
= isBuiltin(interface
);
1563 interfacePrivate
->sort_order
= kSortFireWire
;
1566 if (interfacePrivate
->builtin
) {
1567 interfacePrivate
->localized_key
= CFSTR("firewire");
1569 CFStringRef slot_name
;
1571 slot_name
= pci_slot(interface
, NULL
);
1572 if (slot_name
!= NULL
) {
1573 interfacePrivate
->localized_key
= CFSTR("pci-firewire");
1574 interfacePrivate
->localized_arg1
= slot_name
;
1580 SCLog(TRUE
, LOG_DEBUG
, CFSTR("processNetworkInterface() failed, unknown interface type = %d"), ift
);
1585 interfacePrivate
->entity_device
= IODictionaryCopyCFStringValue(interface_dict
, CFSTR(kIOBSDNameKey
));
1587 // Hardware (MAC) address
1588 data
= CFDictionaryGetValue(controller_dict
, CFSTR(kIOMACAddress
));
1589 if (isA_CFData(data
)) {
1590 interfacePrivate
->address
= CFRetain(data
);
1594 num
= CFDictionaryGetValue(interface_dict
, CFSTR(kIOInterfaceUnit
));
1595 if (isA_CFNumber(num
) &&
1596 CFNumberGetValue(num
, kCFNumberIntType
, & iVal
)) {
1597 interfacePrivate
->unit
= CFRetain(num
);
1605 set_connection_script(SCNetworkInterfacePrivateRef interfacePrivate
, CFStringRef script
)
1607 CFDictionaryRef dict
;
1608 CFMutableDictionaryRef newDict
;
1610 if (interfacePrivate
->overrides
== NULL
) {
1611 interfacePrivate
->overrides
= CFDictionaryCreateMutable(NULL
,
1613 &kCFTypeDictionaryKeyCallBacks
,
1614 &kCFTypeDictionaryValueCallBacks
);
1617 dict
= CFDictionaryGetValue(interfacePrivate
->overrides
, kSCNetworkInterfaceTypeModem
);
1619 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
1621 newDict
= CFDictionaryCreateMutable(NULL
,
1623 &kCFTypeDictionaryKeyCallBacks
,
1624 &kCFTypeDictionaryValueCallBacks
);
1626 if (script
!= NULL
) {
1627 CFDictionarySetValue(newDict
, kSCPropNetModemConnectionScript
, script
);
1629 CFDictionaryRemoveValue(newDict
, kSCPropNetModemConnectionScript
);
1631 if (CFDictionaryGetCount(newDict
) > 0) {
1632 CFDictionarySetValue(interfacePrivate
->overrides
, kSCNetworkInterfaceTypeModem
, newDict
);
1634 CFDictionaryRemoveValue(interfacePrivate
->overrides
, kSCNetworkInterfaceTypeModem
);
1638 if (CFDictionaryGetCount(interfacePrivate
->overrides
) == 0) {
1639 CFRelease(interfacePrivate
->overrides
);
1640 interfacePrivate
->overrides
= NULL
;
1647 is_valid_connection_script(CFStringRef script
)
1649 char ccl
[MAXPATHLEN
];
1650 char path
[MAXPATHLEN
];
1651 NSSearchPathEnumerationState state
;
1653 (void) _SC_cfstring_to_cstring(script
,
1656 kCFStringEncodingUTF8
);
1658 state
= NSStartSearchPathEnumeration(NSLibraryDirectory
,
1659 NSLocalDomainMask
|NSSystemDomainMask
);
1660 while ((state
= NSGetNextSearchPathEnumeration(state
, path
))) {
1662 struct stat statBuf
;
1664 if (ccl
[0] == '/') {
1665 path
[0] = '\0'; // if modemCCL is a full path
1667 strlcat(path
, "/Modem Scripts/", sizeof(path
));
1669 strlcat(path
, ccl
, sizeof(path
));
1671 if (stat(path
, &statBuf
) != 0) {
1672 if (errno
== ENOENT
) {
1676 SCLog(TRUE
, LOG_DEBUG
,
1677 CFSTR("processSerialInterface stat() failed: %s"),
1681 if (S_ISREG(statBuf
.st_mode
)) {
1682 // if we have a valid CCL script
1686 #define BUNDLE_EXT ".ccl"
1687 #define BUNDLE_EXT_LEN sizeof(BUNDLE_EXT) - 1
1692 if ((n
<= BUNDLE_EXT_LEN
) ||
1693 (strstr(&path
[n
- BUNDLE_EXT_LEN
], BUNDLE_EXT
) == NULL
)) {
1694 strlcat(path
, BUNDLE_EXT
, sizeof(path
));
1695 if (stat(path
, &statBuf
) != 0) {
1696 if (errno
== ENOENT
) {
1700 SCLog(TRUE
, LOG_DEBUG
,
1701 CFSTR("processSerialInterface stat() failed: %s"),
1706 if (S_ISDIR(statBuf
.st_mode
)) {
1707 // if we have a valid CCL bundle
1717 processSerialInterface(SCNetworkInterfacePrivateRef interfacePrivate
,
1718 io_registry_entry_t interface
,
1719 CFDictionaryRef interface_dict
,
1720 io_registry_entry_t controller
,
1721 CFDictionaryRef controller_dict
,
1722 io_registry_entry_t bus
,
1723 CFDictionaryRef bus_dict
)
1725 CFStringRef base
= NULL
;
1727 Boolean isModem
= FALSE
;
1728 Boolean isWWAN
= FALSE
;
1729 CFStringRef modemCCL
= NULL
;
1734 val
= IORegistryEntrySearchCFProperty(interface
,
1736 CFSTR("HiddenPort"),
1738 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1741 return FALSE
; // if this interface should not be exposed
1744 // check if initializing
1745 val
= IORegistryEntrySearchCFProperty(interface
,
1747 CFSTR("Initializing"),
1749 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1751 Boolean initializing
;
1753 initializing
= isA_CFBoolean(val
) && CFBooleanGetValue(val
);
1756 return FALSE
; // if this interface is still initializing
1761 val
= IORegistryEntrySearchCFProperty(interface
,
1765 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1767 isWWAN
= isA_CFBoolean(val
) && CFBooleanGetValue(val
);
1772 interfacePrivate
->entity_device
= IODictionaryCopyCFStringValue(interface_dict
, CFSTR(kIOTTYDeviceKey
));
1773 if (interfacePrivate
->entity_device
== NULL
) {
1777 base
= IODictionaryCopyCFStringValue(interface_dict
, CFSTR(kIOTTYBaseNameKey
));
1779 base
= CFRetain(interfacePrivate
->entity_device
);
1785 * Exclude ports named "irda" because otherwise the IrDA ports on the
1786 * original iMac (rev's A through D) show up as serial ports. Given
1787 * that only the rev A actually had an IrDA port, and Mac OS X doesn't
1788 * even support it, these ports definitely shouldn't be listed.
1790 if (CFStringCompare(base
,
1792 kCFCompareCaseInsensitive
) == kCFCompareEqualTo
) {
1796 if (IOStringValueHasPrefix(base
, CFSTR("bluetooth"))) {
1797 Boolean haveController
= FALSE
;
1800 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeBluetooth
;
1801 interfacePrivate
->sort_order
= kSortBluetooth
;
1802 interfacePrivate
->builtin
= isBluetoothBuiltin(&haveController
);
1803 if (!haveController
) {
1804 // if device with no controller present
1807 } else if (IOStringValueHasPrefix(base
, CFSTR("irda-ircomm"))) {
1809 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeIrDA
;
1810 interfacePrivate
->sort_order
= kSortIrDA
;
1811 } else if (isWWAN
) {
1813 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeWWAN
;
1814 interfacePrivate
->sort_order
= kSortWWAN
;
1817 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeModem
;
1818 interfacePrivate
->sort_order
= kSortModem
;
1821 val
= IORegistryEntrySearchCFProperty(interface
,
1823 CFSTR(kIODeviceSupportsHoldKey
),
1825 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1829 if (isA_CFNumber(val
) &&
1830 CFNumberGetValue(val
, kCFNumberSInt32Type
, &v92
)) {
1831 interfacePrivate
->modemIsV92
= (v92
== 1);
1838 interfacePrivate
->entity_type
= kSCEntNetModem
;
1840 // Entity (Hardware)
1841 ift
= CFDictionaryGetValue(interface_dict
, CFSTR(kIOSerialBSDTypeKey
));
1842 if (!isA_CFString(ift
)) {
1846 if (CFEqual(ift
, CFSTR(kIOSerialBSDModemType
))) {
1850 if (CFEqual(base
, CFSTR("modem"))) {
1851 interfacePrivate
->builtin
= TRUE
;
1852 interfacePrivate
->sort_order
= kSortInternalModem
;
1853 } else if (CFEqual(base
, CFSTR("usbmodem"))) {
1854 interfacePrivate
->sort_order
= kSortUSBModem
;
1856 } else if (CFEqual(ift
, CFSTR(kIOSerialBSDRS232Type
))) {
1858 interfacePrivate
->sort_order
= kSortSerialPort
;
1863 // configuration template overrides
1864 val
= IORegistryEntrySearchCFProperty(interface
,
1866 CFSTR("DevicePPPOverrides"),
1868 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1870 if (isA_CFDictionary(val
)) {
1871 if (interfacePrivate
->overrides
== NULL
) {
1872 interfacePrivate
->overrides
= CFDictionaryCreateMutable(NULL
,
1874 &kCFTypeDictionaryKeyCallBacks
,
1875 &kCFTypeDictionaryValueCallBacks
);
1877 CFDictionarySetValue(interfacePrivate
->overrides
, kSCNetworkInterfaceTypePPP
, val
);
1882 val
= IORegistryEntrySearchCFProperty(interface
,
1884 CFSTR("DeviceModemOverrides"),
1886 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1888 if (isA_CFDictionary(val
)) {
1889 CFStringRef uniqueID
;
1891 if (interfacePrivate
->overrides
== NULL
) {
1892 interfacePrivate
->overrides
= CFDictionaryCreateMutable(NULL
,
1894 &kCFTypeDictionaryKeyCallBacks
,
1895 &kCFTypeDictionaryValueCallBacks
);
1897 CFDictionarySetValue(interfacePrivate
->overrides
, kSCNetworkInterfaceTypeModem
, val
);
1899 modemCCL
= CFDictionaryGetValue(val
, kSCPropNetModemConnectionScript
);
1900 modemCCL
= isA_CFString(modemCCL
);
1902 uniqueID
= CFDictionaryGetValue(val
, CFSTR("UniqueIdentifier"));
1903 uniqueID
= isA_CFString(uniqueID
);
1904 if (uniqueID
!= NULL
) {
1905 // retain the device's base name and the unique id
1906 CFRelease(interfacePrivate
->entity_device
);
1907 interfacePrivate
->entity_device
= CFRetain(base
);
1908 interfacePrivate
->entity_device_unique
= CFStringCreateCopy(NULL
, uniqueID
);
1914 // if not part of the DeviceModemOverrides, look harder for the modem CCL
1915 if (modemCCL
== NULL
) {
1916 val
= IORegistryEntrySearchCFProperty(interface
,
1920 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1922 modemCCL
= IOCopyCFStringValue(val
);
1923 if (modemCCL
!= NULL
) {
1924 set_connection_script(interfacePrivate
, modemCCL
);
1925 CFRelease(modemCCL
);
1933 if (CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeIrDA
)) {
1934 interfacePrivate
->localized_key
= CFSTR("irda");
1935 } else if (CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeBluetooth
)) {
1936 interfacePrivate
->localized_key
= CFSTR("bluetooth");
1938 CFStringRef localized
= NULL
;
1939 CFStringRef name
= NULL
;
1940 CFMutableStringRef port
;
1942 port
= CFStringCreateMutableCopy(NULL
, 0, base
);
1943 CFStringLowercase(port
, NULL
);
1946 CFStringAppend(port
, CFSTR("-port"));
1949 // set non-localized name
1950 if (bundle
!= NULL
) {
1951 name
= copy_interface_string(bundle
, port
, FALSE
);
1954 if (!CFEqual(port
, name
)) {
1955 // if [English] localization available
1956 interfacePrivate
->name
= name
;
1958 // if no [English] localization available, use TTY base name
1960 interfacePrivate
->name
= CFStringCreateCopy(NULL
, base
);
1963 interfacePrivate
->name
= CFStringCreateCopy(NULL
, base
);
1966 // set localized name
1967 if (bundle
!= NULL
) {
1968 localized
= copy_interface_string(bundle
, port
, TRUE
);
1970 if (localized
!= NULL
) {
1971 if (!CFEqual(port
, localized
)) {
1972 // if localization available
1973 interfacePrivate
->localized_name
= localized
;
1975 // if no localization available, use TTY base name
1976 CFRelease(localized
);
1977 interfacePrivate
->localized_name
= CFStringCreateCopy(NULL
, base
);
1980 interfacePrivate
->localized_name
= CFStringCreateCopy(NULL
, base
);
1983 if (!isModem
|| !CFEqual(base
, CFSTR("modem"))) {
1984 CFStringRef productName
;
1986 // check if a "Product Name" has been provided
1987 val
= IORegistryEntrySearchCFProperty(interface
,
1989 CFSTR(kIOPropertyProductNameKey
),
1991 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1993 // check if a "USB Product Name" has been provided
1994 val
= IORegistryEntrySearchCFProperty(interface
,
1996 CFSTR(kUSBProductString
),
1998 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
2001 productName
= IOCopyCFStringValue(val
);
2004 if (productName
!= NULL
) {
2005 if (CFStringGetLength(productName
) > 0) {
2006 // if we have a [somewhat reasonable?] product name
2007 if (interfacePrivate
->name
!= NULL
) {
2008 CFRelease(interfacePrivate
->name
);
2010 interfacePrivate
->name
= CFRetain(productName
);
2011 if (interfacePrivate
->localized_name
!= NULL
) {
2012 CFRelease(interfacePrivate
->localized_name
);
2014 interfacePrivate
->localized_name
= copy_interface_string(bundle
, productName
, TRUE
);
2016 // if not provided, also check if the product name
2017 // matches a CCL script
2018 if ((modemCCL
== NULL
) &&
2019 is_valid_connection_script(productName
)) {
2020 set_connection_script(interfacePrivate
, productName
);
2024 CFRelease(productName
);
2036 if (!ok
&& (interfacePrivate
->entity_device
!= NULL
)) {
2037 CFRelease(interfacePrivate
->entity_device
);
2038 interfacePrivate
->entity_device
= NULL
;
2040 if (base
!= NULL
) CFRelease(base
);
2046 static SCNetworkInterfaceRef
2047 createInterface(io_registry_entry_t interface
, processInterface func
)
2049 io_registry_entry_t bus
= MACH_PORT_NULL
;
2050 CFMutableDictionaryRef bus_dict
= NULL
;
2051 io_registry_entry_t controller
= MACH_PORT_NULL
;
2052 CFMutableDictionaryRef controller_dict
= NULL
;
2053 SCNetworkInterfacePrivateRef interfacePrivate
= NULL
;
2054 CFMutableDictionaryRef interface_dict
= NULL
;
2058 kr
= IORegistryEntryGetPath(interface
, kIOServicePlane
, path
);
2059 if (kr
!= kIOReturnSuccess
) {
2060 SCLog(TRUE
, LOG_DEBUG
, CFSTR("createInterface IORegistryEntryGetPath() failed, kr = 0x%x"), kr
);
2064 kr
= IORegistryEntryCreateCFProperties(interface
, &interface_dict
, NULL
, kNilOptions
);
2065 if (kr
!= kIOReturnSuccess
) {
2066 SCLog(TRUE
, LOG_DEBUG
, CFSTR("createInterface IORegistryEntryCreateCFProperties() failed, kr = 0x%x"), kr
);
2070 /* get the controller node */
2071 kr
= IORegistryEntryGetParentEntry(interface
, kIOServicePlane
, &controller
);
2072 if (kr
!= KERN_SUCCESS
) {
2073 SCLog(TRUE
, LOG_DEBUG
, CFSTR("createInterface IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr
);
2077 /* get the dictionary associated with the node */
2078 kr
= IORegistryEntryCreateCFProperties(controller
, &controller_dict
, NULL
, kNilOptions
);
2079 if (kr
!= KERN_SUCCESS
) {
2080 SCLog(TRUE
, LOG_DEBUG
, CFSTR("createInterface IORegistryEntryCreateCFProperties() failed, kr = 0x%x"), kr
);
2084 /* get the bus node */
2085 kr
= IORegistryEntryGetParentEntry(controller
, kIOServicePlane
, &bus
);
2086 if (kr
!= KERN_SUCCESS
) {
2087 SCLog(TRUE
, LOG_DEBUG
, CFSTR("createInterface IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr
);
2091 /* get the dictionary associated with the node */
2092 kr
= IORegistryEntryCreateCFProperties(bus
, &bus_dict
, NULL
, kNilOptions
);
2093 if (kr
!= KERN_SUCCESS
) {
2094 SCLog(TRUE
, LOG_DEBUG
, CFSTR("createInterface IORegistryEntryCreateCFProperties() failed, kr = 0x%x"), kr
);
2098 interfacePrivate
= __SCNetworkInterfaceCreatePrivate(NULL
, NULL
, NULL
, NULL
, path
);
2100 if ((*func
)(interfacePrivate
, interface
, interface_dict
, controller
, controller_dict
, bus
, bus_dict
)) {
2103 /* check user-notification / auto-configuration preferences */
2104 val
= IORegistryEntrySearchCFProperty(interface
,
2106 kSCNetworkInterfaceConfigurationActionKey
,
2108 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
2110 if (isA_CFString(val
)) {
2111 interfacePrivate
->configurationAction
= CFRetain(val
);
2116 CFRelease(interfacePrivate
);
2117 interfacePrivate
= NULL
;
2122 if (interface_dict
!= NULL
) CFRelease(interface_dict
);
2124 if (controller
!= MACH_PORT_NULL
) IOObjectRelease(controller
);
2125 if (controller_dict
!= NULL
) CFRelease(controller_dict
);
2127 if (bus
!= MACH_PORT_NULL
) IOObjectRelease(bus
);
2128 if (bus_dict
!= NULL
) CFRelease(bus_dict
);
2130 return (SCNetworkInterfaceRef
)interfacePrivate
;
2135 findMatchingInterfaces(CFDictionaryRef matching
, processInterface func
)
2137 CFMutableArrayRef interfaces
;
2138 io_registry_entry_t interface
;
2140 io_iterator_t iterator
= MACH_PORT_NULL
;
2142 kr
= IOServiceGetMatchingServices(masterPort
, matching
, &iterator
);
2143 if (kr
!= kIOReturnSuccess
) {
2144 SCLog(TRUE
, LOG_DEBUG
, CFSTR("findMatchingInterfaces IOServiceGetMatchingServices() failed, kr = 0x%x"), kr
);
2148 interfaces
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
2150 while ((interface
= IOIteratorNext(iterator
)) != MACH_PORT_NULL
) {
2151 SCNetworkInterfaceRef match
;
2153 match
= createInterface(interface
, func
);
2154 if (match
!= NULL
) {
2155 CFArrayAppendValue(interfaces
, match
);
2159 IOObjectRelease(interface
);
2162 IOObjectRelease(iterator
);
2169 #pragma mark helper functions
2173 findConfiguration(CFStringRef interface_type
)
2177 for (i
= 0; i
< sizeof(configurations
)/sizeof(configurations
[0]); i
++) {
2178 if (CFEqual(interface_type
, *configurations
[i
].interface_type
)) {
2189 __SCNetworkInterfaceGetDefaultConfigurationType(SCNetworkInterfaceRef interface
)
2191 CFIndex interfaceIndex
;
2192 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2194 if (interfacePrivate
->serviceID
== NULL
) {
2195 // if not associated with a service (yet)
2196 _SCErrorSet(kSCStatusInvalidArgument
);
2200 interfaceIndex
= findConfiguration(interfacePrivate
->interface_type
);
2201 if (interfaceIndex
== kCFNotFound
) {
2202 // unknown interface type, use per-service configuration preferences
2203 return interfacePrivate
->interface_type
; // entity
2206 if (configurations
[interfaceIndex
].entity_hardware
!= NULL
) {
2207 // if configuration information can be associated with this interface type
2208 return *configurations
[interfaceIndex
].entity_hardware
;
2211 _SCErrorSet(kSCStatusInvalidArgument
);
2218 __SCNetworkInterfaceIsValidExtendedConfigurationType(SCNetworkInterfaceRef interface
,
2219 CFStringRef extendedType
,
2220 Boolean requirePerInterface
)
2222 CFStringRef defaultType
;
2223 CFIndex extendedIndex
;
2224 CFIndex interfaceIndex
;
2225 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2226 Boolean isL2TP
= FALSE
;
2229 defaultType
= __SCNetworkInterfaceGetDefaultConfigurationType(interface
);
2230 if (defaultType
== NULL
) {
2234 if (CFEqual(extendedType
, defaultType
)) {
2235 // extended and default configuration types cannot conflict
2239 interfaceIndex
= findConfiguration(interfacePrivate
->interface_type
);
2240 if (interfaceIndex
== kCFNotFound
) {
2241 // configuration information for unknown interface type's
2242 // are stored along with the service and we don't allow
2243 // per-service extended configurations
2247 if (CFEqual(extendedType
, kSCEntNetIPSec
)) {
2248 CFStringRef interfaceType
;
2250 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
2251 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
)) {
2252 SCNetworkInterfaceRef child
;
2254 child
= SCNetworkInterfaceGetInterface(interface
);
2255 if (child
!= NULL
) {
2256 interfaceType
= SCNetworkInterfaceGetInterfaceType(child
);
2257 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeL2TP
)) {
2264 if (requirePerInterface
&&
2265 !configurations
[interfaceIndex
].per_interface_config
&&
2267 // we don't allow per-service extended configurations (except
2268 // that we do allow IPSec as an extended type for PPP->L2TP)
2272 extendedIndex
= findConfiguration(extendedType
);
2273 if ((extendedIndex
!= kCFNotFound
) && !isL2TP
) {
2274 // extended type cannot match a known interface type (except
2275 // that we do allow IPSec as an extended type for PPP->L2TP)
2281 * Do we match specific/known extended configuration types (e.g. EAPOL)
2282 * and ensure that any non-standard extended configuration types be of
2283 * the form com.myCompany.myType?
2292 _SCErrorSet(kSCStatusInvalidArgument
);
2299 CFStringRef defaultType
;
2300 CFMutableArrayRef types
;
2301 } extendedConfiguration
, *extendedConfigurationRef
;
2305 __addExtendedConfigurationType(const void *key
, const void *value
, void *context
)
2307 CFStringRef extendedType
= (CFStringRef
)key
;
2308 extendedConfigurationRef myContextRef
= (extendedConfigurationRef
)context
;
2310 if (CFEqual(extendedType
, myContextRef
->defaultType
)) {
2311 // do not include the default configuration type
2315 if (CFArrayContainsValue(myContextRef
->types
,
2316 CFRangeMake(0, CFArrayGetCount(myContextRef
->types
)),
2318 // if extendedType already has already been added
2322 CFArrayAppendValue(myContextRef
->types
, extendedType
);
2329 extendedConfigurationTypes(SCNetworkInterfaceRef interface
)
2332 CFIndex interfaceIndex
;
2333 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2334 extendedConfiguration myContext
;
2335 SCNetworkServiceRef service
;
2339 myContext
.defaultType
= __SCNetworkInterfaceGetDefaultConfigurationType(interface
);
2340 if (myContext
.defaultType
== NULL
) {
2341 myContext
.types
= NULL
;
2345 myContext
.types
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
2347 if (interfacePrivate
->serviceID
== NULL
) {
2348 // if not associated with a service (yet)
2352 interfaceIndex
= findConfiguration(interfacePrivate
->interface_type
);
2353 if (interfaceIndex
== kCFNotFound
) {
2354 // we don't allow per-service extended configurations
2358 if (!configurations
[interfaceIndex
].per_interface_config
) {
2359 // known interface type but we still don't allow
2360 // per-service extended configurations
2364 service
= (SCNetworkServiceRef
)__SCNetworkServiceCreatePrivate(NULL
,
2365 interfacePrivate
->prefs
,
2366 interfacePrivate
->serviceID
,
2369 sets
= SCNetworkSetCopyAll(interfacePrivate
->prefs
);
2370 n
= (sets
!= NULL
) ? CFArrayGetCount(sets
) : 0;
2372 for (i
= 0; i
< n
; i
++) {
2373 CFDictionaryRef configs
;
2376 CFArrayRef services
;
2377 SCNetworkSetRef set
;
2379 set
= CFArrayGetValueAtIndex(sets
, i
);
2380 services
= SCNetworkSetCopyServices(set
);
2381 found
= CFArrayContainsValue(services
,
2382 CFRangeMake(0, CFArrayGetCount(services
)),
2384 CFRelease(services
);
2390 // add stored extended configuration types
2391 path
= SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL
, // allocator
2392 SCNetworkSetGetSetID(set
), // set
2393 interfacePrivate
->entity_device
, // service
2395 configs
= __getPrefsConfiguration(interfacePrivate
->prefs
, path
);
2397 if (isA_CFDictionary(configs
)) {
2398 CFDictionaryApplyFunction(configs
,
2399 __addExtendedConfigurationType
,
2403 // add not-yet-stored extended configuration types
2404 if (interfacePrivate
->unsaved
!= NULL
) {
2405 CFDictionaryApplyFunction(interfacePrivate
->unsaved
,
2406 __addExtendedConfigurationType
,
2414 if (sets
!= NULL
) CFRelease(sets
);
2418 return myContext
.types
;
2423 copyConfigurationPaths(SCNetworkInterfacePrivateRef interfacePrivate
,
2424 CFStringRef extendedType
)
2426 CFMutableArrayRef array
;
2428 CFIndex interfaceIndex
;
2431 SCNetworkServiceRef service
;
2434 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
2436 interfaceIndex
= findConfiguration(interfacePrivate
->interface_type
);
2437 if (interfaceIndex
== kCFNotFound
) {
2438 // unknown interface type, use per-service configuration preferences
2439 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
2440 interfacePrivate
->serviceID
, // service
2441 extendedType
); // entity
2442 CFArrayAppendValue(array
, path
);
2447 if (!configurations
[interfaceIndex
].per_interface_config
) {
2448 // known interface type, per-service configuration preferences
2449 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
2450 interfacePrivate
->serviceID
, // service
2451 extendedType
); // entity
2452 CFArrayAppendValue(array
, path
);
2457 // known interface type, per-interface configuration preferences
2459 // 1. look for all sets which contain the associated service
2460 // 2. add a per-set path for the interface configuration for
2463 service
= (SCNetworkServiceRef
)__SCNetworkServiceCreatePrivate(NULL
,
2464 interfacePrivate
->prefs
,
2465 interfacePrivate
->serviceID
,
2466 (SCNetworkInterfaceRef
)interfacePrivate
);
2468 sets
= SCNetworkSetCopyAll(interfacePrivate
->prefs
);
2469 n
= (sets
!= NULL
) ? CFArrayGetCount(sets
) : 0;
2471 for (i
= 0; i
< n
; i
++) {
2472 CFArrayRef services
;
2473 SCNetworkSetRef set
;
2475 set
= CFArrayGetValueAtIndex(sets
, i
);
2476 services
= SCNetworkSetCopyServices(set
);
2477 if (CFArrayContainsValue(services
,
2478 CFRangeMake(0, CFArrayGetCount(services
)),
2480 path
= SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL
, // allocator
2481 SCNetworkSetGetSetID(set
), // set
2482 interfacePrivate
->entity_device
, // service
2483 extendedType
); // entity
2484 CFArrayAppendValue(array
, path
);
2487 CFRelease(services
);
2490 if (CFArrayGetCount(array
) == 0) {
2496 if (sets
!= NULL
) CFRelease(sets
);
2502 #pragma mark SCNetworkInterface <--> preferences entity
2507 __SCNetworkInterfaceCopyInterfaceEntity(SCNetworkInterfaceRef interface
)
2509 CFMutableDictionaryRef entity
;
2510 CFIndex interfaceIndex
;
2511 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2513 entity
= CFDictionaryCreateMutable(NULL
,
2515 &kCFTypeDictionaryKeyCallBacks
,
2516 &kCFTypeDictionaryValueCallBacks
);
2517 if (interfacePrivate
->entity_type
!= NULL
) {
2518 CFDictionarySetValue(entity
,
2519 kSCPropNetInterfaceType
,
2520 interfacePrivate
->entity_type
);
2522 if (interfacePrivate
->entity_subtype
!= NULL
) {
2523 CFDictionarySetValue(entity
,
2524 kSCPropNetInterfaceSubType
,
2525 interfacePrivate
->entity_subtype
);
2527 if (interfacePrivate
->entity_device
!= NULL
) {
2528 CFDictionarySetValue(entity
,
2529 kSCPropNetInterfaceDeviceName
,
2530 interfacePrivate
->entity_device
);
2532 if (interfacePrivate
->entity_device_unique
!= NULL
) {
2533 CFDictionarySetValue(entity
,
2534 CFSTR("DeviceUniqueIdentifier"),
2535 interfacePrivate
->entity_device_unique
);
2538 // match the "hardware" with the lowest layer
2540 SCNetworkInterfaceRef nextInterface
;
2542 nextInterface
= SCNetworkInterfaceGetInterface(interface
);
2543 if (nextInterface
== NULL
) {
2547 interface
= nextInterface
;
2549 interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2551 if (CFEqual(interface
, kSCNetworkInterfaceIPv4
)) {
2555 interfaceIndex
= findConfiguration(interfacePrivate
->interface_type
);
2556 if (interfaceIndex
!= kCFNotFound
) {
2557 if (configurations
[interfaceIndex
].entity_hardware
!= NULL
) {
2558 CFDictionarySetValue(entity
,
2559 kSCPropNetInterfaceHardware
,
2560 *configurations
[interfaceIndex
].entity_hardware
);
2563 CFDictionarySetValue(entity
,
2564 kSCPropNetInterfaceHardware
,
2565 interfacePrivate
->interface_type
);
2568 // add the localized display name (which will only be used when/if the
2569 // interface is removed from the system)
2570 CFDictionarySetValue(entity
,
2571 kSCPropUserDefinedName
,
2572 SCNetworkInterfaceGetLocalizedDisplayName(interface
));
2574 // note that this is a V.92 capable modem
2575 if (CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeModem
) &&
2576 interfacePrivate
->modemIsV92
) {
2580 num
= CFNumberCreate(NULL
, kCFNumberIntType
, &one
);
2581 CFDictionarySetValue(entity
,
2582 kSCPropNetInterfaceSupportsModemOnHold
,
2591 #if !TARGET_OS_IPHONE
2592 static SCNetworkInterfaceRef
2593 findInterface(CFArrayRef interfaces
, CFStringRef match_if
)
2598 n
= CFArrayGetCount(interfaces
);
2599 for (i
= 0; i
< n
; i
++) {
2600 SCNetworkInterfaceRef interface
= CFArrayGetValueAtIndex(interfaces
, i
);
2601 CFStringRef interfaceName
;
2603 interfaceName
= SCNetworkInterfaceGetBSDName(interface
);
2604 if ((interfaceName
!= NULL
) && CFEqual(interfaceName
, match_if
)) {
2605 CFRetain(interface
);
2614 static SCNetworkInterfaceRef
2615 findBondInterface(SCPreferencesRef prefs
, CFStringRef ifDevice
)
2618 SCNetworkInterfaceRef interface
= NULL
;
2620 if (prefs
== NULL
) {
2624 // check if the interface is an Ethernet Bond
2625 bonds
= SCBondInterfaceCopyAll(prefs
);
2626 if (bonds
!= NULL
) {
2627 interface
= findInterface(bonds
, ifDevice
);
2633 static SCNetworkInterfaceRef
2634 findVLANInterface(SCPreferencesRef prefs
, CFStringRef ifDevice
)
2636 SCNetworkInterfaceRef interface
= NULL
;
2639 if (prefs
== NULL
) {
2643 // check if the interface is a VLAN
2644 vlans
= SCVLANInterfaceCopyAll(prefs
);
2645 if (vlans
!= NULL
) {
2646 interface
= findInterface(vlans
, ifDevice
);
2651 #endif // !TARGET_OS_IPHONE
2654 SCNetworkInterfaceRef
2655 _SCNetworkInterfaceCreateWithBSDName(CFAllocatorRef allocator
,
2656 CFStringRef bsdName
,
2659 CFMutableDictionaryRef entity
;
2660 SCNetworkInterfaceRef interface
;
2662 entity
= CFDictionaryCreateMutable(NULL
,
2664 &kCFTypeDictionaryKeyCallBacks
,
2665 &kCFTypeDictionaryValueCallBacks
);
2666 CFDictionarySetValue(entity
, kSCPropNetInterfaceDeviceName
, bsdName
);
2667 #if !TARGET_OS_IPHONE
2668 if ((flags
& kIncludeBondInterfaces
) == 0) {
2669 CFDictionarySetValue(entity
, CFSTR("_NO_BOND_INTERFACES_"), kCFBooleanTrue
);
2671 if ((flags
& kIncludeVLANInterfaces
) == 0) {
2672 CFDictionarySetValue(entity
, CFSTR("_NO_VLAN_INTERFACES_"), kCFBooleanTrue
);
2674 #endif // !TARGET_OS_IPHONE
2675 interface
= _SCNetworkInterfaceCreateWithEntity(NULL
, entity
, NULL
);
2683 __SCNetworkInterfaceSetService(SCNetworkInterfaceRef interface
,
2684 SCNetworkServiceRef service
)
2686 SCNetworkInterfacePrivateRef interfacePrivate
;
2687 SCNetworkServicePrivateRef servicePrivate
;
2689 interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2690 if (interfacePrivate
->prefs
!= NULL
) {
2691 CFRelease(interfacePrivate
->prefs
);
2692 interfacePrivate
->prefs
= NULL
;
2694 if (interfacePrivate
->serviceID
!= NULL
) {
2695 CFRelease(interfacePrivate
->serviceID
);
2696 interfacePrivate
->serviceID
= NULL
;
2699 servicePrivate
= (SCNetworkServicePrivateRef
)service
;
2700 if (servicePrivate
->prefs
!= NULL
) {
2701 interfacePrivate
->prefs
= CFRetain(servicePrivate
->prefs
);
2703 if (servicePrivate
->serviceID
!= NULL
) {
2704 interfacePrivate
->serviceID
= CFRetain(servicePrivate
->serviceID
);
2712 _SCNetworkInterfaceMatchesName(CFStringRef name
, CFStringRef key
)
2717 if (bundle
== NULL
) {
2722 if (!isA_CFString(name
)) {
2723 // if no interface "name"
2727 // check non-localized name for a match
2728 str
= copy_interface_string(bundle
, key
, FALSE
);
2730 match
= CFEqual(name
, str
);
2737 // check localized name for a match
2738 str
= copy_interface_string(bundle
, key
, TRUE
);
2740 match
= CFEqual(name
, str
);
2751 SCNetworkInterfaceRef
2752 _SCNetworkInterfaceCreateWithEntity(CFAllocatorRef allocator
,
2753 CFDictionaryRef interface_entity
,
2754 SCNetworkServiceRef service
)
2756 SCNetworkInterfacePrivateRef interfacePrivate
= NULL
;
2757 CFStringRef ifDevice
;
2758 CFStringRef ifUnique
;
2759 CFStringRef ifSubType
;
2761 CFArrayRef matching_interfaces
= NULL
;
2763 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
2764 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
2766 ifType
= CFDictionaryGetValue(interface_entity
, kSCPropNetInterfaceType
);
2767 if (ifType
== NULL
) {
2769 * The interface "Type" was not specified. We'll make an
2770 * assumption that this is an "Ethernet" interface. If a
2771 * real interface exists with the provided interface name
2772 * then the actual type will be set accordingly. If not, we'll
2773 * end up crafting an "Ethernet" SCNetworkInterface which
2774 * will keep the rest of the configuration APIs happy.
2776 ifType
= kSCValNetInterfaceTypeEthernet
;
2779 if (!isA_CFString(ifType
)) {
2783 ifSubType
= CFDictionaryGetValue(interface_entity
, kSCPropNetInterfaceSubType
);
2784 if (CFEqual(ifType
, kSCValNetInterfaceTypePPP
)) {
2785 if (!isA_CFString(ifSubType
)) {
2790 ifDevice
= CFDictionaryGetValue(interface_entity
, kSCPropNetInterfaceDeviceName
);
2791 ifUnique
= CFDictionaryGetValue(interface_entity
, CFSTR("DeviceUniqueIdentifier"));
2793 if (CFEqual(ifType
, kSCValNetInterfaceTypeEthernet
) ||
2794 CFEqual(ifType
, kSCValNetInterfaceTypeFireWire
) ||
2795 (CFEqual(ifType
, kSCValNetInterfaceTypePPP
) && CFEqual(ifSubType
, kSCValNetInterfaceSubTypePPPoE
))) {
2796 char bsdName
[IFNAMSIZ
+ 1];
2797 CFMutableDictionaryRef matching
;
2799 if (!isA_CFString(ifDevice
)) {
2803 if (_SC_cfstring_to_cstring(ifDevice
, bsdName
, sizeof(bsdName
), kCFStringEncodingASCII
) == NULL
) {
2807 matching
= IOBSDNameMatching(masterPort
, 0, bsdName
);
2808 if (matching
== NULL
) {
2812 // note: the "matching" dictionary will be consumed by the following
2813 matching_interfaces
= findMatchingInterfaces(matching
, processNetworkInterface
);
2815 } else if (CFEqual(ifType
, kSCValNetInterfaceTypePPP
)) {
2816 if (CFEqual(ifSubType
, kSCValNetInterfaceSubTypePPPSerial
)) {
2817 CFDictionaryRef matching
;
2818 CFStringRef match_keys
[2];
2819 CFStringRef match_vals
[2];
2821 if (!isA_CFString(ifDevice
)) {
2825 match_keys
[0] = CFSTR(kIOProviderClassKey
);
2826 match_vals
[0] = CFSTR(kIOSerialBSDServiceValue
);
2828 match_keys
[1] = CFSTR(kIOTTYBaseNameKey
);
2829 match_vals
[1] = ifDevice
;
2831 matching
= CFDictionaryCreate(NULL
,
2832 (const void **)match_keys
,
2833 (const void **)match_vals
,
2834 sizeof(match_keys
)/sizeof(match_keys
[0]),
2835 &kCFTypeDictionaryKeyCallBacks
,
2836 &kCFTypeDictionaryValueCallBacks
);
2838 // note: the "matching" dictionary will be consumed by the following
2839 matching_interfaces
= findMatchingInterfaces(matching
, processSerialInterface
);
2841 } else if (CFEqual(ifSubType
, kSCValNetInterfaceSubTypeL2TP
)) {
2842 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
2843 kSCNetworkInterfaceTypeL2TP
);
2844 } else if (CFEqual(ifSubType
, kSCValNetInterfaceSubTypePPTP
)) {
2845 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
2846 kSCNetworkInterfaceTypePPTP
);
2848 // XXX do we allow non-Apple variants of PPP??? XXX
2849 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
2852 } else if (CFEqual(ifType
, kSCValNetInterfaceType6to4
)) {
2853 if (!isA_CFString(ifDevice
)) {
2857 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
2858 kSCNetworkInterfaceType6to4
);
2859 } else if (CFEqual(ifType
, kSCValNetInterfaceTypeIPSec
)) {
2860 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
2861 kSCNetworkInterfaceTypeIPSec
);
2862 } else if ((CFStringFind(ifType
, CFSTR("."), 0).location
!= kCFNotFound
) && (ifDevice
== NULL
)) {
2863 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
2867 if (matching_interfaces
!= NULL
) {
2869 SCPreferencesRef prefs
;
2871 n
= CFArrayGetCount(matching_interfaces
);
2874 interfacePrivate
= (SCNetworkInterfacePrivateRef
)CFArrayGetValueAtIndex(matching_interfaces
, 0);
2875 if (_SC_CFEqual(ifUnique
, interfacePrivate
->entity_device_unique
)) {
2876 // if the unique ID's match
2877 CFRetain(interfacePrivate
);
2881 interfacePrivate
= NULL
;
2884 if (!CFEqual(ifType
, kSCValNetInterfaceTypeEthernet
)) {
2887 prefs
= SCPreferencesCreate(NULL
, CFSTR("SCNetworkInterface"), NULL
);
2888 if (prefs
== NULL
) {
2891 #if !TARGET_OS_IPHONE
2892 if (!CFDictionaryContainsKey(interface_entity
, CFSTR("_NO_VLAN_INTERFACES_"))) {
2893 interfacePrivate
= (SCNetworkInterfacePrivateRef
)findVLANInterface(prefs
, ifDevice
);
2895 if ((interfacePrivate
== NULL
)
2896 && !CFDictionaryContainsKey(interface_entity
, CFSTR("_NO_BOND_INTERFACES_"))) {
2897 interfacePrivate
= (SCNetworkInterfacePrivateRef
)findBondInterface(prefs
, ifDevice
);
2899 #endif // !TARGET_OS_IPHONE
2903 if (ifUnique
!= NULL
) {
2906 for (i
= 0; i
< n
; i
++) {
2907 SCNetworkInterfacePrivateRef scan
;
2909 scan
= (SCNetworkInterfacePrivateRef
)CFArrayGetValueAtIndex(matching_interfaces
, i
);
2910 if (_SC_CFEqual(ifUnique
, scan
->entity_device_unique
)) {
2911 if (interfacePrivate
!= NULL
) {
2912 // if we've matched more than one interface
2913 interfacePrivate
= NULL
;
2916 interfacePrivate
= scan
;
2920 if (interfacePrivate
== NULL
) {
2921 SCLog(TRUE
, LOG_ERR
, CFSTR("_SCNetworkInterfaceCreateWithEntity() failed, more than one interface matches %@"), ifDevice
);
2922 interfacePrivate
= (SCNetworkInterfacePrivateRef
)CFArrayGetValueAtIndex(matching_interfaces
, 0);
2924 CFRetain(interfacePrivate
);
2927 CFRelease(matching_interfaces
);
2932 if (interfacePrivate
== NULL
) {
2934 * if device not present on this system
2936 interfacePrivate
= __SCNetworkInterfaceCreatePrivate(NULL
, NULL
, NULL
, NULL
, NULL
);
2937 interfacePrivate
->entity_type
= ifType
;
2938 interfacePrivate
->entity_subtype
= ifSubType
;
2939 interfacePrivate
->entity_device
= (ifDevice
!= NULL
) ? CFStringCreateCopy(NULL
, ifDevice
) : NULL
;
2940 interfacePrivate
->entity_device_unique
= (ifUnique
!= NULL
) ? CFStringCreateCopy(NULL
, ifUnique
) : NULL
;
2942 if (CFEqual(ifType
, kSCValNetInterfaceTypeEthernet
)) {
2943 CFStringRef entity_hardware
;
2945 entity_hardware
= CFDictionaryGetValue(interface_entity
, kSCPropNetInterfaceHardware
);
2946 if (isA_CFString((entity_hardware
)) &&
2947 CFEqual(entity_hardware
, kSCEntNetAirPort
)) {
2948 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeIEEE80211
;
2949 interfacePrivate
->sort_order
= kSortAirPort
;
2953 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
;
2955 name
= CFDictionaryGetValue(interface_entity
, kSCPropUserDefinedName
);
2956 if (_SCNetworkInterfaceMatchesName(name
, CFSTR("iPhone"))) {
2957 interfacePrivate
->sort_order
= kSortTethered
;
2958 } else if (_SCNetworkInterfaceMatchesName(name
, CFSTR("bluetooth-pan"))) {
2959 interfacePrivate
->sort_order
= kSortBluetoothPAN
;
2961 interfacePrivate
->sort_order
= kSortEthernet
;
2964 } else if (CFEqual(ifType
, kSCValNetInterfaceTypeFireWire
)) {
2965 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeFireWire
;
2966 interfacePrivate
->sort_order
= kSortFireWire
;
2967 } else if (CFEqual(ifType
, kSCValNetInterfaceTypePPP
)) {
2968 if (CFEqual(ifSubType
, kSCValNetInterfaceSubTypePPPoE
)) {
2969 CFStringRef entity_hardware
;
2971 entity_hardware
= CFDictionaryGetValue(interface_entity
, kSCPropNetInterfaceHardware
);
2972 if (isA_CFString((entity_hardware
)) &&
2973 CFEqual(entity_hardware
, kSCEntNetAirPort
)) {
2974 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeIEEE80211
;
2975 interfacePrivate
->sort_order
= kSortAirPort
;
2977 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
;
2978 interfacePrivate
->sort_order
= kSortEthernet
;
2980 } else if (CFEqual(ifSubType
, kSCValNetInterfaceSubTypePPPSerial
)) {
2981 if (CFStringHasPrefix(ifDevice
, CFSTR("Bluetooth"))) {
2982 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeBluetooth
;
2983 interfacePrivate
->sort_order
= kSortBluetooth
;
2984 } else if (CFStringHasPrefix(ifDevice
, CFSTR("irda"))) {
2985 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeIrDA
;
2986 interfacePrivate
->sort_order
= kSortIrDA
;
2987 } else if (CFStringHasPrefix(ifDevice
, CFSTR("wwan"))) {
2988 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeWWAN
;
2989 interfacePrivate
->sort_order
= kSortWWAN
;
2991 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeModem
;
2992 interfacePrivate
->sort_order
= kSortModem
;
2996 CFRelease(interfacePrivate
);
2997 interfacePrivate
= (SCNetworkInterfacePrivateRef
)kSCNetworkInterfaceIPv4
;
2998 CFRetain(interfacePrivate
);
3000 } else if (CFStringFind(ifType
, CFSTR("."), 0).location
!= kCFNotFound
) {
3001 // if vendor interface
3002 interfacePrivate
->interface_type
= ifType
;
3004 // if unknown interface
3005 CFRelease(interfacePrivate
);
3006 interfacePrivate
= NULL
;
3010 if ((interfacePrivate
!= NULL
) && (service
!= NULL
)) {
3011 __SCNetworkInterfaceSetService((SCNetworkInterfaceRef
)interfacePrivate
,
3013 #if !TARGET_OS_IPHONE
3014 // set prefs & serviceID to VLANs and Bonds
3015 if (CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeBond
)) {
3020 members
= SCBondInterfaceGetMemberInterfaces((SCNetworkInterfaceRef
)interfacePrivate
);
3021 n
= (members
!= NULL
) ? CFArrayGetCount(members
) : 0;
3022 for (i
= 0; i
< n
; i
++) {
3023 SCNetworkInterfaceRef member
;
3025 member
= CFArrayGetValueAtIndex(members
, i
);
3026 __SCNetworkInterfaceSetService(member
, service
);
3028 } else if (CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeVLAN
)) {
3029 SCNetworkInterfaceRef vlan_physical
;
3031 vlan_physical
= SCVLANInterfaceGetPhysicalInterface((SCNetworkInterfaceRef
)interfacePrivate
);
3032 if (vlan_physical
!= NULL
) {
3033 __SCNetworkInterfaceSetService(vlan_physical
, service
);
3036 #endif // !TARGET_OS_IPHONE
3039 if (CFEqual(ifType
, kSCValNetInterfaceTypePPP
)) {
3040 SCNetworkInterfaceRef parent
;
3043 parent
= SCNetworkInterfaceCreateWithInterface((SCNetworkInterfaceRef
)interfacePrivate
,
3044 kSCNetworkInterfaceTypePPP
);
3045 CFRelease(interfacePrivate
);
3046 interfacePrivate
= (SCNetworkInterfacePrivateRef
)parent
;
3049 return (SCNetworkInterfaceRef
)interfacePrivate
;
3054 #pragma mark SCNetworkInterface APIs
3059 __SCNetworkInterfaceCopyAll_IONetworkInterface(void)
3061 CFDictionaryRef matching
;
3062 CFArrayRef new_interfaces
;
3064 // get Ethernet, Firewire, and AirPort interfaces
3066 matching
= IOServiceMatching(kIONetworkInterfaceClass
);
3067 new_interfaces
= findMatchingInterfaces(matching
, processNetworkInterface
);
3069 return new_interfaces
;
3075 __SCNetworkInterfaceCopyAll_Modem()
3077 CFDictionaryRef matching
;
3078 CFStringRef match_keys
[2];
3079 CFStringRef match_vals
[2];
3080 CFArrayRef new_interfaces
;
3082 match_keys
[0] = CFSTR(kIOProviderClassKey
);
3083 match_vals
[0] = CFSTR(kIOSerialBSDServiceValue
);
3085 match_keys
[1] = CFSTR(kIOSerialBSDTypeKey
);
3086 match_vals
[1] = CFSTR(kIOSerialBSDModemType
);
3088 matching
= CFDictionaryCreate(NULL
,
3089 (const void **)match_keys
,
3090 (const void **)match_vals
,
3091 sizeof(match_keys
)/sizeof(match_keys
[0]),
3092 &kCFTypeDictionaryKeyCallBacks
,
3093 &kCFTypeDictionaryValueCallBacks
);
3094 new_interfaces
= findMatchingInterfaces(matching
, processSerialInterface
);
3096 return new_interfaces
;
3102 __SCNetworkInterfaceCopyAll_RS232()
3104 CFDictionaryRef matching
;
3105 CFStringRef match_keys
[2];
3106 CFStringRef match_vals
[2];
3107 CFArrayRef new_interfaces
;
3109 match_keys
[0] = CFSTR(kIOProviderClassKey
);
3110 match_vals
[0] = CFSTR(kIOSerialBSDServiceValue
);
3112 match_keys
[1] = CFSTR(kIOSerialBSDTypeKey
);
3113 match_vals
[1] = CFSTR(kIOSerialBSDRS232Type
);
3115 matching
= CFDictionaryCreate(NULL
,
3116 (const void **)match_keys
,
3117 (const void **)match_vals
,
3118 sizeof(match_keys
)/sizeof(match_keys
[0]),
3119 &kCFTypeDictionaryKeyCallBacks
,
3120 &kCFTypeDictionaryValueCallBacks
);
3121 new_interfaces
= findMatchingInterfaces(matching
, processSerialInterface
);
3123 return new_interfaces
;
3128 add_interfaces(CFMutableArrayRef all_interfaces
, CFArrayRef new_interfaces
)
3133 n
= CFArrayGetCount(new_interfaces
);
3134 for (i
= 0; i
< n
; i
++) {
3135 CFStringRef bsdName
;
3136 SCNetworkInterfaceRef interface
;
3138 interface
= CFArrayGetValueAtIndex(new_interfaces
, i
);
3139 bsdName
= SCNetworkInterfaceGetBSDName(interface
);
3140 if (bsdName
!= NULL
) {
3141 CFArrayAppendValue(all_interfaces
, interface
);
3150 __waitForInterfaces()
3155 SCDynamicStoreRef store
;
3157 store
= SCDynamicStoreCreate(NULL
, CFSTR("SCNetworkInterfaceCopyAll"), NULL
, NULL
);
3158 if (store
== NULL
) {
3162 key
= SCDynamicStoreKeyCreate(NULL
, CFSTR("%@" "InterfaceNamer"), kSCDynamicStoreDomainPlugin
);
3163 keys
= CFArrayCreate(NULL
, (const void **)&key
, 1, &kCFTypeArrayCallBacks
);
3164 ok
= SCDynamicStoreSetNotificationKeys(store
, keys
, NULL
);
3167 SCLog(TRUE
, LOG_ERR
,
3168 CFSTR("SCDynamicStoreSetNotificationKeys() failed: %s"), SCErrorString(SCError()));
3173 CFArrayRef changedKeys
;
3174 CFDictionaryRef dict
;
3175 Boolean quiet
= FALSE
;
3178 dict
= SCDynamicStoreCopyValue(store
, key
);
3180 if (isA_CFDictionary(dict
) &&
3181 (CFDictionaryContainsKey(dict
, CFSTR("*QUIET*")) ||
3182 CFDictionaryContainsKey(dict
, CFSTR("*TIMEOUT*")))) {
3191 ok
= SCDynamicStoreNotifyWait(store
);
3193 SCLog(TRUE
, LOG_ERR
,
3194 CFSTR("SCDynamicStoreNotifyWait() failed: %s"), SCErrorString(SCError()));
3198 changedKeys
= SCDynamicStoreCopyNotifiedKeys(store
);
3199 if (changedKeys
!= NULL
) {
3200 CFRelease(changedKeys
);
3212 CFArrayRef
/* of SCNetworkInterfaceRef's */
3213 SCNetworkInterfaceCopyAll()
3215 CFMutableArrayRef all_interfaces
;
3216 CFArrayRef new_interfaces
;
3217 #if !TARGET_OS_IPHONE
3218 SCPreferencesRef prefs
;
3219 #endif // !TARGET_OS_IPHONE
3221 /* initialize runtime */
3222 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
3224 /* wait for IOKit to quiesce */
3225 pthread_once(&iokit_quiet
, __waitForInterfaces
);
3227 all_interfaces
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
3229 // get Ethernet, Firewire, and AirPort interfaces
3230 new_interfaces
= __SCNetworkInterfaceCopyAll_IONetworkInterface();
3231 if (new_interfaces
!= NULL
) {
3232 add_interfaces(all_interfaces
, new_interfaces
);
3233 CFRelease(new_interfaces
);
3236 // get Modem interfaces
3237 new_interfaces
= __SCNetworkInterfaceCopyAll_Modem();
3238 if (new_interfaces
!= NULL
) {
3239 add_interfaces(all_interfaces
, new_interfaces
);
3240 CFRelease(new_interfaces
);
3243 // get serial (RS232) interfaces
3244 new_interfaces
= __SCNetworkInterfaceCopyAll_RS232();
3245 if (new_interfaces
!= NULL
) {
3246 add_interfaces(all_interfaces
, new_interfaces
);
3247 CFRelease(new_interfaces
);
3250 #if !TARGET_OS_IPHONE
3251 // get virtual network interfaces (Bond, VLAN)
3252 prefs
= SCPreferencesCreate(NULL
, CFSTR("SCNetworkInterfaceCopyAll"), NULL
);
3253 if (prefs
!= NULL
) {
3254 new_interfaces
= SCBondInterfaceCopyAll(prefs
);
3255 if (new_interfaces
!= NULL
) {
3256 add_interfaces(all_interfaces
, new_interfaces
);
3257 CFRelease(new_interfaces
);
3260 new_interfaces
= SCVLANInterfaceCopyAll(prefs
);
3261 if (new_interfaces
!= NULL
) {
3262 add_interfaces(all_interfaces
, new_interfaces
);
3263 CFRelease(new_interfaces
);
3268 #endif // !TARGET_OS_IPHONE
3270 // all interfaces have been identified, order and return
3271 sort_interfaces(all_interfaces
);
3273 return all_interfaces
;
3277 CFArrayRef
/* of kSCNetworkInterfaceTypeXXX CFStringRef's */
3278 SCNetworkInterfaceGetSupportedInterfaceTypes(SCNetworkInterfaceRef interface
)
3281 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
3283 if (!isA_SCNetworkInterface(interface
)) {
3284 _SCErrorSet(kSCStatusInvalidArgument
);
3288 if (interfacePrivate
->supported_interface_types
!= NULL
) {
3292 i
= findConfiguration(interfacePrivate
->interface_type
);
3293 if (i
!= kCFNotFound
) {
3294 if (configurations
[i
].supported_interfaces
!= doNone
) {
3295 interfacePrivate
->supported_interface_types
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
3296 if (configurations
[i
].supported_interfaces
& do6to4
) {
3297 CFArrayAppendValue(interfacePrivate
->supported_interface_types
, kSCNetworkInterfaceType6to4
);
3299 if (configurations
[i
].supported_interfaces
& doL2TP
) {
3300 CFArrayAppendValue(interfacePrivate
->supported_interface_types
, kSCNetworkInterfaceTypeL2TP
);
3302 if (configurations
[i
].supported_interfaces
& doPPP
) {
3303 CFArrayAppendValue(interfacePrivate
->supported_interface_types
, kSCNetworkInterfaceTypePPP
);
3305 if (configurations
[i
].supported_interfaces
& doPPTP
) {
3306 CFArrayAppendValue(interfacePrivate
->supported_interface_types
, kSCNetworkInterfaceTypePPTP
);
3308 if (configurations
[i
].supported_interfaces
& doIPSec
) {
3309 CFArrayAppendValue(interfacePrivate
->supported_interface_types
, kSCNetworkInterfaceTypeIPSec
);
3316 return interfacePrivate
->supported_interface_types
;
3320 CFArrayRef
/* of kSCNetworkProtocolTypeXXX CFStringRef's */
3321 SCNetworkInterfaceGetSupportedProtocolTypes(SCNetworkInterfaceRef interface
)
3324 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
3326 if (!isA_SCNetworkInterface(interface
)) {
3327 _SCErrorSet(kSCStatusInvalidArgument
);
3331 if (interfacePrivate
->supported_protocol_types
!= NULL
) {
3335 i
= findConfiguration(interfacePrivate
->interface_type
);
3336 if (i
!= kCFNotFound
) {
3337 if (configurations
[i
].supported_protocols
!= doNone
) {
3338 interfacePrivate
->supported_protocol_types
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
3339 #if !TARGET_OS_IPHONE
3340 if (configurations
[i
].supported_protocols
& doAppleTalk
) {
3341 CFArrayAppendValue(interfacePrivate
->supported_protocol_types
, kSCNetworkProtocolTypeAppleTalk
);
3343 #endif // !TARGET_OS_IPHONE
3344 if (configurations
[i
].supported_protocols
& doDNS
) {
3345 CFArrayAppendValue(interfacePrivate
->supported_protocol_types
, kSCNetworkProtocolTypeDNS
);
3347 if (configurations
[i
].supported_protocols
& doIPv4
) {
3348 CFArrayAppendValue(interfacePrivate
->supported_protocol_types
, kSCNetworkProtocolTypeIPv4
);
3350 if (configurations
[i
].supported_protocols
& doIPv6
) {
3351 CFArrayAppendValue(interfacePrivate
->supported_protocol_types
, kSCNetworkProtocolTypeIPv6
);
3353 if (configurations
[i
].supported_protocols
& doProxies
) {
3354 CFArrayAppendValue(interfacePrivate
->supported_protocol_types
, kSCNetworkProtocolTypeProxies
);
3356 #if !TARGET_OS_IPHONE
3357 if (configurations
[i
].supported_protocols
& doSMB
) {
3358 CFArrayAppendValue(interfacePrivate
->supported_protocol_types
, kSCNetworkProtocolTypeSMB
);
3360 #endif // !TARGET_OS_IPHONE
3366 return interfacePrivate
->supported_protocol_types
;
3370 SCNetworkInterfaceRef
3371 SCNetworkInterfaceCreateWithInterface(SCNetworkInterfaceRef child
, CFStringRef interfaceType
)
3373 SCNetworkInterfacePrivateRef childPrivate
= (SCNetworkInterfacePrivateRef
)child
;
3375 SCNetworkInterfacePrivateRef parentPrivate
;
3377 if (!isA_SCNetworkInterface(child
)) {
3378 _SCErrorSet(kSCStatusInvalidArgument
);
3382 if (!isA_CFString(interfaceType
)) {
3383 _SCErrorSet(kSCStatusInvalidArgument
);
3387 childIndex
= findConfiguration(childPrivate
->interface_type
);
3389 parentPrivate
= __SCNetworkInterfaceCreatePrivate(NULL
,
3391 childPrivate
->prefs
,
3392 childPrivate
->serviceID
,
3394 if (parentPrivate
== NULL
) {
3395 _SCErrorSet(kSCStatusFailed
);
3399 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
)) {
3400 parentPrivate
->interface_type
= kSCNetworkInterfaceTypePPP
;
3401 parentPrivate
->entity_type
= kSCValNetInterfaceTypePPP
;
3404 if (childIndex
!= kCFNotFound
) {
3405 if (configurations
[childIndex
].ppp_subtype
!= NULL
) {
3406 parentPrivate
->entity_subtype
= *configurations
[childIndex
].ppp_subtype
;
3408 // sorry, the child interface does not support PPP
3412 // if the child's interface type not known, use the child entities "Type"
3413 parentPrivate
->entity_subtype
= childPrivate
->entity_type
;
3416 if (childPrivate
->entity_device
!= NULL
) {
3417 parentPrivate
->entity_device
= CFStringCreateCopy(NULL
, childPrivate
->entity_device
);
3420 if (childPrivate
->entity_device_unique
!= NULL
) {
3421 parentPrivate
->entity_device_unique
= CFStringCreateCopy(NULL
, childPrivate
->entity_device_unique
);
3423 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeL2TP
)) {
3424 if ((childIndex
== kCFNotFound
) ||
3425 ((configurations
[childIndex
].supported_interfaces
& doL2TP
) != doL2TP
)) {
3426 // if the child interface does not support L2TP
3429 parentPrivate
->interface_type
= kSCNetworkInterfaceTypeL2TP
;
3430 parentPrivate
->localized_key
= CFSTR("l2tp");
3431 parentPrivate
->entity_type
= kSCEntNetL2TP
; // interface config goes into "L2TP"
3432 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPTP
)) {
3433 if ((childIndex
== kCFNotFound
) ||
3434 ((configurations
[childIndex
].supported_interfaces
& doPPTP
) != doPPTP
)) {
3435 // if the child interface does not support PPTP
3438 parentPrivate
->interface_type
= kSCNetworkInterfaceTypePPTP
;
3439 parentPrivate
->localized_key
= CFSTR("pptp");
3440 parentPrivate
->entity_type
= kSCEntNetPPTP
; // interface config goes into "PPTP"
3441 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceType6to4
)) {
3442 if ((childIndex
== kCFNotFound
) ||
3443 ((configurations
[childIndex
].supported_interfaces
& do6to4
) != do6to4
)) {
3444 // if the child interface does not support 6to4
3448 parentPrivate
->interface_type
= kSCNetworkInterfaceType6to4
;
3449 parentPrivate
->localized_key
= CFSTR("6to4");
3450 parentPrivate
->entity_type
= kSCValNetInterfaceType6to4
;
3451 parentPrivate
->entity_device
= CFRetain(CFSTR("stf0"));
3452 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeIPSec
)) {
3453 if ((childIndex
== kCFNotFound
) ||
3454 ((configurations
[childIndex
].supported_interfaces
& doIPSec
) != doIPSec
)) {
3455 // if the child interface does not support IPSec
3458 parentPrivate
->interface_type
= kSCNetworkInterfaceTypeIPSec
;
3459 parentPrivate
->localized_key
= CFSTR("ipsec");
3460 parentPrivate
->entity_type
= kSCValNetInterfaceTypeIPSec
;
3461 } else if (CFStringFind(interfaceType
, CFSTR("."), 0).location
!= kCFNotFound
) {
3462 // if custom interface type
3463 parentPrivate
->interface_type
= interfaceType
;
3464 parentPrivate
->entity_type
= interfaceType
; // interface config goes into a
3465 // a dictionary with the same
3466 // name as the interfaceType
3468 // unknown interface type
3472 if (childPrivate
->overrides
!= NULL
) {
3473 parentPrivate
->overrides
= CFDictionaryCreateMutableCopy(NULL
, 0, childPrivate
->overrides
);
3476 // The following change handles the case where a user has both an Ethernet and
3477 // PPPoE network service. Because a PPPoE service is typically associated with
3478 // an ISP we want it to be sorted higher in the service order.
3479 if ((parentPrivate
->entity_subtype
!= NULL
) &&
3480 (CFEqual(parentPrivate
->entity_subtype
, kSCValNetInterfaceSubTypePPPoE
))) {
3481 if ((childPrivate
->interface_type
!= NULL
) &&
3482 (CFEqual(childPrivate
->interface_type
, kSCNetworkInterfaceTypeIEEE80211
))) {
3483 parentPrivate
->sort_order
= kSortAirportPPP
;
3485 parentPrivate
->sort_order
= kSortEthernetPPP
;
3488 // set sort order of the parent to match the child interface
3489 parentPrivate
->sort_order
= childPrivate
->sort_order
;
3492 return (SCNetworkInterfaceRef
)parentPrivate
;
3496 CFRelease(parentPrivate
);
3497 _SCErrorSet(kSCStatusInvalidArgument
);
3504 __SCNetworkInterfaceGetDefaultConfiguration(SCNetworkSetRef set
, SCNetworkInterfaceRef interface
)
3506 CFDictionaryRef config
= NULL
;
3507 CFStringRef defaultType
;
3508 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
3510 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
3511 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
3513 defaultType
= __SCNetworkInterfaceGetDefaultConfigurationType(interface
);
3514 if (defaultType
!= NULL
) {
3518 path
= SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL
, // allocator
3519 SCNetworkSetGetSetID(set
), // set
3520 interfacePrivate
->entity_device
, // interface
3521 defaultType
); // entity
3523 config
= __getPrefsConfiguration(interfacePrivate
->prefs
, path
);
3526 if (config
== NULL
) {
3527 // if the "set" does not have a saved configuration, use
3528 // the [template] "interface" configuration
3529 if (interfacePrivate
->unsaved
!= NULL
) {
3530 config
= CFDictionaryGetValue(interfacePrivate
->unsaved
, defaultType
);
3531 if (config
== (CFDictionaryRef
)kCFNull
) {
3536 if (isA_CFDictionary(config
) && (CFDictionaryGetCount(config
) == 0)) {
3547 static CFDictionaryRef
3548 __SCNetworkInterfaceGetConfiguration(SCNetworkInterfaceRef interface
,
3549 CFStringRef extendedType
)
3551 CFDictionaryRef config
= NULL
;
3552 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
3555 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
3556 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
3558 paths
= copyConfigurationPaths(interfacePrivate
, extendedType
);
3559 if (paths
!= NULL
) {
3562 path
= CFArrayGetValueAtIndex(paths
, 0);
3563 config
= __getPrefsConfiguration(interfacePrivate
->prefs
, path
);
3567 if (interfacePrivate
->unsaved
!= NULL
) {
3568 config
= CFDictionaryGetValue(interfacePrivate
->unsaved
, extendedType
);
3569 if (config
== (CFDictionaryRef
)kCFNull
) {
3575 if (isA_CFDictionary(config
) && (CFDictionaryGetCount(config
) == 0)) {
3584 SCNetworkInterfaceGetConfiguration(SCNetworkInterfaceRef interface
)
3586 CFDictionaryRef config
;
3587 CFStringRef defaultType
;
3589 if (!isA_SCNetworkInterface(interface
)) {
3590 _SCErrorSet(kSCStatusInvalidArgument
);
3594 defaultType
= __SCNetworkInterfaceGetDefaultConfigurationType(interface
);
3595 if (defaultType
== NULL
) {
3599 config
= __SCNetworkInterfaceGetConfiguration(interface
, defaultType
);
3600 if (config
== NULL
) {
3601 if (CFEqual(defaultType
, kSCEntNetAirPort
)) {
3602 SCNetworkInterfacePrivateRef interfacePrivate
;
3605 // if AirPort interface, check for a per-service config
3606 interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
3607 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
3608 interfacePrivate
->serviceID
, // service
3609 kSCEntNetAirPort
); // entity
3610 config
= __getPrefsConfiguration(interfacePrivate
->prefs
, path
);
3614 if (config
== NULL
) {
3615 _SCErrorSet(kSCStatusOK
);
3623 SCNetworkInterfaceGetExtendedConfiguration(SCNetworkInterfaceRef interface
,
3624 CFStringRef extendedType
)
3626 CFDictionaryRef config
;
3628 if (!isA_SCNetworkInterface(interface
)) {
3629 _SCErrorSet(kSCStatusInvalidArgument
);
3633 if (!__SCNetworkInterfaceIsValidExtendedConfigurationType(interface
, extendedType
, TRUE
)) {
3634 _SCErrorSet(kSCStatusInvalidArgument
);
3638 config
= __SCNetworkInterfaceGetConfiguration(interface
, extendedType
);
3639 if (config
== NULL
) {
3640 _SCErrorSet(kSCStatusOK
);
3648 SCNetworkInterfaceGetBSDName(SCNetworkInterfaceRef interface
)
3650 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
3652 if (!isA_SCNetworkInterface(interface
)) {
3653 _SCErrorSet(kSCStatusInvalidArgument
);
3657 if ((interfacePrivate
->interface
!= NULL
) &&
3658 (interfacePrivate
->interface
!= kSCNetworkInterfaceIPv4
)) {
3659 _SCErrorSet(kSCStatusOK
);
3663 return interfacePrivate
->entity_device
;
3668 SCNetworkInterfaceGetHardwareAddressString(SCNetworkInterfaceRef interface
)
3670 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
3672 if (!isA_SCNetworkInterface(interface
)) {
3673 _SCErrorSet(kSCStatusInvalidArgument
);
3677 if ((interfacePrivate
->address
!= NULL
) &&
3678 (interfacePrivate
->addressString
== NULL
)) {
3682 char mac
[sizeof("xx:xx:xx:xx:xx:xx:xx:xx")];
3685 bp
= (uint8_t *)CFDataGetBytePtr(interfacePrivate
->address
);
3686 n
= CFDataGetLength(interfacePrivate
->address
) * 3;
3688 if (n
> sizeof(mac
)) {
3689 mac_p
= CFAllocatorAllocate(NULL
, 0, n
);
3692 for (cp
= mac_p
; n
> 0; n
-= 3) {
3693 cp
+= snprintf(cp
, n
, "%2.2x:", *bp
++);
3696 interfacePrivate
->addressString
= CFStringCreateWithCString(NULL
, mac_p
, kCFStringEncodingUTF8
);
3697 if (mac_p
!= mac
) CFAllocatorDeallocate(NULL
, mac_p
);
3700 return interfacePrivate
->addressString
;
3704 SCNetworkInterfaceRef
3705 SCNetworkInterfaceGetInterface(SCNetworkInterfaceRef interface
)
3707 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
3709 if (!isA_SCNetworkInterface(interface
)) {
3710 _SCErrorSet(kSCStatusInvalidArgument
);
3714 return interfacePrivate
->interface
;
3719 SCNetworkInterfaceGetInterfaceType(SCNetworkInterfaceRef interface
)
3721 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
3723 if (!isA_SCNetworkInterface(interface
)) {
3724 _SCErrorSet(kSCStatusInvalidArgument
);
3728 return interfacePrivate
->interface_type
;
3733 copy_interface_string(CFBundleRef bundle
, CFStringRef key
, Boolean localized
)
3735 CFStringRef str
= NULL
;
3738 str
= CFBundleCopyLocalizedString(bundle
,
3741 NETWORKINTERFACE_LOCALIZATIONS
);
3743 str
= _SC_CFBundleCopyNonLocalizedString(bundle
,
3746 NETWORKINTERFACE_LOCALIZATIONS
);
3754 copy_display_name(SCNetworkInterfaceRef interface
, Boolean localized
, Boolean oldLocalization
)
3756 CFMutableStringRef local
;
3759 local
= CFStringCreateMutable(NULL
, 0);
3761 while (interface
!= NULL
) {
3762 Boolean added
= FALSE
;
3763 SCNetworkInterfaceRef child
= NULL
;
3764 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
3766 if ((interfacePrivate
->interface
!= NULL
) &&
3767 (interfacePrivate
->interface
!= kSCNetworkInterfaceIPv4
)) {
3768 child
= interfacePrivate
->interface
;
3771 if ((bundle
!= NULL
) && (interfacePrivate
->localized_key
!= NULL
)) {
3773 CFStringRef key
= interfacePrivate
->localized_key
;
3775 if (oldLocalization
) {
3776 key
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("X-%@"),
3777 interfacePrivate
->localized_key
);
3779 fmt
= copy_interface_string(bundle
, key
, localized
);
3781 CFStringAppendFormat(local
,
3784 interfacePrivate
->localized_arg1
,
3785 interfacePrivate
->localized_arg2
);
3789 if (oldLocalization
) {
3795 (interfacePrivate
->prefs
!= NULL
) &&
3796 (interfacePrivate
->serviceID
!= NULL
) &&
3798 CFDictionaryRef entity
;
3801 // check for (and use) the name of the interface when it
3802 // was last available
3803 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
,
3804 interfacePrivate
->serviceID
,
3805 kSCEntNetInterface
);
3806 entity
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
3808 if (isA_CFDictionary(entity
)) {
3811 name
= CFDictionaryGetValue(entity
, kSCPropUserDefinedName
);
3812 if (isA_CFString(name
)) {
3813 CFStringAppend(local
, name
);
3820 // create (non-)localized name based on the interface type
3821 CFStringAppend(local
, interfacePrivate
->interface_type
);
3823 // ... and, if this is a leaf node, the interface device
3824 if ((interfacePrivate
->entity_device
!= NULL
) && (child
== NULL
)) {
3825 CFStringAppendFormat(local
, NULL
, CFSTR(" (%@)"), interfacePrivate
->entity_device
);
3829 if (child
!= NULL
) {
3830 // if this interface is layered over another
3831 CFStringAppend(local
, CFSTR(" --> "));
3837 name
= CFStringCreateCopy(NULL
, local
);
3846 __SCNetworkInterfaceCopyXLocalizedDisplayName(SCNetworkInterfaceRef interface
)
3850 if (!isA_SCNetworkInterface(interface
)) {
3851 _SCErrorSet(kSCStatusInvalidArgument
);
3855 name
= copy_display_name(interface
, TRUE
, TRUE
);
3862 __SCNetworkInterfaceCopyXNonLocalizedDisplayName(SCNetworkInterfaceRef interface
)
3864 CFStringRef localized_name
;
3866 if (!isA_SCNetworkInterface(interface
)) {
3867 _SCErrorSet(kSCStatusInvalidArgument
);
3871 localized_name
= copy_display_name(interface
, FALSE
, TRUE
);
3872 return localized_name
;
3878 __SCNetworkInterfaceGetNonLocalizedDisplayName(SCNetworkInterfaceRef interface
)
3880 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
3882 if (!isA_SCNetworkInterface(interface
)) {
3883 _SCErrorSet(kSCStatusInvalidArgument
);
3887 if (interfacePrivate
->name
== NULL
) {
3888 interfacePrivate
->name
= copy_display_name(interface
, FALSE
, FALSE
);
3891 return interfacePrivate
->name
;
3896 SCNetworkInterfaceGetLocalizedDisplayName(SCNetworkInterfaceRef interface
)
3898 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
3900 if (!isA_SCNetworkInterface(interface
)) {
3901 _SCErrorSet(kSCStatusInvalidArgument
);
3905 if (interfacePrivate
->localized_name
== NULL
) {
3906 interfacePrivate
->localized_name
= copy_display_name(interface
, TRUE
, FALSE
);
3909 return interfacePrivate
->localized_name
;
3915 __SCNetworkInterfaceGetTemplateOverrides(SCNetworkInterfaceRef interface
, CFStringRef interfaceType
)
3917 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
3918 CFDictionaryRef overrides
= NULL
;
3920 if (interfacePrivate
->overrides
!= NULL
) {
3921 overrides
= CFDictionaryGetValue(interfacePrivate
->overrides
, interfaceType
);
3929 SCNetworkInterfaceGetTypeID(void)
3931 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
); /* initialize runtime */
3932 return __kSCNetworkInterfaceTypeID
;
3938 __SCNetworkInterfaceSetDefaultConfiguration(SCNetworkSetRef set
,
3939 SCNetworkInterfaceRef interface
,
3940 CFStringRef defaultType
,
3941 CFDictionaryRef config
,
3944 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
3947 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
3948 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
3950 if (defaultType
== NULL
) {
3951 defaultType
= __SCNetworkInterfaceGetDefaultConfigurationType(interface
);
3952 if (defaultType
== NULL
) {
3957 if (isA_CFDictionary(config
) && (CFDictionaryGetCount(config
) == 0)) {
3964 path
= SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL
, // allocator
3965 SCNetworkSetGetSetID(set
), // set
3966 interfacePrivate
->entity_device
, // interface
3967 defaultType
); // entity
3969 ok
= __setPrefsConfiguration(interfacePrivate
->prefs
, path
, config
, FALSE
);
3972 // if configuration has been saved
3973 if (interfacePrivate
->unsaved
!= NULL
) {
3974 CFDictionaryRemoveValue(interfacePrivate
->unsaved
, defaultType
);
3975 if (CFDictionaryGetCount(interfacePrivate
->unsaved
) == 0) {
3976 CFRelease(interfacePrivate
->unsaved
);
3977 interfacePrivate
->unsaved
= NULL
;
3983 if (config
== NULL
) {
3984 // remember that we are clearing the configuration
3985 config
= (CFDictionaryRef
)kCFNull
;
3988 if (interfacePrivate
->unsaved
== NULL
) {
3989 interfacePrivate
->unsaved
= CFDictionaryCreateMutable(NULL
,
3991 &kCFTypeDictionaryKeyCallBacks
,
3992 &kCFTypeDictionaryValueCallBacks
);
3994 CFDictionarySetValue(interfacePrivate
->unsaved
, defaultType
, config
);
3997 _SCErrorSet(kSCStatusNoKey
);
4008 __SCNetworkInterfaceSetConfiguration(SCNetworkInterfaceRef interface
,
4009 CFStringRef extendedType
,
4010 CFDictionaryRef config
,
4013 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
4017 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
4018 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
4020 if (extendedType
== NULL
) {
4021 extendedType
= __SCNetworkInterfaceGetDefaultConfigurationType(interface
);
4022 if (extendedType
== NULL
) {
4027 if (isA_CFDictionary(config
) && (CFDictionaryGetCount(config
) == 0)) {
4031 paths
= copyConfigurationPaths(interfacePrivate
, extendedType
);
4032 if (paths
!= NULL
) {
4036 n
= CFArrayGetCount(paths
);
4037 for (i
= 0; i
< n
; i
++) {
4040 path
= CFArrayGetValueAtIndex(paths
, i
);
4041 ok
= __setPrefsConfiguration(interfacePrivate
->prefs
, path
, config
, FALSE
);
4048 // if configuration has been saved
4049 if (interfacePrivate
->unsaved
!= NULL
) {
4050 CFDictionaryRemoveValue(interfacePrivate
->unsaved
, extendedType
);
4051 if (CFDictionaryGetCount(interfacePrivate
->unsaved
) == 0) {
4052 CFRelease(interfacePrivate
->unsaved
);
4053 interfacePrivate
->unsaved
= NULL
;
4061 if (config
== NULL
) {
4062 // remember that we are clearing the configuration
4063 config
= (CFDictionaryRef
)kCFNull
;
4066 if (interfacePrivate
->unsaved
== NULL
) {
4067 interfacePrivate
->unsaved
= CFDictionaryCreateMutable(NULL
,
4069 &kCFTypeDictionaryKeyCallBacks
,
4070 &kCFTypeDictionaryValueCallBacks
);
4072 CFDictionarySetValue(interfacePrivate
->unsaved
, extendedType
, config
);
4075 _SCErrorSet(kSCStatusNoKey
);
4084 SCNetworkInterfaceSetConfiguration(SCNetworkInterfaceRef interface
, CFDictionaryRef config
)
4086 CFStringRef defaultType
;
4088 if (!isA_SCNetworkInterface(interface
)) {
4089 _SCErrorSet(kSCStatusInvalidArgument
);
4093 defaultType
= __SCNetworkInterfaceGetDefaultConfigurationType(interface
);
4094 if (defaultType
== NULL
) {
4098 return __SCNetworkInterfaceSetConfiguration(interface
, defaultType
, config
, FALSE
);
4103 SCNetworkInterfaceSetExtendedConfiguration(SCNetworkInterfaceRef interface
,
4104 CFStringRef extendedType
,
4105 CFDictionaryRef config
)
4107 if (!isA_SCNetworkInterface(interface
)) {
4108 _SCErrorSet(kSCStatusInvalidArgument
);
4112 if (!__SCNetworkInterfaceIsValidExtendedConfigurationType(interface
, extendedType
, TRUE
)) {
4116 return __SCNetworkInterfaceSetConfiguration(interface
, extendedType
, config
, FALSE
);
4121 #pragma mark SCNetworkInterface [Refresh Configuration] API
4124 #ifndef kSCEntNetRefreshConfiguration
4125 #define kSCEntNetRefreshConfiguration CFSTR("RefreshConfiguration")
4126 #endif // kSCEntNetRefreshConfiguration
4129 _SCNetworkInterfaceForceConfigurationRefresh(CFStringRef ifName
)
4133 SCDynamicStoreRef store
;
4135 if (!isA_CFString(ifName
)) {
4136 _SCErrorSet(kSCStatusInvalidArgument
);
4140 store
= SCDynamicStoreCreate(NULL
, CFSTR("_SCNetworkInterfaceForceConfigurationRefresh"), NULL
, NULL
);
4141 if (store
== NULL
) {
4145 key
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
,
4146 kSCDynamicStoreDomainState
,
4148 kSCEntNetRefreshConfiguration
);
4149 ok
= SCDynamicStoreNotifyValue(store
, key
);
4157 __SCNetworkInterfaceForceConfigurationRefresh_helper(SCPreferencesRef prefs
, CFStringRef ifName
)
4159 CFDataRef data
= NULL
;
4161 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
4162 uint32_t status
= kSCStatusOK
;
4163 CFDataRef reply
= NULL
;
4165 if (prefsPrivate
->helper
== -1) {
4166 ok
= __SCPreferencesCreate_helper(prefs
);
4172 // serialize the interface name
4173 ok
= _SCSerializeString(ifName
, &data
, NULL
, NULL
);
4178 // have the helper "refresh" the configuration
4179 status
= kSCStatusOK
;
4181 ok
= _SCHelperExec(prefsPrivate
->helper
,
4182 SCHELPER_MSG_INTERFACE_REFRESH
,
4186 if (data
!= NULL
) CFRelease(data
);
4191 if (status
!= kSCStatusOK
) {
4200 if (prefsPrivate
->helper
!= -1) {
4201 _SCHelperClose(prefsPrivate
->helper
);
4202 prefsPrivate
->helper
= -1;
4205 status
= kSCStatusAccessError
;
4210 _SCErrorSet(status
);
4216 SCNetworkInterfaceForceConfigurationRefresh(SCNetworkInterfaceRef interface
)
4219 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
4221 if (!isA_SCNetworkInterface(interface
)) {
4222 _SCErrorSet(kSCStatusInvalidArgument
);
4226 ifName
= SCNetworkInterfaceGetBSDName(interface
);
4227 if (ifName
== NULL
) {
4228 _SCErrorSet(kSCStatusInvalidArgument
);
4232 if (interfacePrivate
->prefs
!= NULL
) {
4233 SCPreferencesRef prefs
= interfacePrivate
->prefs
;
4234 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
4236 if (prefsPrivate
->authorizationData
!= NULL
) {
4237 return __SCNetworkInterfaceForceConfigurationRefresh_helper(prefs
, ifName
);
4241 return _SCNetworkInterfaceForceConfigurationRefresh(ifName
);
4246 SCNetworkInterfaceRefreshConfiguration(CFStringRef ifName
)
4248 return _SCNetworkInterfaceForceConfigurationRefresh(ifName
);
4253 #pragma mark SCNetworkInterface Password APIs
4257 getPasswordID(CFDictionaryRef config
, CFStringRef serviceID
)
4259 CFStringRef unique_id
= NULL
;
4261 if (config
!= NULL
) {
4262 CFStringRef encryption
;
4264 encryption
= CFDictionaryGetValue(config
, kSCPropNetPPPAuthPasswordEncryption
);
4265 if (isA_CFString(encryption
) &&
4266 CFEqual(encryption
, kSCValNetPPPAuthPasswordEncryptionKeychain
)) {
4267 unique_id
= CFDictionaryGetValue(config
, kSCPropNetPPPAuthPassword
);
4270 if (unique_id
== NULL
) {
4271 unique_id
= serviceID
;
4279 copySharedSecretID(CFDictionaryRef config
, CFStringRef serviceID
)
4281 CFMutableStringRef shared_id
= NULL
;
4283 if (config
!= NULL
) {
4284 CFStringRef encryption
;
4286 encryption
= CFDictionaryGetValue(config
, kSCPropNetIPSecSharedSecretEncryption
);
4287 if (isA_CFString(encryption
) &&
4288 CFEqual(encryption
, kSCValNetIPSecSharedSecretEncryptionKeychain
)) {
4289 shared_id
= (CFMutableStringRef
)CFDictionaryGetValue(config
, kSCPropNetIPSecSharedSecret
);
4290 if (shared_id
!= NULL
) {
4291 CFRetain(shared_id
);
4296 if (shared_id
== NULL
) {
4297 CFStringRef unique_id
;
4299 unique_id
= getPasswordID(config
, serviceID
);
4300 shared_id
= CFStringCreateMutableCopy(NULL
, 0, unique_id
);
4301 CFStringAppend(shared_id
, CFSTR(".SS"));
4309 copyXAuthID(CFDictionaryRef config
, CFStringRef serviceID
)
4311 CFMutableStringRef xauth_id
= NULL
;
4313 if (config
!= NULL
) {
4314 CFStringRef encryption
;
4316 encryption
= CFDictionaryGetValue(config
, kSCPropNetIPSecXAuthPasswordEncryption
);
4317 if (isA_CFString(encryption
) &&
4318 CFEqual(encryption
, kSCValNetIPSecXAuthPasswordEncryptionKeychain
)) {
4319 xauth_id
= (CFMutableStringRef
)CFDictionaryGetValue(config
, kSCPropNetIPSecXAuthPassword
);
4320 if (xauth_id
!= NULL
) {
4326 if (xauth_id
== NULL
) {
4327 CFStringRef unique_id
;
4329 unique_id
= getPasswordID(config
, serviceID
);
4330 xauth_id
= CFStringCreateMutableCopy(NULL
, 0, unique_id
);
4331 CFStringAppend(xauth_id
, CFSTR(".XAUTH"));
4339 checkInterfacePassword(SCNetworkInterfaceRef interface
,
4340 SCNetworkInterfacePasswordType passwordType
,
4341 SCPreferencesRef
*prefs
,
4342 CFStringRef
*serviceID
)
4344 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
4346 if (!isA_SCNetworkInterface(interface
)) {
4350 *serviceID
= interfacePrivate
->serviceID
;
4351 if (*serviceID
== NULL
) {
4355 *prefs
= interfacePrivate
->prefs
;
4356 if (*prefs
== NULL
) {
4360 switch (passwordType
) {
4361 case kSCNetworkInterfacePasswordTypePPP
: {
4362 CFStringRef interfaceType
;
4364 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
4365 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
)) {
4373 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret
: {
4374 CFStringRef interfaceType
;
4376 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
4377 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
)) {
4378 interface
= SCNetworkInterfaceGetInterface(interface
);
4379 if (interface
!= NULL
) {
4380 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
4381 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeL2TP
)) {
4382 // if PPP->L2TP interface
4386 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeIPSec
)) {
4387 // if IPSec interface
4394 case kSCNetworkInterfacePasswordTypeEAPOL
: {
4398 case kSCNetworkInterfacePasswordTypeIPSecXAuth
: {
4399 CFStringRef interfaceType
;
4401 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
4402 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeIPSec
)) {
4403 // if IPSec interface
4418 _SCErrorSet(kSCStatusInvalidArgument
);
4424 SCNetworkInterfaceCheckPassword(SCNetworkInterfaceRef interface
,
4425 SCNetworkInterfacePasswordType passwordType
)
4427 Boolean exists
= FALSE
;
4428 SCPreferencesRef prefs
= NULL
;
4429 CFStringRef serviceID
= NULL
;
4431 if (!checkInterfacePassword(interface
, passwordType
, &prefs
, &serviceID
)) {
4435 switch (passwordType
) {
4436 case kSCNetworkInterfacePasswordTypePPP
: {
4437 CFDictionaryRef config
;
4438 CFStringRef unique_id
;
4440 // get configuration
4441 config
= SCNetworkInterfaceGetConfiguration(interface
);
4444 unique_id
= getPasswordID(config
, serviceID
);
4447 exists
= __extract_password(prefs
,
4449 kSCPropNetPPPAuthPassword
,
4450 kSCPropNetPPPAuthPasswordEncryption
,
4451 kSCValNetPPPAuthPasswordEncryptionKeychain
,
4457 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret
: {
4458 CFDictionaryRef config
;
4460 CFStringRef shared_id
;
4462 // get configuration
4463 extended
= CFEqual(SCNetworkInterfaceGetInterfaceType(interface
), kSCNetworkInterfaceTypePPP
);
4465 config
= SCNetworkInterfaceGetExtendedConfiguration(interface
, kSCEntNetIPSec
);
4467 config
= SCNetworkInterfaceGetConfiguration(interface
);
4470 // get sharedSecret ID
4471 shared_id
= copySharedSecretID(config
, serviceID
);
4474 exists
= __extract_password(prefs
,
4476 kSCPropNetIPSecSharedSecret
,
4477 kSCPropNetIPSecSharedSecretEncryption
,
4478 kSCValNetIPSecSharedSecretEncryptionKeychain
,
4481 CFRelease(shared_id
);
4485 case kSCNetworkInterfacePasswordTypeEAPOL
: {
4486 CFDictionaryRef config
;
4487 CFStringRef unique_id
= NULL
;
4489 // get configuration
4490 config
= SCNetworkInterfaceGetExtendedConfiguration(interface
, kSCEntNetEAPOL
);
4492 // get 802.1X identifier
4493 if (config
!= NULL
) {
4494 unique_id
= CFDictionaryGetValue(config
, kEAPClientPropUserPasswordKeychainItemID
);
4496 if (!isA_CFString(unique_id
)) {
4501 exists
= _SCPreferencesSystemKeychainPasswordItemExists(prefs
, unique_id
);
4505 case kSCNetworkInterfacePasswordTypeIPSecXAuth
: {
4506 CFDictionaryRef config
;
4507 CFStringRef xauth_id
;
4509 // get configuration
4510 config
= SCNetworkInterfaceGetConfiguration(interface
);
4513 xauth_id
= copyXAuthID(config
, serviceID
);
4516 exists
= __extract_password(prefs
,
4518 kSCPropNetIPSecXAuthPassword
,
4519 kSCPropNetIPSecXAuthPasswordEncryption
,
4520 kSCValNetIPSecXAuthPasswordEncryptionKeychain
,
4523 CFRelease(xauth_id
);
4528 _SCErrorSet(kSCStatusInvalidArgument
);
4537 SCNetworkInterfaceCopyPassword(SCNetworkInterfaceRef interface
,
4538 SCNetworkInterfacePasswordType passwordType
)
4540 CFDataRef password
= NULL
;
4541 SCPreferencesRef prefs
= NULL
;
4542 CFStringRef serviceID
= NULL
;
4544 if (!checkInterfacePassword(interface
, passwordType
, &prefs
, &serviceID
)) {
4548 switch (passwordType
) {
4549 case kSCNetworkInterfacePasswordTypePPP
: {
4550 CFDictionaryRef config
;
4551 CFStringRef unique_id
;
4553 // get configuration
4554 config
= SCNetworkInterfaceGetConfiguration(interface
);
4557 unique_id
= getPasswordID(config
, serviceID
);
4560 (void) __extract_password(prefs
,
4562 kSCPropNetPPPAuthPassword
,
4563 kSCPropNetPPPAuthPasswordEncryption
,
4564 kSCValNetPPPAuthPasswordEncryptionKeychain
,
4570 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret
: {
4571 CFDictionaryRef config
;
4573 CFStringRef shared_id
;
4575 // get configuration
4576 extended
= CFEqual(SCNetworkInterfaceGetInterfaceType(interface
), kSCNetworkInterfaceTypePPP
);
4578 config
= SCNetworkInterfaceGetExtendedConfiguration(interface
, kSCEntNetIPSec
);
4580 config
= SCNetworkInterfaceGetConfiguration(interface
);
4583 // get sharedSecret ID
4584 shared_id
= copySharedSecretID(config
, serviceID
);
4587 (void) __extract_password(prefs
,
4589 kSCPropNetIPSecSharedSecret
,
4590 kSCPropNetIPSecSharedSecretEncryption
,
4591 kSCValNetIPSecSharedSecretEncryptionKeychain
,
4595 CFRelease(shared_id
);
4599 case kSCNetworkInterfacePasswordTypeEAPOL
: {
4600 CFDictionaryRef config
;
4601 CFStringRef unique_id
= NULL
;
4603 // get configuration
4604 config
= SCNetworkInterfaceGetExtendedConfiguration(interface
, kSCEntNetEAPOL
);
4606 // get 802.1X identifier
4607 if (config
!= NULL
) {
4608 unique_id
= CFDictionaryGetValue(config
, kEAPClientPropUserPasswordKeychainItemID
);
4610 if (!isA_CFString(unique_id
)) {
4611 _SCErrorSet(kSCStatusFailed
);
4616 password
= _SCPreferencesSystemKeychainPasswordItemCopy(prefs
, unique_id
);
4620 case kSCNetworkInterfacePasswordTypeIPSecXAuth
: {
4621 CFDictionaryRef config
;
4622 CFStringRef xauth_id
;
4624 // get configuration
4625 config
= SCNetworkInterfaceGetConfiguration(interface
);
4628 xauth_id
= copyXAuthID(config
, serviceID
);
4631 (void) __extract_password(prefs
,
4633 kSCPropNetIPSecXAuthPassword
,
4634 kSCPropNetIPSecXAuthPasswordEncryption
,
4635 kSCValNetIPSecXAuthPasswordEncryptionKeychain
,
4638 CFRelease(xauth_id
);
4643 _SCErrorSet(kSCStatusInvalidArgument
);
4652 SCNetworkInterfaceRemovePassword(SCNetworkInterfaceRef interface
,
4653 SCNetworkInterfacePasswordType passwordType
)
4656 SCPreferencesRef prefs
= NULL
;
4657 CFStringRef serviceID
= NULL
;
4659 if (!checkInterfacePassword(interface
, passwordType
, &prefs
, &serviceID
)) {
4663 switch (passwordType
) {
4664 case kSCNetworkInterfacePasswordTypePPP
: {
4665 CFDictionaryRef config
;
4666 CFDictionaryRef newConfig
= NULL
;
4667 CFStringRef unique_id
;
4669 // get configuration
4670 config
= SCNetworkInterfaceGetConfiguration(interface
);
4673 unique_id
= getPasswordID(config
, serviceID
);
4676 ok
= __remove_password(prefs
,
4678 kSCPropNetPPPAuthPassword
,
4679 kSCPropNetPPPAuthPasswordEncryption
,
4680 kSCValNetPPPAuthPasswordEncryptionKeychain
,
4684 ok
= SCNetworkInterfaceSetConfiguration(interface
, newConfig
);
4685 if (newConfig
!= NULL
) CFRelease(newConfig
);
4691 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret
: {
4692 CFDictionaryRef config
;
4694 CFDictionaryRef newConfig
= NULL
;
4695 CFStringRef shared_id
;
4697 // get configuration
4698 extended
= CFEqual(SCNetworkInterfaceGetInterfaceType(interface
), kSCNetworkInterfaceTypePPP
);
4700 config
= SCNetworkInterfaceGetExtendedConfiguration(interface
, kSCEntNetIPSec
);
4702 config
= SCNetworkInterfaceGetConfiguration(interface
);
4705 // get sharedSecret ID
4706 shared_id
= copySharedSecretID(config
, serviceID
);
4709 ok
= __remove_password(prefs
,
4711 kSCPropNetIPSecSharedSecret
,
4712 kSCPropNetIPSecSharedSecretEncryption
,
4713 kSCValNetIPSecSharedSecretEncryptionKeychain
,
4718 ok
= SCNetworkInterfaceSetExtendedConfiguration(interface
,
4722 ok
= SCNetworkInterfaceSetConfiguration(interface
,
4725 if (newConfig
!= NULL
) CFRelease(newConfig
);
4728 CFRelease(shared_id
);
4732 case kSCNetworkInterfacePasswordTypeEAPOL
: {
4733 CFDictionaryRef config
;
4734 CFStringRef unique_id
= NULL
;
4736 // get configuration
4737 config
= SCNetworkInterfaceGetExtendedConfiguration(interface
, kSCEntNetEAPOL
);
4739 // get 802.1X identifier
4740 if (config
!= NULL
) {
4741 unique_id
= CFDictionaryGetValue(config
, kEAPClientPropUserPasswordKeychainItemID
);
4743 if (!isA_CFString(unique_id
)) {
4744 _SCErrorSet(kSCStatusFailed
);
4749 ok
= _SCPreferencesSystemKeychainPasswordItemRemove(prefs
, unique_id
);
4753 case kSCNetworkInterfacePasswordTypeIPSecXAuth
: {
4754 CFDictionaryRef config
;
4755 CFDictionaryRef newConfig
= NULL
;
4756 CFStringRef xauth_id
;
4758 // get configuration
4759 config
= SCNetworkInterfaceGetConfiguration(interface
);
4762 xauth_id
= copyXAuthID(config
, serviceID
);
4765 ok
= __remove_password(prefs
,
4767 kSCPropNetIPSecXAuthPassword
,
4768 kSCPropNetIPSecXAuthPasswordEncryption
,
4769 kSCValNetIPSecXAuthPasswordEncryptionKeychain
,
4773 ok
= SCNetworkInterfaceSetConfiguration(interface
, newConfig
);
4774 if (newConfig
!= NULL
) CFRelease(newConfig
);
4777 CFRelease(xauth_id
);
4782 _SCErrorSet(kSCStatusInvalidArgument
);
4791 SCNetworkInterfaceSetPassword(SCNetworkInterfaceRef interface
,
4792 SCNetworkInterfacePasswordType passwordType
,
4794 CFDictionaryRef options
)
4796 CFStringRef account
= NULL
;
4797 CFDictionaryRef config
;
4798 CFStringRef description
= NULL
;
4799 CFStringRef label
= NULL
;
4801 SCPreferencesRef prefs
= NULL
;
4802 CFStringRef serviceID
= NULL
;
4804 if (!checkInterfacePassword(interface
, passwordType
, &prefs
, &serviceID
)) {
4808 switch (passwordType
) {
4809 case kSCNetworkInterfacePasswordTypePPP
: {
4810 SCNetworkServiceRef service
= NULL
;
4811 CFStringRef unique_id
;
4813 // get configuration
4814 config
= SCNetworkInterfaceGetConfiguration(interface
);
4817 unique_id
= getPasswordID(config
, serviceID
);
4819 // get "Account", "Name", "Kind"
4820 if (config
!= NULL
) {
4821 // auth name --> keychain "Account"
4822 account
= CFDictionaryGetValue(config
, kSCPropNetPPPAuthName
);
4824 // PPP [user defined] "name" --> keychain "Name"
4825 label
= CFDictionaryGetValue(config
, kSCPropUserDefinedName
);
4828 if (label
== NULL
) {
4829 // service name --> keychain "Name"
4830 service
= (SCNetworkServiceRef
)__SCNetworkServiceCreatePrivate(NULL
,
4835 label
= SCNetworkServiceGetName(service
);
4836 if (label
== NULL
) {
4837 // interface name --> keychain "Name"
4838 label
= SCNetworkInterfaceGetLocalizedDisplayName(interface
);
4842 if (bundle
!= NULL
) {
4843 // "PPP Password" --> keychain "Kind"
4844 description
= CFBundleCopyLocalizedString(bundle
,
4845 CFSTR("KEYCHAIN_KIND_PPP_PASSWORD"),
4846 CFSTR("PPP Password"),
4851 ok
= _SCPreferencesSystemKeychainPasswordItemSet(prefs
,
4853 (label
!= NULL
) ? label
: CFSTR("Network Connection"),
4854 (description
!= NULL
) ? description
: CFSTR("PPP Password"),
4859 CFMutableDictionaryRef newConfig
;
4861 if (config
!= NULL
) {
4862 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
4864 newConfig
= CFDictionaryCreateMutable(NULL
,
4866 &kCFTypeDictionaryKeyCallBacks
,
4867 &kCFTypeDictionaryValueCallBacks
);
4869 CFDictionarySetValue(newConfig
,
4870 kSCPropNetPPPAuthPassword
,
4872 CFDictionarySetValue(newConfig
,
4873 kSCPropNetPPPAuthPasswordEncryption
,
4874 kSCValNetPPPAuthPasswordEncryptionKeychain
);
4875 ok
= SCNetworkInterfaceSetConfiguration(interface
, newConfig
);
4876 CFRelease(newConfig
);
4879 if (description
!= NULL
) CFRelease(description
);
4880 if (service
!= NULL
) CFRelease(service
);
4884 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret
: {
4885 CFDictionaryRef baseConfig
= NULL
;
4887 SCNetworkServiceRef service
= NULL
;
4888 CFStringRef shared_id
;
4890 // get configuration
4891 extended
= CFEqual(SCNetworkInterfaceGetInterfaceType(interface
), kSCNetworkInterfaceTypePPP
);
4892 config
= SCNetworkInterfaceGetConfiguration(interface
);
4894 baseConfig
= config
;
4895 config
= SCNetworkInterfaceGetExtendedConfiguration(interface
, kSCEntNetIPSec
);
4898 // get sharedSecret ID
4899 shared_id
= copySharedSecretID(config
, serviceID
);
4901 // get "Account", "Name", "Kind"
4902 if (config
!= NULL
) {
4903 CFStringRef localIdentifier
;
4904 CFStringRef localIdentifierType
;
4906 if (CFDictionaryGetValueIfPresent(config
,
4907 kSCPropNetIPSecLocalIdentifierType
,
4908 (const void **)&localIdentifierType
)
4909 && CFEqual(localIdentifierType
, kSCValNetIPSecLocalIdentifierTypeKeyID
)
4910 && CFDictionaryGetValueIfPresent(config
,
4911 kSCPropNetIPSecLocalIdentifier
,
4912 (const void **)&localIdentifier
)
4913 && isA_CFString(localIdentifier
)) {
4914 // local identifier --> keychain "Account"
4915 account
= localIdentifier
;
4918 // PPP [user defined] "name" --> keychain "Name"
4920 label
= CFDictionaryGetValue(config
, kSCPropUserDefinedName
);
4922 if (baseConfig
!= NULL
) {
4923 label
= CFDictionaryGetValue(baseConfig
, kSCPropUserDefinedName
);
4928 if (label
== NULL
) {
4929 // service name --> keychain "Name"
4930 service
= (SCNetworkServiceRef
)__SCNetworkServiceCreatePrivate(NULL
,
4935 label
= SCNetworkServiceGetName(service
);
4936 if (label
== NULL
) {
4937 // interface name --> keychain "Name"
4938 label
= SCNetworkInterfaceGetLocalizedDisplayName(interface
);
4942 if (bundle
!= NULL
) {
4943 // "IPSec Shared Secret" --> keychain "Kind"
4944 description
= CFBundleCopyLocalizedString(bundle
,
4945 CFSTR("KEYCHAIN_KIND_IPSEC_SHARED_SECRET"),
4946 CFSTR("IPSec Shared Secret"),
4951 ok
= _SCPreferencesSystemKeychainPasswordItemSet(prefs
,
4953 (label
!= NULL
) ? label
: CFSTR("VPN Connection"),
4954 (description
!= NULL
) ? description
: CFSTR("IPSec Shared Secret"),
4959 CFMutableDictionaryRef newConfig
= NULL
;
4961 if (config
!= NULL
) {
4962 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
4964 newConfig
= CFDictionaryCreateMutable(NULL
,
4966 &kCFTypeDictionaryKeyCallBacks
,
4967 &kCFTypeDictionaryValueCallBacks
);
4969 CFDictionarySetValue(newConfig
,
4970 kSCPropNetIPSecSharedSecret
,
4972 CFDictionarySetValue(newConfig
,
4973 kSCPropNetIPSecSharedSecretEncryption
,
4974 kSCValNetIPSecSharedSecretEncryptionKeychain
);
4976 ok
= SCNetworkInterfaceSetExtendedConfiguration(interface
,
4980 ok
= SCNetworkInterfaceSetConfiguration(interface
, newConfig
);
4982 CFRelease(newConfig
);
4985 if (description
!= NULL
) CFRelease(description
);
4986 if (service
!= NULL
) CFRelease(service
);
4987 CFRelease(shared_id
);
4991 case kSCNetworkInterfacePasswordTypeEAPOL
: {
4992 CFStringRef account
= NULL
;
4993 CFStringRef unique_id
= NULL
;
4995 // get configuration
4996 config
= SCNetworkInterfaceGetExtendedConfiguration(interface
, kSCEntNetEAPOL
);
4998 // get 802.1X identifier
4999 if (config
!= NULL
) {
5000 unique_id
= CFDictionaryGetValue(config
, kEAPClientPropUserPasswordKeychainItemID
);
5002 if (isA_CFString(unique_id
)) {
5003 CFRetain(unique_id
);
5007 uuid
= CFUUIDCreate(NULL
);
5008 unique_id
= CFUUIDCreateString(NULL
, uuid
);
5012 // 802.1x UserName --> keychain "Account"
5013 if (config
!= NULL
) {
5014 account
= CFDictionaryGetValue(config
, kEAPClientPropUserName
);
5017 // get "Name", "Kind"
5018 if (bundle
!= NULL
) {
5019 CFStringRef interface_name
;
5021 // "Network Connection (%@)" --> keychain "Name"
5022 interface_name
= SCNetworkInterfaceGetLocalizedDisplayName(interface
);
5023 if (interface_name
!= NULL
) {
5024 CFStringRef label_fmt
;
5026 label_fmt
= CFBundleCopyLocalizedString(bundle
,
5027 CFSTR("KEYCHAIN_DESCRIPTION_EAPOL_INTERFACE"),
5028 CFSTR("Network Connection (%@)"),
5030 label
= CFStringCreateWithFormat(NULL
, NULL
, label_fmt
, interface_name
);
5031 CFRelease(label_fmt
);
5033 label
= CFBundleCopyLocalizedString(bundle
,
5034 CFSTR("KEYCHAIN_DESCRIPTION_EAPOL"),
5035 CFSTR("Network Connection"),
5039 // "802.1X Password" --> keychain "Kind"
5040 description
= CFBundleCopyLocalizedString(bundle
,
5041 CFSTR("KEYCHAIN_KIND_EAPOL"),
5042 CFSTR("802.1X Password"),
5047 ok
= _SCPreferencesSystemKeychainPasswordItemSet(prefs
,
5049 (label
!= NULL
) ? label
: CFSTR("Network Connection"),
5050 (description
!= NULL
) ? description
: CFSTR("802.1X Password"),
5055 CFMutableDictionaryRef newConfig
= NULL
;
5057 if (config
!= NULL
) {
5058 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
5060 newConfig
= CFDictionaryCreateMutable(NULL
,
5062 &kCFTypeDictionaryKeyCallBacks
,
5063 &kCFTypeDictionaryValueCallBacks
);
5065 CFDictionarySetValue(newConfig
,
5066 kEAPClientPropUserPasswordKeychainItemID
,
5068 ok
= SCNetworkInterfaceSetExtendedConfiguration(interface
,
5071 CFRelease(newConfig
);
5074 CFRelease(unique_id
);
5075 if (label
!= NULL
) CFRelease(label
);
5076 if (description
!= NULL
) CFRelease(description
);
5080 case kSCNetworkInterfacePasswordTypeIPSecXAuth
: {
5081 SCNetworkServiceRef service
= NULL
;
5082 CFStringRef xauth_id
;
5084 // get configuration
5085 config
= SCNetworkInterfaceGetConfiguration(interface
);
5088 xauth_id
= copyXAuthID(config
, serviceID
);
5090 // get "Account", "Name", "Kind"
5091 if (config
!= NULL
) {
5092 // auth name --> keychain "Account"
5093 account
= CFDictionaryGetValue(config
, kSCPropNetIPSecXAuthName
);
5095 // IPSec [user defined] "name" --> keychain "Name"
5096 label
= CFDictionaryGetValue(config
, kSCPropUserDefinedName
);
5099 if (label
== NULL
) {
5100 // service name --> keychain "Name"
5101 service
= (SCNetworkServiceRef
)__SCNetworkServiceCreatePrivate(NULL
,
5106 label
= SCNetworkServiceGetName(service
);
5107 if (label
== NULL
) {
5108 // interface name --> keychain "Name"
5109 label
= SCNetworkInterfaceGetLocalizedDisplayName(interface
);
5113 if (bundle
!= NULL
) {
5114 // "IPSec XAuth Password" --> keychain "Kind"
5115 description
= CFBundleCopyLocalizedString(bundle
,
5116 CFSTR("KEYCHAIN_KIND_IPSEC_XAUTH_PASSWORD"),
5117 CFSTR("IPSec XAuth Password"),
5122 ok
= _SCPreferencesSystemKeychainPasswordItemSet(prefs
,
5124 (label
!= NULL
) ? label
: CFSTR("VPN Connection"),
5125 (description
!= NULL
) ? description
: CFSTR("IPSec XAuth Password"),
5130 CFMutableDictionaryRef newConfig
;
5132 if (config
!= NULL
) {
5133 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
5135 newConfig
= CFDictionaryCreateMutable(NULL
,
5137 &kCFTypeDictionaryKeyCallBacks
,
5138 &kCFTypeDictionaryValueCallBacks
);
5140 CFDictionarySetValue(newConfig
,
5141 kSCPropNetIPSecXAuthPassword
,
5143 CFDictionarySetValue(newConfig
,
5144 kSCPropNetIPSecXAuthPasswordEncryption
,
5145 kSCValNetIPSecXAuthPasswordEncryptionKeychain
);
5146 ok
= SCNetworkInterfaceSetConfiguration(interface
, newConfig
);
5147 CFRelease(newConfig
);
5150 CFRelease(xauth_id
);
5151 if (description
!= NULL
) CFRelease(description
);
5152 if (service
!= NULL
) CFRelease(service
);
5157 _SCErrorSet(kSCStatusInvalidArgument
);
5166 #pragma mark SCNetworkInterface [InterfaceNamer] SPIs
5169 SCNetworkInterfaceRef
5170 _SCNetworkInterfaceCreateWithIONetworkInterfaceObject(io_object_t if_obj
)
5172 SCNetworkInterfaceRef interface
= NULL
;
5174 /* initialize runtime */
5175 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
5177 if (IOObjectConformsTo(if_obj
, kIONetworkInterfaceClass
)) {
5178 interface
= createInterface(if_obj
, processNetworkInterface
);
5179 } else if (IOObjectConformsTo(if_obj
, kIOSerialBSDServiceValue
)) {
5180 interface
= createInterface(if_obj
, processSerialInterface
);
5188 _SCNetworkInterfaceGetConfigurationAction(SCNetworkInterfaceRef interface
)
5190 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
5192 return interfacePrivate
->configurationAction
;
5197 _SCNetworkInterfaceGetHardwareAddress(SCNetworkInterfaceRef interface
)
5199 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
5201 return interfacePrivate
->address
;
5206 _SCNetworkInterfaceGetIOInterfaceType(SCNetworkInterfaceRef interface
)
5208 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
5210 return interfacePrivate
->type
;
5215 _SCNetworkInterfaceGetIOInterfaceUnit(SCNetworkInterfaceRef interface
)
5217 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
5219 return interfacePrivate
->unit
;
5224 _SCNetworkInterfaceGetIOPath(SCNetworkInterfaceRef interface
)
5226 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
5228 return interfacePrivate
->path
;
5233 _SCNetworkInterfaceIsBuiltin(SCNetworkInterfaceRef interface
)
5235 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
5237 return interfacePrivate
->builtin
;
5242 #pragma mark SCNetworkInterface SPIs
5246 _SCNetworkInterfaceCopySlashDevPath(SCNetworkInterfaceRef interface
)
5248 io_registry_entry_t device
;
5249 io_iterator_t device_iterator
= MACH_PORT_NULL
;
5250 CFStringRef device_path
= NULL
;
5251 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
5253 CFStringRef match_keys
[2];
5254 CFTypeRef match_vals
[2];
5255 CFDictionaryRef match_dict
;
5256 CFDictionaryRef matching
;
5258 if (interfacePrivate
->entity_device
== NULL
) {
5262 if (interfacePrivate
->entity_device_unique
== NULL
) {
5266 match_keys
[0] = CFSTR(kIOTTYBaseNameKey
);
5267 match_vals
[0] = interfacePrivate
->entity_device
;
5268 match_dict
= CFDictionaryCreate(NULL
,
5269 (const void **)match_keys
,
5270 (const void **)match_vals
,
5272 &kCFTypeDictionaryKeyCallBacks
,
5273 &kCFTypeDictionaryValueCallBacks
);
5275 match_keys
[0] = CFSTR(kIOProviderClassKey
);
5276 match_vals
[0] = CFSTR(kIOSerialBSDServiceValue
);
5277 match_keys
[1] = CFSTR(kIOPropertyMatchKey
);
5278 match_vals
[1] = match_dict
;
5279 matching
= CFDictionaryCreate(NULL
,
5280 (const void **)match_keys
,
5281 (const void **)match_vals
,
5282 sizeof(match_keys
)/sizeof(match_keys
[0]),
5283 &kCFTypeDictionaryKeyCallBacks
,
5284 &kCFTypeDictionaryValueCallBacks
);
5285 CFRelease(match_dict
);
5287 // note: this "matching" dictionary will be consumed by the call to IOServiceGetMatchingServices
5288 kr
= IOServiceGetMatchingServices(masterPort
, matching
, &device_iterator
);
5289 if (kr
!= kIOReturnSuccess
) {
5290 SCLog(TRUE
, LOG_DEBUG
, CFSTR("IOServiceGetMatchingServices() failed, kr = 0x%x"), kr
);
5294 while ((device_path
== NULL
) &&
5295 ((device
= IOIteratorNext(device_iterator
)) != MACH_PORT_NULL
)) {
5296 CFDictionaryRef overrides
;
5298 overrides
= IORegistryEntrySearchCFProperty(device
,
5300 CFSTR("DeviceModemOverrides"),
5302 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
5303 if (overrides
!= NULL
) {
5304 if (isA_CFDictionary(overrides
)) {
5305 CFStringRef matchIdentifier
;
5307 matchIdentifier
= CFDictionaryGetValue(overrides
, CFSTR("UniqueIdentifier"));
5308 if (isA_CFString(matchIdentifier
) &&
5309 CFEqual(interfacePrivate
->entity_device_unique
, matchIdentifier
)) {
5310 device_path
= IORegistryEntryCreateCFProperty(device
,
5311 CFSTR(kIOTTYDeviceKey
),
5316 CFRelease(overrides
);
5318 IOObjectRelease(device
);
5321 IOObjectRelease(device_iterator
);
5325 if (device_path
== NULL
) {
5326 // if we haven't found an exact match to our UniqueIdentifier
5327 // so we simply return the base name.
5328 device_path
= SCNetworkInterfaceGetBSDName(interface
);
5329 if (device_path
!= NULL
) {
5330 CFRetain(device_path
);
5339 _SCNetworkInterfaceIsBluetoothPAN(SCNetworkInterfaceRef interface
)
5341 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
5343 return (interfacePrivate
->sort_order
== kSortBluetoothPAN
);
5348 _SCNetworkInterfaceIsModemV92(SCNetworkInterfaceRef interface
)
5350 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
5352 return interfacePrivate
->modemIsV92
;
5357 _SCNetworkInterfaceIsTethered(SCNetworkInterfaceRef interface
)
5359 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
5361 return (interfacePrivate
->sort_order
== kSortTethered
);
5366 #pragma mark SCNetworkInterface [internal] SPIs
5370 SCNetworkInterfacePrivateRef
5371 __SCNetworkInterfaceCreateCopy(CFAllocatorRef allocator
,
5372 SCNetworkInterfaceRef interface
,
5373 SCPreferencesRef prefs
,
5374 CFStringRef serviceID
)
5376 SCNetworkInterfacePrivateRef oldPrivate
= (SCNetworkInterfacePrivateRef
)interface
;
5377 SCNetworkInterfacePrivateRef newPrivate
;
5379 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
5380 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
5382 if (interface
== kSCNetworkInterfaceIPv4
) {
5383 return (SCNetworkInterfacePrivateRef
)CFRetain(interface
);
5386 newPrivate
= __SCNetworkInterfaceCreatePrivate(NULL
, NULL
, prefs
, serviceID
, NULL
);
5387 newPrivate
->interface_type
= oldPrivate
->interface_type
;
5388 if (oldPrivate
->interface
!= NULL
) {
5389 newPrivate
->interface
= (SCNetworkInterfaceRef
)__SCNetworkInterfaceCreateCopy(NULL
, // allocator
5390 oldPrivate
->interface
, // interface
5391 prefs
, // [new] prefs
5392 serviceID
); // [new] serviceID
5394 if (oldPrivate
->name
!= NULL
) {
5395 newPrivate
->name
= CFRetain(oldPrivate
->name
);
5397 if (oldPrivate
->localized_name
!= NULL
) {
5398 newPrivate
->localized_name
= CFRetain(oldPrivate
->localized_name
);
5400 newPrivate
->localized_key
= oldPrivate
->localized_key
;
5401 if (oldPrivate
->localized_arg1
!= NULL
) {
5402 newPrivate
->localized_arg1
= CFRetain(oldPrivate
->localized_arg1
);
5404 if (oldPrivate
->localized_arg2
!= NULL
) {
5405 newPrivate
->localized_arg2
= CFRetain(oldPrivate
->localized_arg2
);
5407 if (oldPrivate
->unsaved
!= NULL
) {
5408 newPrivate
->unsaved
= CFDictionaryCreateMutableCopy(NULL
, 0, oldPrivate
->unsaved
);
5410 if (oldPrivate
->entity_device
!= NULL
) {
5411 newPrivate
->entity_device
= CFRetain(oldPrivate
->entity_device
);
5413 if (oldPrivate
->entity_device_unique
!= NULL
) {
5414 newPrivate
->entity_device_unique
= CFRetain(oldPrivate
->entity_device_unique
);
5416 newPrivate
->entity_type
= oldPrivate
->entity_type
;
5417 newPrivate
->entity_subtype
= oldPrivate
->entity_subtype
;
5418 if (oldPrivate
->supported_interface_types
!= NULL
) {
5419 newPrivate
->supported_interface_types
= CFArrayCreateMutableCopy(NULL
, 0, oldPrivate
->supported_interface_types
);
5421 if (oldPrivate
->supported_protocol_types
!= NULL
) {
5422 newPrivate
->supported_protocol_types
= CFArrayCreateMutableCopy(NULL
, 0, oldPrivate
->supported_protocol_types
);
5424 if (oldPrivate
->address
!= NULL
) {
5425 newPrivate
->address
= CFRetain(oldPrivate
->address
);
5427 newPrivate
->builtin
= oldPrivate
->builtin
;
5428 if (oldPrivate
->configurationAction
!= NULL
) {
5429 newPrivate
->configurationAction
= CFRetain(oldPrivate
->configurationAction
);
5431 if (oldPrivate
->location
!= NULL
) {
5432 newPrivate
->location
= CFRetain(oldPrivate
->location
);
5434 if (oldPrivate
->path
!= NULL
) {
5435 newPrivate
->path
= CFRetain(oldPrivate
->path
);
5437 if (oldPrivate
->overrides
!= NULL
) {
5438 newPrivate
->overrides
= CFDictionaryCreateMutableCopy(NULL
, 0, oldPrivate
->overrides
);
5440 newPrivate
->modemIsV92
= oldPrivate
->modemIsV92
;
5441 if (oldPrivate
->type
!= NULL
) {
5442 newPrivate
->type
= CFRetain(oldPrivate
->type
);
5444 if (oldPrivate
->unit
!= NULL
) {
5445 newPrivate
->unit
= CFRetain(oldPrivate
->unit
);
5447 newPrivate
->sort_order
= oldPrivate
->sort_order
;
5448 #if !TARGET_OS_IPHONE
5449 newPrivate
->supportsBond
= oldPrivate
->supportsBond
;
5450 if (oldPrivate
->bond
.interfaces
!= NULL
) {
5451 newPrivate
->bond
.interfaces
= CFRetain(oldPrivate
->bond
.interfaces
);
5453 if (oldPrivate
->bond
.mode
!= NULL
) {
5454 newPrivate
->bond
.mode
= CFRetain(oldPrivate
->bond
.mode
);
5456 if (oldPrivate
->bond
.options
!= NULL
) {
5457 newPrivate
->bond
.options
= CFRetain(oldPrivate
->bond
.options
);
5459 newPrivate
->supportsVLAN
= oldPrivate
->supportsVLAN
;
5460 if (oldPrivate
->vlan
.interface
!= NULL
) {
5461 newPrivate
->vlan
.interface
= CFRetain(oldPrivate
->vlan
.interface
);
5463 if (oldPrivate
->vlan
.tag
!= NULL
) {
5464 newPrivate
->vlan
.tag
= CFRetain(oldPrivate
->vlan
.tag
);
5466 if (oldPrivate
->vlan
.options
!= NULL
) {
5467 newPrivate
->vlan
.options
= CFRetain(oldPrivate
->vlan
.options
);
5469 #endif // !TARGET_OS_IPHONE
5477 __SCNetworkInterfaceCopyDeepConfiguration(SCNetworkSetRef set
, SCNetworkInterfaceRef interface
)
5479 CFMutableArrayRef configs
;
5481 configs
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
5483 while (interface
!= NULL
) {
5484 CFStringRef defaultType
;
5485 CFMutableDictionaryRef interfaceConfiguration
;
5487 interfaceConfiguration
= CFDictionaryCreateMutable(NULL
,
5489 &kCFTypeDictionaryKeyCallBacks
,
5490 &kCFTypeDictionaryValueCallBacks
);
5492 defaultType
= __SCNetworkInterfaceGetDefaultConfigurationType(interface
);
5493 if (defaultType
!= NULL
) {
5494 CFDictionaryRef config
;
5495 CFArrayRef extendedTypes
;
5498 config
= __SCNetworkInterfaceGetConfiguration(interface
, defaultType
);
5500 config
= __SCNetworkInterfaceGetDefaultConfiguration(set
, interface
);
5502 if (config
== NULL
) {
5503 config
= (CFDictionaryRef
)kCFNull
;
5505 CFDictionarySetValue(interfaceConfiguration
, defaultType
, config
);
5507 extendedTypes
= extendedConfigurationTypes(interface
);
5508 if (extendedTypes
!= NULL
) {
5512 n
= CFArrayGetCount(extendedTypes
);
5513 for (i
= 0; i
< n
; i
++) {
5514 CFStringRef extendedType
;
5516 extendedType
= CFArrayGetValueAtIndex(extendedTypes
, i
);
5517 config
= __SCNetworkInterfaceGetConfiguration(interface
, extendedType
);
5518 if (config
== NULL
) {
5519 config
= (CFDictionaryRef
)kCFNull
;
5521 CFDictionarySetValue(interfaceConfiguration
, extendedType
, config
);
5524 CFRelease(extendedTypes
);
5528 CFArrayAppendValue(configs
, interfaceConfiguration
);
5529 CFRelease(interfaceConfiguration
);
5531 interface
= SCNetworkInterfaceGetInterface(interface
);
5540 __SCNetworkInterfaceSetDeepConfiguration(SCNetworkSetRef set
, SCNetworkInterfaceRef interface
, CFArrayRef configs
)
5544 for (i
= 0; interface
!= NULL
; i
++) {
5545 CFStringRef defaultType
;
5546 CFDictionaryRef interfaceConfiguration
;
5548 interfaceConfiguration
= (configs
!= NULL
) ? CFArrayGetValueAtIndex(configs
, i
) : NULL
;
5550 defaultType
= __SCNetworkInterfaceGetDefaultConfigurationType(interface
);
5551 if (defaultType
!= NULL
) {
5552 CFDictionaryRef config
;
5553 CFArrayRef extendedTypes
;
5555 config
= (interfaceConfiguration
!= NULL
) ? CFDictionaryGetValue(interfaceConfiguration
, defaultType
)
5557 if (config
== (CFDictionaryRef
)kCFNull
) {
5561 // if service is not associated with the set
5562 if (!__SCNetworkInterfaceSetConfiguration(interface
, defaultType
, config
, TRUE
)) {
5563 SCLog(TRUE
, LOG_DEBUG
,
5564 CFSTR("__SCNetworkInterfaceSetDeepConfiguration __SCNetworkInterfaceSetConfiguration() failed, interface=%@, type=%@"),
5569 // apply default configuration to this set
5570 if (!__SCNetworkInterfaceSetDefaultConfiguration(set
, interface
, defaultType
, config
, TRUE
)) {
5571 SCLog(TRUE
, LOG_DEBUG
,
5572 CFSTR("__SCNetworkInterfaceSetDeepConfiguration __SCNetworkInterfaceSetDefaultConfiguration() failed, interface=%@, type=%@"),
5578 extendedTypes
= extendedConfigurationTypes(interface
);
5579 if (extendedTypes
!= NULL
) {
5583 n
= CFArrayGetCount(extendedTypes
);
5584 for (j
= 0; j
< n
; j
++) {
5585 CFStringRef extendedType
;
5587 extendedType
= CFArrayGetValueAtIndex(extendedTypes
, j
);
5588 config
= (interfaceConfiguration
!= NULL
) ? CFDictionaryGetValue(interfaceConfiguration
, extendedType
)
5590 if (config
== (CFDictionaryRef
)kCFNull
) {
5593 if (!__SCNetworkInterfaceSetConfiguration(interface
, extendedType
, config
, TRUE
)) {
5594 SCLog(TRUE
, LOG_DEBUG
,
5595 CFSTR("__SCNetworkInterfaceSetDeepConfiguration __SCNetworkInterfaceSetConfiguration() failed, interface=%@, type=%@"),
5601 CFRelease(extendedTypes
);
5605 interface
= SCNetworkInterfaceGetInterface(interface
);