2 * Copyright (c) 2004, 2005 Apple Computer, 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 * Elizaabeth Douglas <elizabeth@apple.com>
32 * Quinn <eskimo1@apple.com>
36 #include <CoreFoundation/CoreFoundation.h>
37 #include <CoreFoundation/CFRuntime.h>
38 #include <SystemConfiguration/SystemConfiguration.h>
39 #include <SystemConfiguration/SCNetworkConfigurationInternal.h>
40 #include <SystemConfiguration/SCValidation.h>
41 #include <SystemConfiguration/SCPrivate.h>
42 #include <SystemConfiguration/BondConfiguration.h>
43 #include <SystemConfiguration/VLANConfiguration.h>
45 #include <IOKit/IOKitLib.h>
46 #include <IOKit/IOCFBundle.h>
47 #include <IOKit/IOBSD.h>
48 #include <IOKit/network/IONetworkController.h>
49 #include <IOKit/network/IONetworkInterface.h>
50 #include <IOKit/network/IOEthernetInterface.h> // for kIOEthernetInterfaceClass
51 #include <IOKit/serial/IOSerialKeys.h>
52 #include <IOKit/storage/IOStorageDeviceCharacteristics.h>
53 #include "dy_framework.h"
55 #ifndef kIODeviceSupportsHoldKey
56 #define kIODeviceSupportsHoldKey "V92Modem"
59 #include "SCNetworkConfiguration.h"
60 #include "SCNetworkConfigurationInternal.h"
63 #include <mach/mach.h>
65 #include <net/if_types.h>
66 #include <sys/param.h>
67 #include <sys/types.h>
70 #include <NSSystemDirectories.h>
73 static CFStringRef
__SCNetworkInterfaceCopyDescription (CFTypeRef cf
);
74 static void __SCNetworkInterfaceDeallocate (CFTypeRef cf
);
75 static Boolean
__SCNetworkInterfaceEqual (CFTypeRef cf1
, CFTypeRef cf2
);
95 const CFStringRef kSCNetworkInterfaceType6to4
= CFSTR("6to4");
96 const CFStringRef kSCNetworkInterfaceTypeBluetooth
= CFSTR("Bluetooth");
97 const CFStringRef kSCNetworkInterfaceTypeBond
= CFSTR("Bond");
98 const CFStringRef kSCNetworkInterfaceTypeEthernet
= CFSTR("Ethernet");
99 const CFStringRef kSCNetworkInterfaceTypeFireWire
= CFSTR("FireWire");
100 const CFStringRef kSCNetworkInterfaceTypeIEEE80211
= CFSTR("IEEE80211"); // IEEE 802.11, AirPort
101 const CFStringRef kSCNetworkInterfaceTypeIrDA
= CFSTR("IrDA");
102 const CFStringRef kSCNetworkInterfaceTypeL2TP
= CFSTR("L2TP");
103 const CFStringRef kSCNetworkInterfaceTypeModem
= CFSTR("Modem");
104 const CFStringRef kSCNetworkInterfaceTypePPP
= CFSTR("PPP");
105 const CFStringRef kSCNetworkInterfaceTypePPTP
= CFSTR("PPTP");
106 const CFStringRef kSCNetworkInterfaceTypeSerial
= CFSTR("Serial");
107 const CFStringRef kSCNetworkInterfaceTypeVLAN
= CFSTR("VLAN");
109 const CFStringRef kSCNetworkInterfaceTypeIPv4
= CFSTR("IPv4");
111 static SCNetworkInterfacePrivate __kSCNetworkInterfaceIPv4
= {
112 INIT_CFRUNTIME_BASE(NULL
, 0, 0x0080), // cfBase
113 NULL
, // interface type
114 NULL
, // localized name
115 NULL
, // localization key
116 NULL
, // localization arg1
117 NULL
, // localization arg2
118 NULL
, // [layered] interface
121 NULL
, // entity_device
123 NULL
, // entity_subtype
124 NULL
, // supported_interface_types
125 NULL
, // supported_protocol_types
132 FALSE
, // supportsBond
133 FALSE
, // supportsVLAN
134 kSortUnknown
// sort_order
137 const SCNetworkInterfaceRef kSCNetworkInterfaceIPv4
= (SCNetworkInterfaceRef
)&__kSCNetworkInterfaceIPv4
;
146 #define doAppleTalk 1<<0
150 #define doProxies 1<<4
152 static const struct {
153 const CFStringRef
*interface_type
;
154 const CFStringRef
*entity_hardware
;
155 Boolean per_interface_config
;
156 uint32_t supported_interfaces
;
157 const CFStringRef
*ppp_subtype
;
158 uint32_t supported_protocols
;
159 } configurations
[] = {
160 // interface type entity_hardware if config? interface types PPP sub-type interface protocols
161 // ===================================== ================= ========== ======================= ======================================= =========================================
162 { &kSCNetworkInterfaceType6to4
, &kSCEntNet6to4
, FALSE
, doNone
, NULL
, doIPv6
},
163 { &kSCNetworkInterfaceTypeBluetooth
, &kSCEntNetModem
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypePPPSerial
, doNone
},
164 { &kSCNetworkInterfaceTypeBond
, &kSCEntNetEthernet
, TRUE
, doNone
, NULL
, doAppleTalk
|doDNS
|doIPv4
|doIPv6
|doProxies
},
165 { &kSCNetworkInterfaceTypeEthernet
, &kSCEntNetEthernet
, TRUE
, doPPP
, &kSCValNetInterfaceSubTypePPPoE
, doAppleTalk
|doDNS
|doIPv4
|doIPv6
|doProxies
},
166 { &kSCNetworkInterfaceTypeFireWire
, &kSCEntNetFireWire
, TRUE
, doNone
, NULL
, doDNS
|doIPv4
|doIPv6
|doProxies
},
167 { &kSCNetworkInterfaceTypeIEEE80211
, &kSCEntNetAirPort
, TRUE
, doPPP
, &kSCValNetInterfaceSubTypePPPoE
, doAppleTalk
|doDNS
|doIPv4
|doIPv6
|doProxies
},
168 { &kSCNetworkInterfaceTypeIrDA
, &kSCEntNetModem
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypePPPSerial
, doNone
},
169 { &kSCNetworkInterfaceTypeL2TP
, NULL
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypeL2TP
, doNone
},
170 { &kSCNetworkInterfaceTypeModem
, &kSCEntNetModem
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypePPPSerial
, doNone
},
171 { &kSCNetworkInterfaceTypePPP
, &kSCEntNetPPP
, FALSE
, doNone
, NULL
, doDNS
|doIPv4
|doIPv6
|doProxies
},
172 { &kSCNetworkInterfaceTypePPTP
, NULL
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypePPTP
, doNone
},
173 { &kSCNetworkInterfaceTypeSerial
, &kSCEntNetModem
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypePPPSerial
, doNone
},
174 { &kSCNetworkInterfaceTypeVLAN
, &kSCEntNetEthernet
, TRUE
, doNone
, NULL
, doAppleTalk
|doDNS
|doIPv4
|doIPv6
|doProxies
},
175 // ===================================== ================= ========== ======================= ======================================= =========================================
176 { &kSCNetworkInterfaceTypeIPv4
, NULL
, FALSE
, do6to4
|doL2TP
|doPPTP
, NULL
, doNone
}
180 #define SYSTEMCONFIGURATION_BUNDLE_ID CFSTR("com.apple.SystemConfiguration")
181 #define NETWORKINTERFACE_LOCALIZATIONS CFSTR("NetworkInterface")
182 static CFBundleRef bundle
= NULL
;
185 static CFTypeID __kSCNetworkInterfaceTypeID
= _kCFRuntimeNotATypeID
;
188 static const CFRuntimeClass __SCNetworkInterfaceClass
= {
190 "SCNetworkInterface", // className
193 __SCNetworkInterfaceDeallocate
, // dealloc
194 __SCNetworkInterfaceEqual
, // equal
196 NULL
, // copyFormattingDesc
197 __SCNetworkInterfaceCopyDescription
// copyDebugDesc
201 static pthread_once_t initialized
= PTHREAD_ONCE_INIT
;
204 static __inline__ CFTypeRef
205 isA_SCNetworkInterface(CFTypeRef obj
)
207 return (isA_CFType(obj
, SCNetworkInterfaceGetTypeID()));
212 __SCNetworkInterfaceCopyDescription(CFTypeRef cf
)
214 CFAllocatorRef allocator
= CFGetAllocator(cf
);
215 CFMutableStringRef result
;
216 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)cf
;
218 result
= CFStringCreateMutable(allocator
, 0);
219 CFStringAppendFormat(result
, NULL
, CFSTR("<SCNetworkInterface %p [%p]> {"), cf
, allocator
);
220 CFStringAppendFormat(result
, NULL
, CFSTR("type = %@"), interfacePrivate
->interface_type
);
221 CFStringAppendFormat(result
, NULL
, CFSTR(", entity_device = %@"), interfacePrivate
->entity_device
);
222 CFStringAppendFormat(result
, NULL
, CFSTR(", entity_type = %@"), interfacePrivate
->entity_type
);
223 if (interfacePrivate
->entity_subtype
!= NULL
) {
224 CFStringAppendFormat(result
, NULL
, CFSTR(" / %@"), interfacePrivate
->entity_subtype
);
226 if (interfacePrivate
->localized_name
!= NULL
) {
227 CFStringAppendFormat(result
, NULL
, CFSTR(", name = %@"), interfacePrivate
->localized_name
);
229 if (interfacePrivate
->localized_key
!= NULL
) {
230 CFStringAppendFormat(result
, NULL
, CFSTR(", name = \"%@\""), interfacePrivate
->localized_key
);
231 if (interfacePrivate
->localized_arg1
!= NULL
) {
232 CFStringAppendFormat(result
, NULL
, CFSTR("+\"%@\""), interfacePrivate
->localized_arg1
);
234 if (interfacePrivate
->localized_arg2
!= NULL
) {
235 CFStringAppendFormat(result
, NULL
, CFSTR("+\"%@\""), interfacePrivate
->localized_arg2
);
239 if (interfacePrivate
->address
!= NULL
) {
240 CFStringAppendFormat(result
, NULL
, CFSTR(", address = %@"), interfacePrivate
->address
);
242 CFStringAppendFormat(result
, NULL
, CFSTR(", builtin = %s"), interfacePrivate
->builtin
? "TRUE" : "FALSE");
243 if (interfacePrivate
->location
!= NULL
) {
244 CFStringAppendFormat(result
, NULL
, CFSTR(", location = %@"), interfacePrivate
->location
);
246 if (interfacePrivate
->path
!= NULL
) {
247 CFStringAppendFormat(result
, NULL
, CFSTR(", path = %@"), interfacePrivate
->path
);
249 if (interfacePrivate
->modemCCL
!= NULL
) {
250 CFStringAppendFormat(result
, NULL
, CFSTR(", modemCCL = %@"), interfacePrivate
->modemCCL
);
252 CFStringAppendFormat(result
, NULL
, CFSTR(", order = %d"), interfacePrivate
->sort_order
);
253 if (interfacePrivate
->service
!= NULL
) {
254 CFStringAppendFormat(result
, NULL
, CFSTR(", service=%@"), interfacePrivate
->service
);
256 if (interfacePrivate
->interface
!= NULL
) {
257 CFStringAppendFormat(result
, NULL
, CFSTR(", interface=%@"), interfacePrivate
->interface
);
259 if (interfacePrivate
->unsaved
!= NULL
) {
260 CFStringAppendFormat(result
, NULL
, CFSTR(", unsaved=%@"), interfacePrivate
->unsaved
);
262 CFStringAppendFormat(result
, NULL
, CFSTR("}"));
269 __SCNetworkInterfaceDeallocate(CFTypeRef cf
)
271 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)cf
;
273 /* release resources */
275 if (interfacePrivate
->interface
!= NULL
)
276 CFRelease(interfacePrivate
->interface
);
278 if (interfacePrivate
->localized_name
!= NULL
)
279 CFRelease(interfacePrivate
->localized_name
);
281 if (interfacePrivate
->localized_arg1
!= NULL
)
282 CFRelease(interfacePrivate
->localized_arg1
);
284 if (interfacePrivate
->localized_arg2
!= NULL
)
285 CFRelease(interfacePrivate
->localized_arg2
);
287 if (interfacePrivate
->unsaved
!= NULL
)
288 CFRelease(interfacePrivate
->unsaved
);
290 if (interfacePrivate
->entity_device
!= NULL
)
291 CFRelease(interfacePrivate
->entity_device
);
293 if (interfacePrivate
->supported_interface_types
!= NULL
)
294 CFRelease(interfacePrivate
->supported_interface_types
);
296 if (interfacePrivate
->supported_protocol_types
!= NULL
)
297 CFRelease(interfacePrivate
->supported_protocol_types
);
299 if (interfacePrivate
->address
!= NULL
)
300 CFRelease(interfacePrivate
->address
);
302 if (interfacePrivate
->location
!= NULL
)
303 CFRelease(interfacePrivate
->location
);
305 if (interfacePrivate
->path
!= NULL
)
306 CFRelease(interfacePrivate
->path
);
308 if (interfacePrivate
->modemCCL
!= NULL
)
309 CFRelease(interfacePrivate
->modemCCL
);
316 __SCNetworkInterfaceEqual(CFTypeRef cf1
, CFTypeRef cf2
)
318 SCNetworkInterfacePrivateRef if1
= (SCNetworkInterfacePrivateRef
)cf1
;
319 SCNetworkInterfacePrivateRef if2
= (SCNetworkInterfacePrivateRef
)cf2
;
324 if (!CFEqual(if1
->interface_type
, if2
->interface_type
)) {
325 return FALSE
; // if not the same interface type
328 if (if1
->entity_device
!= if2
->entity_device
) {
329 if ((if1
->entity_device
!= NULL
) && (if2
->entity_device
!= NULL
)) {
330 if (!CFEqual(if1
->entity_device
, if2
->entity_device
)) {
331 return FALSE
; // if not the same device
334 return FALSE
; // if only one interface has a device
343 __SCNetworkInterfaceInitialize(void)
346 __kSCNetworkInterfaceTypeID
= _CFRuntimeRegisterClass(&__SCNetworkInterfaceClass
);
348 // initialize __kSCNetworkInterfaceIPv4
349 _CFRuntimeSetInstanceTypeID(&__kSCNetworkInterfaceIPv4
, __kSCNetworkInterfaceTypeID
);
350 __kSCNetworkInterfaceIPv4
.interface_type
= kSCNetworkInterfaceTypeIPv4
;
351 __kSCNetworkInterfaceIPv4
.localized_key
= CFSTR("ipv4");
353 // get CFBundleRef for SystemConfiguration.framework
354 bundle
= CFBundleGetBundleWithIdentifier(SYSTEMCONFIGURATION_BUNDLE_ID
);
355 if (bundle
== NULL
) {
359 url
= CFURLCreateWithFileSystemPath(NULL
,
360 CFSTR("/System/Library/Frameworks/SystemConfiguration.framework"),
361 kCFURLPOSIXPathStyle
,
363 bundle
= CFBundleCreate(NULL
, url
);
371 __private_extern__ SCNetworkInterfacePrivateRef
372 __SCNetworkInterfaceCreatePrivate(CFAllocatorRef allocator
,
373 SCNetworkInterfaceRef interface
,
374 SCNetworkServiceRef service
,
377 SCNetworkInterfacePrivateRef interfacePrivate
;
380 /* initialize runtime */
381 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
383 /* allocate target */
384 size
= sizeof(SCNetworkInterfacePrivate
) - sizeof(CFRuntimeBase
);
385 interfacePrivate
= (SCNetworkInterfacePrivateRef
)_CFRuntimeCreateInstance(allocator
,
386 __kSCNetworkInterfaceTypeID
,
389 if (interfacePrivate
== NULL
) {
393 interfacePrivate
->interface_type
= NULL
;
394 interfacePrivate
->localized_name
= NULL
;
395 interfacePrivate
->localized_key
= NULL
;
396 interfacePrivate
->localized_arg1
= NULL
;
397 interfacePrivate
->localized_arg2
= NULL
;
398 interfacePrivate
->interface
= (interface
!= NULL
) ? CFRetain(interface
) : NULL
;
399 interfacePrivate
->service
= service
;
400 interfacePrivate
->unsaved
= NULL
;
401 interfacePrivate
->entity_device
= NULL
;
402 interfacePrivate
->entity_type
= NULL
;
403 interfacePrivate
->entity_subtype
= NULL
;
404 interfacePrivate
->supported_interface_types
= NULL
;
405 interfacePrivate
->supported_protocol_types
= NULL
;
406 interfacePrivate
->address
= NULL
;
407 interfacePrivate
->builtin
= FALSE
;
408 interfacePrivate
->path
= (path
!= NULL
) ? CFStringCreateWithCString(NULL
, path
, kCFStringEncodingUTF8
)
410 interfacePrivate
->location
= NULL
;
411 interfacePrivate
->modemCCL
= NULL
;
412 interfacePrivate
->modemIsV92
= FALSE
;
413 interfacePrivate
->supportsBond
= FALSE
;
414 interfacePrivate
->supportsVLAN
= FALSE
;
415 interfacePrivate
->sort_order
= kSortUnknown
;
417 return interfacePrivate
;
421 /* ---------- ordering ---------- */
425 split_path(CFStringRef path
)
427 CFArrayRef components
;
428 CFMutableStringRef nPath
;
430 // turn '@'s into '/'s
431 nPath
= CFStringCreateMutableCopy(NULL
, 0, path
);
432 (void) CFStringFindAndReplace(nPath
,
435 CFRangeMake(0, CFStringGetLength(nPath
)),
438 // split path into components to be compared
439 components
= CFStringCreateArrayBySeparatingStrings(NULL
, nPath
, CFSTR("/"));
446 static CFComparisonResult
447 compare_interfaces(const void *val1
, const void *val2
, void *context
)
449 SCNetworkInterfacePrivateRef dev1
= (SCNetworkInterfacePrivateRef
)val1
;
450 SCNetworkInterfacePrivateRef dev2
= (SCNetworkInterfacePrivateRef
)val2
;
451 CFComparisonResult res
= kCFCompareEqualTo
;
453 /* sort by interface type */
454 if (dev1
->sort_order
!= dev2
->sort_order
) {
455 if (dev1
->sort_order
< dev2
->sort_order
) {
456 res
= kCFCompareLessThan
;
458 res
= kCFCompareGreaterThan
;
463 /* built-in interfaces sort first */
464 if (dev1
->builtin
!= dev2
->builtin
) {
466 res
= kCFCompareLessThan
;
468 res
= kCFCompareGreaterThan
;
473 /* ... and then, sort built-in interfaces by "location" */
475 if (dev1
->location
!= dev2
->location
) {
476 if (isA_CFString(dev1
->location
)) {
477 if (isA_CFString(dev2
->location
)) {
478 res
= CFStringCompare(dev1
->location
, dev2
->location
, 0);
480 res
= kCFCompareLessThan
;
483 res
= kCFCompareGreaterThan
;
486 if (res
!= kCFCompareEqualTo
) {
492 /* ... and, then sort by IOPathMatch */
493 if ((dev1
->path
!= NULL
) && (dev2
->path
!= NULL
)) {
494 CFArrayRef elements1
;
495 CFArrayRef elements2
;
501 elements1
= split_path(dev1
->path
);
502 n1
= CFArrayGetCount(elements1
);
504 elements2
= split_path(dev2
->path
);
505 n2
= CFArrayGetCount(elements2
);
507 n
= (n1
<= n2
) ? n1
: n2
;
508 for (i
= 0; i
< n
; i
++) {
517 e1
= CFArrayGetValueAtIndex(elements1
, i
);
518 e2
= CFArrayGetValueAtIndex(elements2
, i
);
520 str
= _SC_cfstring_to_cstring(e1
, NULL
, 0, kCFStringEncodingUTF8
);
522 q1
= strtoq(str
, &end
, 16);
523 isNum
= ((*str
!= '\0') && (*end
== '\0') && (errno
== 0));
524 CFAllocatorDeallocate(NULL
, str
);
527 // if e1 is a valid numeric string
528 str
= _SC_cfstring_to_cstring(e2
, NULL
, 0, kCFStringEncodingUTF8
);
530 q2
= strtoq(str
, &end
, 16);
531 isNum
= ((*str
!= '\0') && (*end
== '\0') && (errno
== 0));
532 CFAllocatorDeallocate(NULL
, str
);
535 // if e2 is also a valid numeric string
538 res
= kCFCompareEqualTo
;
540 } else if (q1
< q2
) {
541 res
= kCFCompareLessThan
;
543 res
= kCFCompareGreaterThan
;
549 res
= CFStringCompare(e1
, e2
, 0);
550 if (res
!= kCFCompareEqualTo
) {
555 if (res
== kCFCompareEqualTo
) {
557 res
= kCFCompareLessThan
;
558 } else if (n1
< n2
) {
559 res
= kCFCompareGreaterThan
;
563 CFRelease(elements1
);
564 CFRelease(elements2
);
566 if (res
!= kCFCompareEqualTo
) {
571 /* ... and lastly, sort by BSD interface name */
572 if ((dev1
->entity_device
!= NULL
) && (dev2
->entity_device
!= NULL
)) {
573 res
= CFStringCompare(dev1
->entity_device
, dev2
->entity_device
, 0);
581 sort_interfaces(CFMutableArrayRef all_interfaces
)
583 int n
= CFArrayGetCount(all_interfaces
);
589 CFArraySortValues(all_interfaces
, CFRangeMake(0, n
), compare_interfaces
, NULL
);
594 /* ---------- interface details ---------- */
598 IOCopyCFStringValue(CFTypeRef ioVal
)
600 if (isA_CFString(ioVal
)) {
601 return CFStringCreateCopy(NULL
, ioVal
);
604 if (isA_CFData(ioVal
)) {
605 return CFStringCreateWithCString(NULL
,
606 (const char *)CFDataGetBytePtr(ioVal
),
607 kCFStringEncodingUTF8
);
615 IODictionaryCopyCFStringValue(CFDictionaryRef io_dict
, CFStringRef io_key
)
619 ioVal
= CFDictionaryGetValue(io_dict
, io_key
);
620 return IOCopyCFStringValue(ioVal
);
625 IOStringValueHasPrefix(CFTypeRef ioVal
, CFStringRef prefix
)
627 Boolean match
= FALSE
;
628 CFIndex prefixLen
= CFStringGetLength(prefix
);
629 CFStringRef str
= ioVal
;
631 if (!isA_CFString(ioVal
)) {
632 if (isA_CFData(ioVal
)) {
633 str
= CFStringCreateWithCStringNoCopy(NULL
,
634 (const char *)CFDataGetBytePtr(ioVal
),
635 kCFStringEncodingUTF8
,
643 (CFStringGetLength(str
) >= prefixLen
) &&
644 (CFStringCompareWithOptions(str
,
646 CFRangeMake(0, prefixLen
),
647 kCFCompareCaseInsensitive
) == kCFCompareEqualTo
)) {
651 if (str
!= ioVal
) CFRelease(str
);
657 copyMACAddress(CFDictionaryRef controller_dict
)
659 CFStringRef address
= NULL
;
664 char mac
[sizeof("xx:xx:xx:xx:xx:xx:xx:xx")];
667 data
= CFDictionaryGetValue(controller_dict
, CFSTR(kIOMACAddress
));
672 bp
= (uint8_t *)CFDataGetBytePtr(data
);
673 n
= CFDataGetLength(data
) * 3;
675 if (n
> sizeof(mac
)) {
676 mac_p
= CFAllocatorAllocate(NULL
, 0, n
);
679 for (cp
= mac_p
; n
> 0; n
-= 3) {
680 cp
+= snprintf(cp
, n
, "%2.2x:", *bp
++);
683 address
= CFStringCreateWithCString(NULL
, mac_p
, kCFStringEncodingUTF8
);
684 if (mac_p
!= mac
) CFAllocatorDeallocate(NULL
, mac_p
);
689 static const struct {
690 const CFStringRef name
;
691 const CFStringRef slot
;
692 } slot_mappings
[] = {
694 { CFSTR("A1") , CFSTR("1") },
695 { CFSTR("B1") , CFSTR("2") },
696 { CFSTR("C1") , CFSTR("3") },
698 // Blue&White G3, Yikes G4
699 { CFSTR("J12"), CFSTR("1") },
700 { CFSTR("J11"), CFSTR("2") },
701 { CFSTR("J10"), CFSTR("3") },
702 { CFSTR("J9"), CFSTR("4") },
705 { CFSTR("A") , CFSTR("1") },
706 { CFSTR("B") , CFSTR("2") },
707 { CFSTR("C") , CFSTR("3") },
708 { CFSTR("D") , CFSTR("4") },
710 // Digital Audio G4 (and later models)
711 { CFSTR("1") , CFSTR("1") },
712 { CFSTR("2") , CFSTR("2") },
713 { CFSTR("3") , CFSTR("3") },
714 { CFSTR("4") , CFSTR("4") },
715 { CFSTR("5") , CFSTR("5") }
720 pci_slot(io_registry_entry_t interface
, CFTypeRef
*pci_slot_name
)
723 io_registry_entry_t parent
;
724 CFMutableStringRef slot
;
728 if (pci_slot_name
!= NULL
) *pci_slot_name
= NULL
;
730 slot_name
= IORegistryEntryCreateCFProperty(interface
, CFSTR("AAPL,slot-name"), NULL
, 0);
731 if (slot_name
!= NULL
) {
734 slot
= CFStringCreateMutable(NULL
, 0);
735 if (isA_CFString(slot_name
)) {
736 if (pci_slot_name
!= NULL
) *pci_slot_name
= CFStringCreateCopy(NULL
, slot_name
);
737 CFStringAppend(slot
, slot_name
);
738 } else if (isA_CFData(slot_name
)) {
739 if (pci_slot_name
!= NULL
) *pci_slot_name
= CFDataCreateCopy(NULL
, slot_name
);
740 CFStringAppendCString(slot
,
741 (const char *)CFDataGetBytePtr(slot_name
),
742 kCFStringEncodingUTF8
);
745 if (CFStringGetLength(slot
) > 5) {
746 (void) CFStringFindAndReplace(slot
,
750 kCFCompareCaseInsensitive
|kCFCompareAnchored
);
753 for (i
= 0; i
< sizeof(slot_mappings
)/sizeof(slot_mappings
[0]); i
++) {
754 if (CFStringCompare(slot
,
755 slot_mappings
[i
].name
,
756 kCFCompareCaseInsensitive
) == kCFCompareEqualTo
) {
758 slot
= (CFMutableStringRef
)CFRetain(slot_mappings
[i
].slot
);
763 CFRelease(slot_name
);
766 kr
= IORegistryEntryGetParentEntry(interface
, kIOServicePlane
, &parent
);
768 case kIOReturnSuccess
: {
769 CFTypeRef parent_pci_slot_name
= NULL
;
770 CFStringRef parent_slot
;
772 parent_slot
= pci_slot(parent
, &parent_pci_slot_name
);
773 if (parent_slot
!= NULL
) {
774 if (slot
!= NULL
) CFRelease(slot
);
775 slot
= (CFMutableStringRef
)parent_slot
;
777 if (pci_slot_name
!= NULL
) {
778 if (*pci_slot_name
!= NULL
) CFRelease(*pci_slot_name
);
779 *pci_slot_name
= parent_pci_slot_name
;
781 CFRelease(parent_pci_slot_name
);
785 IOObjectRelease(parent
);
788 case kIOReturnNoDevice
:
789 // if we have hit the root node
792 SCLog(TRUE
, LOG_DEBUG
, CFSTR("pci_slot IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr
);
800 static CFComparisonResult
801 compare_bsdNames(const void *val1
, const void *val2
, void *context
)
803 CFStringRef bsd1
= (CFStringRef
)val1
;
804 CFStringRef bsd2
= (CFStringRef
)val2
;
806 return CFStringCompare(bsd1
, bsd2
, 0);
811 pci_port(mach_port_t masterPort
, CFTypeRef slot_name
, CFStringRef bsdName
)
814 CFStringRef port_name
= NULL
;
815 CFMutableArrayRef port_names
;
818 CFStringRef match_keys
[2];
819 CFTypeRef match_vals
[2];
820 CFDictionaryRef match_dict
;
821 CFDictionaryRef matching
;
822 io_registry_entry_t slot
;
823 io_iterator_t slot_iterator
= MACH_PORT_NULL
;
825 match_keys
[0] = CFSTR("AAPL,slot-name");
826 match_vals
[0] = slot_name
;
828 match_dict
= CFDictionaryCreate(NULL
,
829 (const void **)match_keys
,
830 (const void **)match_vals
,
832 &kCFTypeDictionaryKeyCallBacks
,
833 &kCFTypeDictionaryValueCallBacks
);
835 match_keys
[0] = CFSTR(kIOProviderClassKey
);
836 match_vals
[0] = CFSTR("IOPCIDevice");
838 match_keys
[1] = CFSTR(kIOPropertyMatchKey
);
839 match_vals
[1] = match_dict
;
841 // note: the "matching" dictionary will be consumed by the following
842 matching
= CFDictionaryCreate(NULL
,
843 (const void **)match_keys
,
844 (const void **)match_vals
,
845 sizeof(match_keys
)/sizeof(match_keys
[0]),
846 &kCFTypeDictionaryKeyCallBacks
,
847 &kCFTypeDictionaryValueCallBacks
);
848 CFRelease(match_dict
);
850 kr
= IOServiceGetMatchingServices(masterPort
, matching
, &slot_iterator
);
851 if (kr
!= kIOReturnSuccess
) {
852 SCLog(TRUE
, LOG_DEBUG
, CFSTR("pci_port IOServiceGetMatchingServices() failed, kr = 0x%x"), kr
);
853 return MACH_PORT_NULL
;
856 port_names
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
858 while ((slot
= IOIteratorNext(slot_iterator
)) != MACH_PORT_NULL
) {
859 io_registry_entry_t child
;
860 io_iterator_t child_iterator
= MACH_PORT_NULL
;
862 kr
= IORegistryEntryCreateIterator(slot
,
864 kIORegistryIterateRecursively
,
866 if (kr
!= kIOReturnSuccess
) {
867 SCLog(TRUE
, LOG_DEBUG
, CFSTR("pci_port IORegistryEntryCreateIterator() failed, kr = 0x%x"), kr
);
868 return MACH_PORT_NULL
;
871 while ((child
= IOIteratorNext(child_iterator
)) != MACH_PORT_NULL
) {
872 if (IOObjectConformsTo(child
, kIONetworkInterfaceClass
)) {
873 CFStringRef if_bsdName
;
875 if_bsdName
= IORegistryEntryCreateCFProperty(child
,
876 CFSTR(kIOBSDNameKey
),
879 if (if_bsdName
!= NULL
) {
880 CFArrayAppendValue(port_names
, if_bsdName
);
881 CFRelease(if_bsdName
);
884 IOObjectRelease(child
);
886 IOObjectRelease(child_iterator
);
887 IOObjectRelease(slot
);
889 IOObjectRelease(slot_iterator
);
891 n
= CFArrayGetCount(port_names
);
893 CFArraySortValues(port_names
, CFRangeMake(0, n
), compare_bsdNames
, NULL
);
894 n
= CFArrayGetFirstIndexOfValue(port_names
, CFRangeMake(0, n
), bsdName
);
895 if (n
!= kCFNotFound
) {
896 port_name
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%d"), n
+ 1);
900 CFRelease(port_names
);
906 pci_slot_info(mach_port_t masterPort
, io_registry_entry_t interface
, CFStringRef
*slot_name
, CFStringRef
*port_name
)
908 CFStringRef bsd_name
;
910 CFTypeRef pci_slot_name
;
915 bsd_name
= IORegistryEntryCreateCFProperty(interface
, CFSTR(kIOBSDNameKey
), NULL
, 0);
916 if (bsd_name
== NULL
) {
920 *slot_name
= pci_slot(interface
, &pci_slot_name
);
921 if (*slot_name
!= NULL
) {
922 if (pci_slot_name
!= NULL
) {
923 *port_name
= pci_port(masterPort
, pci_slot_name
, bsd_name
);
924 CFRelease(pci_slot_name
);
935 isBuiltIn(io_registry_entry_t interface
)
939 slot
= pci_slot(interface
, NULL
);
941 // interfaces which have a "slot" are not built-in
950 /* ---------- interface enumeration ---------- */
953 typedef Boolean (*processInterface
)(mach_port_t masterPort
,
954 SCNetworkInterfacePrivateRef interfacePrivate
,
955 io_registry_entry_t interface
,
956 CFDictionaryRef interface_dict
,
957 io_registry_entry_t controller
,
958 CFDictionaryRef controller_dict
,
959 io_registry_entry_t bus
,
960 CFDictionaryRef bus_dict
);
964 processNetworkInterface(mach_port_t masterPort
,
965 SCNetworkInterfacePrivateRef interfacePrivate
,
966 io_registry_entry_t interface
,
967 CFDictionaryRef interface_dict
,
968 io_registry_entry_t controller
,
969 CFDictionaryRef controller_dict
,
970 io_registry_entry_t bus
,
971 CFDictionaryRef bus_dict
)
980 num
= CFDictionaryGetValue(interface_dict
, CFSTR(kIOInterfaceType
));
981 if (!isA_CFNumber(num
) ||
982 !CFNumberGetValue(num
, kCFNumberIntType
, &ift
)) {
983 SCPrint(TRUE
, stderr
, CFSTR("Could not get interface type\n"));
991 if ((IOObjectConformsTo(controller
, "IO80211Controller")) ||
992 (IOObjectConformsTo(controller
, "AirPortPCI" )) ||
993 (IOObjectConformsTo(controller
, "AirPortDriver" ))) {
994 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeIEEE80211
;
995 interfacePrivate
->entity_type
= kSCEntNetEthernet
;
996 interfacePrivate
->sort_order
= kSortAirPort
;
998 str
= IODictionaryCopyCFStringValue(bus_dict
, CFSTR("name"));
999 if ((str
!= NULL
) && CFEqual(str
, CFSTR("radio"))) {
1000 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
; // ??
1001 interfacePrivate
->entity_type
= kSCEntNetEthernet
;
1002 interfacePrivate
->sort_order
= kSortOtherWireless
;
1004 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
;
1005 interfacePrivate
->entity_type
= kSCEntNetEthernet
;
1006 interfacePrivate
->sort_order
= kSortEthernet
;
1008 // BOND support only enabled for ethernet devices
1009 interfacePrivate
->supportsBond
= TRUE
;
1012 if (str
!= NULL
) CFRelease(str
);
1016 bVal
= isA_CFBoolean(CFDictionaryGetValue(interface_dict
, CFSTR(kIOBuiltin
)));
1017 if ((bVal
== NULL
) || !CFBooleanGetValue(bVal
)) {
1018 bVal
= isA_CFBoolean(CFDictionaryGetValue(interface_dict
, CFSTR(kIOPrimaryInterface
)));
1021 interfacePrivate
->builtin
= CFBooleanGetValue(bVal
);
1023 interfacePrivate
->builtin
= isBuiltIn(interface
);
1027 interfacePrivate
->location
= IODictionaryCopyCFStringValue(interface_dict
, CFSTR(kIOLocation
));
1030 num
= CFDictionaryGetValue(controller_dict
, CFSTR(kIOFeatures
));
1031 if (isA_CFNumber(num
) &&
1032 CFNumberGetValue(num
, kCFNumberIntType
, & iVal
)) {
1033 if (iVal
& (kIONetworkFeatureHardwareVlan
| kIONetworkFeatureSoftwareVlan
)) {
1034 interfacePrivate
->supportsVLAN
= TRUE
;
1039 if (interfacePrivate
->builtin
) {
1040 if ((interfacePrivate
->location
== NULL
) ||
1041 (CFStringGetLength(interfacePrivate
->location
) == 0)) {
1042 interfacePrivate
->localized_key
= CFSTR("ether");
1044 interfacePrivate
->localized_key
= CFSTR("multiether");
1045 interfacePrivate
->localized_arg1
= CFRetain(interfacePrivate
->location
);
1047 } else if (CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeIEEE80211
)) {
1048 interfacePrivate
->localized_key
= CFSTR("airport");
1049 } else if (interfacePrivate
->sort_order
== kSortOtherWireless
) {
1050 interfacePrivate
->localized_key
= CFSTR("wireless");
1051 interfacePrivate
->localized_arg1
= CFRetain(CFSTR("")); // ??
1053 CFStringRef provider
;
1055 // check provider class
1056 provider
= IORegistryEntrySearchCFProperty(interface
,
1058 CFSTR(kIOProviderClassKey
),
1060 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1061 if (provider
!= NULL
) {
1062 if (CFEqual(provider
, CFSTR("IOPCIDevice"))) {
1063 CFStringRef port_name
;
1064 CFStringRef slot_name
;
1066 if (pci_slot_info(masterPort
, interface
, &slot_name
, &port_name
)) {
1067 if (port_name
== NULL
) {
1068 interfacePrivate
->localized_key
= CFSTR("pci-ether");
1069 interfacePrivate
->localized_arg1
= slot_name
;
1071 interfacePrivate
->localized_key
= CFSTR("pci-multiether");
1072 interfacePrivate
->localized_arg1
= slot_name
;
1073 interfacePrivate
->localized_arg2
= port_name
;
1077 CFRelease(provider
);
1080 if (interfacePrivate
->localized_key
== NULL
) {
1081 // if no provider, not a PCI device, or no slot information
1082 interfacePrivate
->localized_key
= CFSTR("generic-ether");
1083 interfacePrivate
->localized_arg1
= IODictionaryCopyCFStringValue(interface_dict
, CFSTR(kIOBSDNameKey
));
1090 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeFireWire
;
1093 interfacePrivate
->entity_type
= kSCEntNetFireWire
;
1096 interfacePrivate
->builtin
= isBuiltIn(interface
);
1099 interfacePrivate
->sort_order
= kSortFireWire
;
1102 if (interfacePrivate
->builtin
) {
1103 interfacePrivate
->localized_key
= CFSTR("firewire");
1105 CFStringRef slot_name
;
1107 slot_name
= pci_slot(interface
, NULL
);
1108 if (slot_name
!= NULL
) {
1109 interfacePrivate
->localized_key
= CFSTR("pci-firewire");
1110 interfacePrivate
->localized_arg1
= slot_name
;
1116 SCLog(TRUE
, LOG_DEBUG
, CFSTR("processNetworkInterface() failed, unknown interface type = %d"), ift
);
1121 interfacePrivate
->entity_device
= IODictionaryCopyCFStringValue(interface_dict
, CFSTR(kIOBSDNameKey
));
1123 // Hardware (MAC) address
1124 interfacePrivate
->address
= copyMACAddress(controller_dict
);
1131 processSerialInterface(mach_port_t masterPort
,
1132 SCNetworkInterfacePrivateRef interfacePrivate
,
1133 io_registry_entry_t interface
,
1134 CFDictionaryRef interface_dict
,
1135 io_registry_entry_t controller
,
1136 CFDictionaryRef controller_dict
,
1137 io_registry_entry_t bus
,
1138 CFDictionaryRef bus_dict
)
1141 Boolean isModem
= FALSE
;
1146 val
= IORegistryEntrySearchCFProperty(interface
,
1148 CFSTR("HiddenPort"),
1150 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1153 return FALSE
; // if this interface should not be exposed
1157 str
= CFDictionaryGetValue(interface_dict
, CFSTR(kIOTTYBaseNameKey
));
1165 * Exclude ports named "irda" because otherwise the IrDA ports on the
1166 * original iMac (rev's A through D) show up as serial ports. Given
1167 * that only the rev A actually had an IrDA port, and Mac OS X doesn't
1168 * even support it, these ports definitely shouldn't be listed.
1170 if (CFStringCompare(str
,
1172 kCFCompareCaseInsensitive
) == kCFCompareEqualTo
) {
1176 if (IOStringValueHasPrefix(str
, CFSTR("irda-ircomm"))) {
1178 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeIrDA
;
1179 interfacePrivate
->sort_order
= kSortIrDA
;
1180 } else if (IOStringValueHasPrefix(str
, CFSTR("bluetooth"))) {
1182 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeBluetooth
;
1183 interfacePrivate
->sort_order
= kSortBluetooth
;
1186 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeModem
;
1189 val
= IORegistryEntrySearchCFProperty(interface
,
1191 CFSTR(kIODeviceSupportsHoldKey
),
1193 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1197 if (isA_CFNumber(val
) &&
1198 CFNumberGetValue(val
, kCFNumberSInt32Type
, &v92
)) {
1199 interfacePrivate
->modemIsV92
= (v92
== 1);
1206 interfacePrivate
->entity_type
= kSCEntNetModem
;
1208 // Entity (Hardware)
1209 ift
= CFDictionaryGetValue(interface_dict
, CFSTR(kIOSerialBSDTypeKey
));
1210 if (!isA_CFString(ift
)) {
1214 if (CFEqual(ift
, CFSTR(kIOSerialBSDModemType
))) {
1218 if (CFEqual(str
, CFSTR("modem"))) {
1219 interfacePrivate
->builtin
= TRUE
;
1220 interfacePrivate
->sort_order
= kSortInternalModem
;
1221 } else if (CFEqual(str
, CFSTR("usbmodem"))) {
1222 interfacePrivate
->sort_order
= kSortUSBModem
;
1224 interfacePrivate
->sort_order
= kSortModem
;
1226 } else if (CFEqual(ift
, CFSTR(kIOSerialBSDRS232Type
))) {
1228 interfacePrivate
->sort_order
= kSortSerialPort
;
1234 interfacePrivate
->entity_device
= IODictionaryCopyCFStringValue(interface_dict
, CFSTR(kIOTTYDeviceKey
));
1237 val
= IORegistryEntrySearchCFProperty(interface
,
1241 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1243 interfacePrivate
->modemCCL
= IOCopyCFStringValue(val
);
1248 if (CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeIrDA
)) {
1249 interfacePrivate
->localized_key
= CFSTR("irda");
1250 } else if (CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeBluetooth
)) {
1251 interfacePrivate
->localized_key
= CFSTR("bluetooth");
1253 CFStringRef localized
= NULL
;
1254 CFMutableStringRef port
;
1256 port
= CFStringCreateMutableCopy(NULL
, 0, str
);
1257 CFStringLowercase(port
, NULL
);
1260 CFStringAppend(port
, CFSTR("-port"));
1263 if (bundle
!= NULL
) {
1264 localized
= CFBundleCopyLocalizedString(bundle
,
1267 NETWORKINTERFACE_LOCALIZATIONS
);
1269 if (localized
!= NULL
) {
1270 if (!CFEqual(port
, localized
)) {
1271 // if localization available
1272 interfacePrivate
->localized_name
= localized
;
1274 // if no localization available, use TTY base name
1275 CFRelease(localized
);
1276 interfacePrivate
->localized_name
= CFStringCreateCopy(NULL
, str
);
1279 interfacePrivate
->localized_name
= CFStringCreateCopy(NULL
, str
);
1282 if (!isModem
|| !CFEqual(str
, CFSTR("modem"))) {
1283 CFStringRef productName
;
1285 // check if a "Product Name" has been provided
1286 val
= IORegistryEntrySearchCFProperty(interface
,
1288 CFSTR(kIOPropertyProductNameKey
),
1290 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1292 productName
= IOCopyCFStringValue(val
);
1295 if (productName
!= NULL
) {
1296 if (CFStringGetLength(productName
) > 0) {
1297 // if we have a [somewhat reasonable?] product name
1298 CFRelease(interfacePrivate
->localized_name
);
1299 interfacePrivate
->localized_name
= CFRetain(productName
);
1301 // if not provided, also check if the product name
1302 // matches a CCL script
1303 if (interfacePrivate
->modemCCL
== NULL
) {
1304 interfacePrivate
->modemCCL
= CFRetain(productName
);
1308 CFRelease(productName
);
1316 // validate the CCL script
1317 if (interfacePrivate
->modemCCL
!= NULL
) {
1318 char ccl
[MAXPATHLEN
];
1319 char path
[MAXPATHLEN
];
1320 NSSearchPathEnumerationState state
;
1321 Boolean valid
= FALSE
;
1323 (void) _SC_cfstring_to_cstring(interfacePrivate
->modemCCL
,
1326 kCFStringEncodingUTF8
);
1328 state
= NSStartSearchPathEnumeration(NSLibraryDirectory
,
1329 NSLocalDomainMask
|NSSystemDomainMask
);
1330 while ((state
= NSGetNextSearchPathEnumeration(state
, path
))) {
1331 struct stat statBuf
;
1333 if (ccl
[0] == '/') {
1334 path
[0] = '\0'; // if modemCCL is a full path
1336 strlcat(path
, "/Modem Scripts/", sizeof(path
));
1337 strlcat(path
, ccl
, sizeof(path
));
1340 if (stat(path
, &statBuf
) == 0) {
1341 if (S_ISREG(statBuf
.st_mode
)) {
1342 // if we have a valid CCL script
1347 if (errno
== ENOENT
) {
1351 SCLog(TRUE
, LOG_DEBUG
,
1352 CFSTR("processSerialInterface stat() failed: %s"),
1359 // if the CCL script is not valid
1360 CFRelease(interfacePrivate
->modemCCL
);
1361 interfacePrivate
->modemCCL
= NULL
;
1370 findMatchingInterfaces(mach_port_t masterPort
, CFDictionaryRef matching
, processInterface func
)
1372 CFMutableArrayRef interfaces
;
1373 io_registry_entry_t interface
;
1375 io_iterator_t iterator
= MACH_PORT_NULL
;
1377 kr
= IOServiceGetMatchingServices(masterPort
, matching
, &iterator
);
1378 if (kr
!= kIOReturnSuccess
) {
1379 SCLog(TRUE
, LOG_DEBUG
, CFSTR("findMatchingInterfaces IOServiceGetMatchingServices() failed, kr = 0x%x"), kr
);
1383 interfaces
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1385 while ((interface
= IOIteratorNext(iterator
)) != MACH_PORT_NULL
) {
1386 io_registry_entry_t bus
= MACH_PORT_NULL
;
1387 CFMutableDictionaryRef bus_dict
= NULL
;
1388 io_registry_entry_t controller
= MACH_PORT_NULL
;
1389 CFMutableDictionaryRef controller_dict
= NULL
;
1390 SCNetworkInterfacePrivateRef interfacePrivate
= NULL
;
1391 CFMutableDictionaryRef interface_dict
= NULL
;
1394 kr
= IORegistryEntryGetPath(interface
, kIOServicePlane
, path
);
1395 if (kr
!= kIOReturnSuccess
) {
1396 SCPrint(TRUE
, stderr
, CFSTR("IORegistryEntryGetPath() failed, kr = 0x%x"), kr
);
1400 kr
= IORegistryEntryCreateCFProperties(interface
, &interface_dict
, NULL
, kNilOptions
);
1401 if (kr
!= kIOReturnSuccess
) {
1402 SCPrint(TRUE
, stderr
, CFSTR("IORegistryEntryCreateCFProperties() failed, kr = 0x%x\n"), kr
);
1406 /* get the controller node */
1407 kr
= IORegistryEntryGetParentEntry(interface
, kIOServicePlane
, &controller
);
1408 if (kr
!= KERN_SUCCESS
) {
1409 SCLog(TRUE
, LOG_INFO
, CFSTR("findMatchingInterfaces IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr
);
1413 /* get the dictionary associated with the node */
1414 kr
= IORegistryEntryCreateCFProperties(controller
, &controller_dict
, NULL
, kNilOptions
);
1415 if (kr
!= KERN_SUCCESS
) {
1416 SCLog(TRUE
, LOG_INFO
, CFSTR("findMatchingInterfaces IORegistryEntryCreateCFProperties() failed, kr = 0x%x"), kr
);
1420 /* get the bus node */
1421 kr
= IORegistryEntryGetParentEntry(controller
, kIOServicePlane
, &bus
);
1422 if (kr
!= KERN_SUCCESS
) {
1423 SCLog(TRUE
, LOG_INFO
, CFSTR("findMatchingInterfaces IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr
);
1427 /* get the dictionary associated with the node */
1428 kr
= IORegistryEntryCreateCFProperties(bus
, &bus_dict
, NULL
, kNilOptions
);
1429 if (kr
!= KERN_SUCCESS
) {
1430 SCLog(TRUE
, LOG_INFO
, CFSTR("findMatchingInterfaces IORegistryEntryCreateCFProperties() failed, kr = 0x%x"), kr
);
1434 interfacePrivate
= __SCNetworkInterfaceCreatePrivate(NULL
, NULL
, NULL
, path
);
1436 if ((*func
)(masterPort
, interfacePrivate
, interface
, interface_dict
, controller
, controller_dict
, bus
, bus_dict
)) {
1437 CFArrayAppendValue(interfaces
, (SCNetworkInterfaceRef
)interfacePrivate
);
1440 CFRelease(interfacePrivate
);
1444 if (interface
!= MACH_PORT_NULL
) IOObjectRelease(interface
);
1445 if (interface_dict
!= NULL
) CFRelease(interface_dict
);
1447 if (controller
!= MACH_PORT_NULL
) IOObjectRelease(controller
);
1448 if (controller_dict
!= NULL
) CFRelease(controller_dict
);
1450 if (bus
!= MACH_PORT_NULL
) IOObjectRelease(bus
);
1451 if (bus_dict
!= NULL
) CFRelease(bus_dict
);
1454 IOObjectRelease(iterator
);
1460 /* ---------- Bond configuration ---------- */
1463 SCNetworkInterfaceSupportsBonding(SCNetworkInterfaceRef interface
)
1465 return ((SCNetworkInterfacePrivateRef
)interface
)->supportsBond
;
1469 SCNetworkInterfaceRef
1470 SCNetworkInterfaceCreateWithBond(BondInterfaceRef bond
)
1472 SCNetworkInterfacePrivateRef interfacePrivate
;
1473 CFStringRef bond_if
;
1475 bond_if
= BondInterfaceGetInterface(bond
);
1476 if (bond_if
== NULL
) {
1480 interfacePrivate
= __SCNetworkInterfaceCreatePrivate(NULL
, NULL
, NULL
, NULL
);
1481 if (interfacePrivate
== NULL
) {
1485 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeBond
;
1486 interfacePrivate
->entity_type
= kSCEntNetEthernet
;
1487 interfacePrivate
->entity_device
= CFStringCreateCopy(NULL
, bond_if
);
1488 interfacePrivate
->builtin
= TRUE
;
1489 interfacePrivate
->sort_order
= kSortBond
;
1491 interfacePrivate
->localized_key
= CFSTR("bond");
1492 interfacePrivate
->localized_arg1
= CFRetain(interfacePrivate
->entity_device
);
1494 return (SCNetworkInterfaceRef
)interfacePrivate
;
1499 findBondInterfaces(CFStringRef match
)
1501 CFMutableArrayRef interfaces
= NULL
;
1504 BondPreferencesRef prefs
;
1505 CFArrayRef bonds
= NULL
;
1507 prefs
= BondPreferencesCreate(NULL
);
1508 if (prefs
== NULL
) {
1513 bonds
= BondPreferencesCopyInterfaces(prefs
);
1514 if (bonds
== NULL
) {
1519 n
= CFArrayGetCount(bonds
);
1525 interfaces
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1527 for (i
= 0; i
< n
; i
++) {
1528 SCNetworkInterfaceRef interface
;
1529 BondInterfaceRef bond
= CFArrayGetValueAtIndex(bonds
, i
);
1530 CFStringRef bond_if
;
1532 bond_if
= BondInterfaceGetInterface(bond
);
1533 if (bond_if
== NULL
) {
1537 if ((match
!= NULL
) && !CFEqual(bond_if
, match
)) {
1541 interface
= SCNetworkInterfaceCreateWithBond(bond
);
1542 CFArrayAppendValue(interfaces
, interface
);
1543 CFRelease(interface
);
1548 if (bonds
!= NULL
) CFRelease(bonds
);
1554 /* ---------- VLAN configuration ---------- */
1556 SCNetworkInterfaceRef
1557 SCNetworkInterfaceCreateWithVLAN(VLANInterfaceRef vlan
)
1559 SCNetworkInterfacePrivateRef interfacePrivate
;
1560 CFStringRef vlan_if
;
1562 vlan_if
= VLANInterfaceGetInterface(vlan
);
1563 if (vlan_if
== NULL
) {
1567 interfacePrivate
= __SCNetworkInterfaceCreatePrivate(NULL
, NULL
, NULL
, NULL
);
1568 if (interfacePrivate
== NULL
) {
1572 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeVLAN
;
1573 interfacePrivate
->entity_type
= kSCEntNetEthernet
;
1574 interfacePrivate
->entity_device
= CFStringCreateCopy(NULL
, vlan_if
);
1575 interfacePrivate
->builtin
= TRUE
;
1576 interfacePrivate
->sort_order
= kSortVLAN
;
1578 interfacePrivate
->localized_key
= CFSTR("vlan");
1579 interfacePrivate
->localized_arg1
= CFRetain(interfacePrivate
->entity_device
);
1581 return (SCNetworkInterfaceRef
)interfacePrivate
;
1586 findVLANInterfaces(CFStringRef match
)
1588 CFMutableArrayRef interfaces
= NULL
;
1591 VLANPreferencesRef prefs
;
1592 CFArrayRef vlans
= NULL
;
1594 prefs
= VLANPreferencesCreate(NULL
);
1595 if (prefs
== NULL
) {
1600 vlans
= VLANPreferencesCopyInterfaces(prefs
);
1601 if (vlans
== NULL
) {
1606 n
= CFArrayGetCount(vlans
);
1612 interfaces
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1614 for (i
= 0; i
< n
; i
++) {
1615 SCNetworkInterfaceRef interface
;
1616 VLANInterfaceRef vlan
= CFArrayGetValueAtIndex(vlans
, i
);
1617 CFStringRef vlan_if
;
1619 vlan_if
= VLANInterfaceGetInterface(vlan
);
1620 if (vlan_if
== NULL
) {
1624 if ((match
!= NULL
) && !CFEqual(vlan_if
, match
)) {
1628 interface
= SCNetworkInterfaceCreateWithVLAN(vlan
);
1629 CFArrayAppendValue(interfaces
, interface
);
1630 CFRelease(interface
);
1635 if (vlans
!= NULL
) CFRelease(vlans
);
1641 /* ---------- helper functions ---------- */
1645 findConfiguration(CFStringRef interface_type
)
1649 for (i
= 0; i
< sizeof(configurations
)/sizeof(configurations
[0]); i
++) {
1650 if (CFEqual(interface_type
, *configurations
[i
].interface_type
)) {
1660 copyConfigurationPaths(SCNetworkInterfacePrivateRef interfacePrivate
)
1662 CFMutableArrayRef array
= NULL
;
1663 CFIndex interfaceIndex
;
1665 SCNetworkServicePrivateRef servicePrivate
;
1667 servicePrivate
= (SCNetworkServicePrivateRef
)interfacePrivate
->service
;
1668 if (servicePrivate
== NULL
) {
1669 // if not associated with a service (yet)
1673 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1675 interfaceIndex
= findConfiguration(interfacePrivate
->interface_type
);
1676 if (interfaceIndex
== kCFNotFound
) {
1677 // unknown interface type, use per-service configuration preferences
1678 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1679 servicePrivate
->serviceID
, // service
1680 interfacePrivate
->interface_type
); // entity
1681 CFArrayAppendValue(array
, path
);
1686 if (configurations
[interfaceIndex
].entity_hardware
== NULL
) {
1687 // if no configuration information can be associated with this interface type
1693 if (configurations
[interfaceIndex
].per_interface_config
) {
1698 // known interface type, per-interface configuration preferences
1700 // 1. look for all sets which contain the associated service
1701 // 2. add a per-set path for the interface configuration for
1704 sets
= SCNetworkSetCopyAll(servicePrivate
->prefs
);
1705 n
= (sets
!= NULL
) ? CFArrayGetCount(sets
) : 0;
1707 for (i
= 0; i
< n
; i
++) {
1708 CFArrayRef services
;
1709 SCNetworkSetRef set
;
1711 set
= CFArrayGetValueAtIndex(sets
, i
);
1712 services
= SCNetworkSetCopyServices(set
);
1713 if (CFArrayContainsValue(services
,
1714 CFRangeMake(0, CFArrayGetCount(services
)),
1715 interfacePrivate
->service
)) {
1716 path
= SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL
, // allocator
1717 SCNetworkSetGetSetID(set
), // set
1718 interfacePrivate
->entity_device
, // service
1719 *configurations
[interfaceIndex
].entity_hardware
); // entity
1720 CFArrayAppendValue(array
, path
);
1723 CFRelease(services
);
1726 if (CFArrayGetCount(array
) == 0) {
1731 if (sets
!= NULL
) CFRelease(sets
);
1733 // known interface type, per-service configuration preferences
1734 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1735 servicePrivate
->serviceID
, // service
1736 *configurations
[interfaceIndex
].entity_hardware
); // entity
1737 CFArrayAppendValue(array
, path
);
1747 /* ---------- preferences entity for interface ---------- */
1750 __private_extern__ CFDictionaryRef
1751 __SCNetworkInterfaceCopyInterfaceEntity(SCNetworkInterfaceRef interface
)
1753 CFMutableDictionaryRef entity
;
1754 CFIndex interfaceIndex
;
1755 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
1757 entity
= CFDictionaryCreateMutable(NULL
,
1759 &kCFTypeDictionaryKeyCallBacks
,
1760 &kCFTypeDictionaryValueCallBacks
);
1761 if (interfacePrivate
->entity_type
!= NULL
) {
1762 CFDictionarySetValue(entity
,
1763 kSCPropNetInterfaceType
,
1764 interfacePrivate
->entity_type
);
1766 if (interfacePrivate
->entity_subtype
!= NULL
) {
1767 CFDictionarySetValue(entity
,
1768 kSCPropNetInterfaceSubType
,
1769 interfacePrivate
->entity_subtype
);
1771 if (interfacePrivate
->entity_device
!= NULL
) {
1772 CFDictionarySetValue(entity
,
1773 kSCPropNetInterfaceDeviceName
,
1774 interfacePrivate
->entity_device
);
1777 // match the "hardware" with the lowest layer
1779 SCNetworkInterfaceRef nextInterface
;
1781 nextInterface
= SCNetworkInterfaceGetInterface(interface
);
1782 if (nextInterface
== NULL
) {
1786 interface
= nextInterface
;
1788 interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
1790 interfaceIndex
= findConfiguration(interfacePrivate
->interface_type
);
1791 if (interfaceIndex
!= kCFNotFound
) {
1792 if (configurations
[interfaceIndex
].entity_hardware
!= NULL
) {
1793 CFDictionarySetValue(entity
,
1794 kSCPropNetInterfaceHardware
,
1795 *configurations
[interfaceIndex
].entity_hardware
);
1798 CFDictionarySetValue(entity
,
1799 kSCPropNetInterfaceHardware
,
1800 interfacePrivate
->interface_type
);
1803 if (CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeModem
) &&
1804 interfacePrivate
->modemIsV92
) {
1808 num
= CFNumberCreate(NULL
, kCFNumberIntType
, &one
);
1809 CFDictionarySetValue(entity
,
1810 kSCPropNetInterfaceSupportsModemOnHold
,
1819 /* ---------- interface from preferences entity ---------- */
1822 __private_extern__ SCNetworkInterfaceRef
1823 __SCNetworkInterfaceCreateWithEntity(CFAllocatorRef allocator
,
1824 CFDictionaryRef interface_entity
,
1825 SCNetworkServiceRef service
)
1827 SCNetworkInterfacePrivateRef interfacePrivate
= NULL
;
1828 CFStringRef ifDevice
;
1829 CFStringRef ifSubType
;
1831 static mach_port_t masterPort
= MACH_PORT_NULL
;
1832 CFArrayRef matching_interfaces
= NULL
;
1834 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
1835 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
1837 if (masterPort
== MACH_PORT_NULL
) {
1840 kr
= IOMasterPort(MACH_PORT_NULL
, &masterPort
);
1841 if (kr
!= KERN_SUCCESS
) {
1846 ifType
= CFDictionaryGetValue(interface_entity
, kSCPropNetInterfaceType
);
1847 if (!isA_CFString(ifType
)) {
1851 ifSubType
= CFDictionaryGetValue(interface_entity
, kSCPropNetInterfaceSubType
);
1852 if (CFEqual(ifType
, kSCValNetInterfaceTypePPP
)) {
1853 if (!isA_CFString(ifSubType
)) {
1858 ifDevice
= CFDictionaryGetValue(interface_entity
, kSCPropNetInterfaceDeviceName
);
1860 if (CFEqual(ifType
, kSCValNetInterfaceTypeEthernet
) ||
1861 CFEqual(ifType
, kSCValNetInterfaceTypeFireWire
) ||
1862 (CFEqual(ifType
, kSCValNetInterfaceTypePPP
) && CFEqual(ifSubType
, kSCValNetInterfaceSubTypePPPoE
))) {
1863 char bsdName
[IFNAMSIZ
+ 1];
1864 CFMutableDictionaryRef matching
;
1866 if (!isA_CFString(ifDevice
)) {
1870 if (_SC_cfstring_to_cstring(ifDevice
, bsdName
, sizeof(bsdName
), kCFStringEncodingASCII
) == NULL
) {
1874 matching
= IOBSDNameMatching(masterPort
, 0, bsdName
);
1875 if (matching
== NULL
) {
1879 // note: the "matching" dictionary will be consumed by the following
1880 matching_interfaces
= findMatchingInterfaces(masterPort
, matching
, processNetworkInterface
);
1882 } else if (CFEqual(ifType
, kSCValNetInterfaceTypePPP
)) {
1883 if (CFEqual(ifSubType
, kSCValNetInterfaceSubTypePPPSerial
)) {
1884 CFDictionaryRef matching
;
1885 CFStringRef match_keys
[2];
1886 CFStringRef match_vals
[2];
1888 if (!isA_CFString(ifDevice
)) {
1892 match_keys
[0] = CFSTR(kIOProviderClassKey
);
1893 match_vals
[0] = CFSTR(kIOSerialBSDServiceValue
);
1895 match_keys
[1] = CFSTR(kIOTTYDeviceKey
);
1896 match_vals
[1] = ifDevice
;
1898 matching
= CFDictionaryCreate(NULL
,
1899 (const void **)match_keys
,
1900 (const void **)match_vals
,
1901 sizeof(match_keys
)/sizeof(match_keys
[0]),
1902 &kCFTypeDictionaryKeyCallBacks
,
1903 &kCFTypeDictionaryValueCallBacks
);
1905 // note: the "matching" dictionary will be consumed by the following
1906 matching_interfaces
= findMatchingInterfaces(masterPort
, matching
, processSerialInterface
);
1908 } else if (CFEqual(ifSubType
, kSCValNetInterfaceSubTypeL2TP
)) {
1909 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
1910 kSCNetworkInterfaceTypeL2TP
);
1911 } else if (CFEqual(ifSubType
, kSCValNetInterfaceSubTypePPTP
)) {
1912 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
1913 kSCNetworkInterfaceTypePPTP
);
1915 // XXX do we allow non-Apple variants of PPP??? XXX
1916 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
1919 } else if (CFEqual(ifType
, kSCValNetInterfaceType6to4
)) {
1920 if (!isA_CFString(ifDevice
)) {
1924 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
1925 kSCNetworkInterfaceType6to4
);
1926 } else if (CFStringFind(ifType
, CFSTR("."), 0).location
!= kCFNotFound
) {
1927 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
1931 if (matching_interfaces
!= NULL
) {
1934 n
= CFArrayGetCount(matching_interfaces
);
1937 if (CFEqual(ifType
, kSCValNetInterfaceTypeEthernet
)) {
1941 bonds
= findBondInterfaces(ifDevice
);
1942 if (bonds
!= NULL
) {
1943 if (CFArrayGetCount(bonds
) == 1) {
1944 interfacePrivate
= (SCNetworkInterfacePrivateRef
)CFArrayGetValueAtIndex(bonds
, 0);
1945 CFRetain(interfacePrivate
);
1951 vlans
= findVLANInterfaces(ifDevice
);
1952 if (vlans
!= NULL
) {
1953 if (CFArrayGetCount(vlans
) == 1) {
1954 interfacePrivate
= (SCNetworkInterfacePrivateRef
)CFArrayGetValueAtIndex(vlans
, 0);
1955 CFRetain(interfacePrivate
);
1963 interfacePrivate
= (SCNetworkInterfacePrivateRef
)CFArrayGetValueAtIndex(matching_interfaces
, 0);
1964 CFRetain(interfacePrivate
);
1967 SCLog(TRUE
, LOG_DEBUG
, CFSTR("__SCNetworkInterfaceCreateWithEntity() failed, more than one interface matches %@"), ifDevice
);
1968 if (matching_interfaces
!= NULL
) CFRelease(matching_interfaces
);
1969 _SCErrorSet(kSCStatusFailed
);
1972 CFRelease(matching_interfaces
);
1977 if (interfacePrivate
== NULL
) {
1978 CFStringRef entity_hardware
;
1981 * if device not present on this system
1983 interfacePrivate
= __SCNetworkInterfaceCreatePrivate(NULL
, NULL
, NULL
, NULL
);
1984 interfacePrivate
->entity_type
= ifType
;
1985 interfacePrivate
->entity_subtype
= ifSubType
;
1986 interfacePrivate
->entity_device
= (ifDevice
!= NULL
) ? CFStringCreateCopy(NULL
, ifDevice
) : NULL
;
1988 entity_hardware
= CFDictionaryGetValue(interface_entity
, kSCPropNetInterfaceHardware
);
1989 if (CFEqual(ifType
, kSCValNetInterfaceTypeEthernet
)) {
1990 if ((entity_hardware
!= NULL
) &&
1991 CFEqual(entity_hardware
, kSCEntNetAirPort
)) {
1992 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeIEEE80211
;
1994 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
;
1996 } else if (CFEqual(ifType
, kSCValNetInterfaceTypeFireWire
)) {
1997 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeFireWire
;
1998 } else if (CFEqual(ifType
, kSCValNetInterfaceTypePPP
)) {
1999 if (CFEqual(ifSubType
, kSCValNetInterfaceSubTypePPPoE
)) {
2000 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
;
2001 } else if (CFEqual(ifSubType
, kSCValNetInterfaceSubTypePPPSerial
)) {
2002 if (CFStringHasPrefix(ifDevice
, CFSTR("irda"))) {
2003 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeIrDA
;
2004 } else if (CFStringHasPrefix(ifDevice
, CFSTR("Bluetooth"))) {
2005 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeBluetooth
;
2007 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeModem
;
2011 CFRelease(interfacePrivate
);
2012 interfacePrivate
= (SCNetworkInterfacePrivateRef
)kSCNetworkInterfaceIPv4
;
2013 CFRetain(interfacePrivate
);
2016 // unknown interface type
2017 CFRelease(interfacePrivate
);
2018 interfacePrivate
= NULL
;
2022 if ((interfacePrivate
!= NULL
) && (service
!= NULL
)) {
2023 interfacePrivate
->service
= service
;
2026 if (CFEqual(ifType
, kSCValNetInterfaceTypePPP
)) {
2027 SCNetworkInterfaceRef parent
;
2029 parent
= SCNetworkInterfaceCreateWithInterface((SCNetworkInterfaceRef
)interfacePrivate
,
2030 kSCNetworkInterfaceTypePPP
);
2031 CFRelease(interfacePrivate
);
2032 interfacePrivate
= (SCNetworkInterfacePrivateRef
)parent
;
2035 return (SCNetworkInterfaceRef
)interfacePrivate
;
2039 /* ---------- SCNetworkInterface APIs ---------- */
2042 CFArrayRef
/* of SCNetworkInterfaceRef's */
2043 SCNetworkInterfaceCopyAll()
2045 CFMutableArrayRef all_interfaces
;
2046 static mach_port_t masterPort
= MACH_PORT_NULL
;
2047 CFDictionaryRef matching
;
2048 CFStringRef match_keys
[2];
2049 CFStringRef match_vals
[2];
2050 CFArrayRef new_interfaces
;
2052 if (masterPort
== MACH_PORT_NULL
) {
2055 kr
= IOMasterPort(MACH_PORT_NULL
, &masterPort
);
2056 if (kr
!= KERN_SUCCESS
) {
2061 all_interfaces
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
2063 // get Ethernet, Firewire, and AirPort interfaces
2065 matching
= IOServiceMatching(kIONetworkInterfaceClass
);
2066 new_interfaces
= findMatchingInterfaces(masterPort
, matching
, processNetworkInterface
);
2067 if (new_interfaces
!= NULL
) {
2068 CFArrayAppendArray(all_interfaces
, new_interfaces
, CFRangeMake(0, CFArrayGetCount(new_interfaces
)));
2069 CFRelease(new_interfaces
);
2072 // get Modem interfaces
2074 match_keys
[0] = CFSTR(kIOProviderClassKey
);
2075 match_vals
[0] = CFSTR(kIOSerialBSDServiceValue
);
2077 match_keys
[1] = CFSTR(kIOSerialBSDTypeKey
);
2078 match_vals
[1] = CFSTR(kIOSerialBSDModemType
);
2080 matching
= CFDictionaryCreate(NULL
,
2081 (const void **)match_keys
,
2082 (const void **)match_vals
,
2083 sizeof(match_keys
)/sizeof(match_keys
[0]),
2084 &kCFTypeDictionaryKeyCallBacks
,
2085 &kCFTypeDictionaryValueCallBacks
);
2086 new_interfaces
= findMatchingInterfaces(masterPort
, matching
, processSerialInterface
);
2087 if (new_interfaces
!= NULL
) {
2088 CFArrayAppendArray(all_interfaces
, new_interfaces
, CFRangeMake(0, CFArrayGetCount(new_interfaces
)));
2089 CFRelease(new_interfaces
);
2092 // get serial (RS232) interfaces
2094 match_keys
[0] = CFSTR(kIOProviderClassKey
);
2095 match_vals
[0] = CFSTR(kIOSerialBSDServiceValue
);
2097 match_keys
[1] = CFSTR(kIOSerialBSDTypeKey
);
2098 match_vals
[1] = CFSTR(kIOSerialBSDRS232Type
);
2100 matching
= CFDictionaryCreate(NULL
,
2101 (const void **)match_keys
,
2102 (const void **)match_vals
,
2103 sizeof(match_keys
)/sizeof(match_keys
[0]),
2104 &kCFTypeDictionaryKeyCallBacks
,
2105 &kCFTypeDictionaryValueCallBacks
);
2106 new_interfaces
= findMatchingInterfaces(masterPort
, matching
, processSerialInterface
);
2107 if (new_interfaces
!= NULL
) {
2108 CFArrayAppendArray(all_interfaces
, new_interfaces
, CFRangeMake(0, CFArrayGetCount(new_interfaces
)));
2109 CFRelease(new_interfaces
);
2112 new_interfaces
= findBondInterfaces(NULL
);
2113 if (new_interfaces
!= NULL
) {
2114 CFArrayAppendArray(all_interfaces
, new_interfaces
, CFRangeMake(0, CFArrayGetCount(new_interfaces
)));
2115 CFRelease(new_interfaces
);
2118 new_interfaces
= findVLANInterfaces(NULL
);
2119 if (new_interfaces
!= NULL
) {
2120 CFArrayAppendArray(all_interfaces
, new_interfaces
, CFRangeMake(0, CFArrayGetCount(new_interfaces
)));
2121 CFRelease(new_interfaces
);
2124 sort_interfaces(all_interfaces
);
2126 return all_interfaces
;
2130 CFArrayRef
/* of kSCNetworkInterfaceTypeXXX CFStringRef's */
2131 SCNetworkInterfaceGetSupportedInterfaceTypes(SCNetworkInterfaceRef interface
)
2134 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2136 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
2137 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
2139 if (interfacePrivate
->supported_interface_types
!= NULL
) {
2143 i
= findConfiguration(interfacePrivate
->interface_type
);
2144 if (i
!= kCFNotFound
) {
2145 if (configurations
[i
].supported_interfaces
!= doNone
) {
2146 interfacePrivate
->supported_interface_types
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
2147 if (configurations
[i
].supported_interfaces
& do6to4
) {
2148 CFArrayAppendValue(interfacePrivate
->supported_interface_types
, kSCNetworkInterfaceType6to4
);
2150 if (configurations
[i
].supported_interfaces
& doL2TP
) {
2151 CFArrayAppendValue(interfacePrivate
->supported_interface_types
, kSCNetworkInterfaceTypeL2TP
);
2153 if (configurations
[i
].supported_interfaces
& doPPP
) {
2154 CFArrayAppendValue(interfacePrivate
->supported_interface_types
, kSCNetworkInterfaceTypePPP
);
2156 if (configurations
[i
].supported_interfaces
& doPPTP
) {
2157 CFArrayAppendValue(interfacePrivate
->supported_interface_types
, kSCNetworkInterfaceTypePPTP
);
2164 return interfacePrivate
->supported_interface_types
;
2168 CFArrayRef
/* of kSCNetworkProtocolTypeXXX CFStringRef's */
2169 SCNetworkInterfaceGetSupportedProtocolTypes(SCNetworkInterfaceRef interface
)
2172 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2174 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
2175 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
2177 if (interfacePrivate
->supported_protocol_types
!= NULL
) {
2181 i
= findConfiguration(interfacePrivate
->interface_type
);
2182 if (i
!= kCFNotFound
) {
2183 if (configurations
[i
].supported_protocols
!= doNone
) {
2184 interfacePrivate
->supported_protocol_types
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
2185 if (configurations
[i
].supported_protocols
& doAppleTalk
) {
2186 CFArrayAppendValue(interfacePrivate
->supported_protocol_types
, kSCNetworkProtocolTypeAppleTalk
);
2188 if (configurations
[i
].supported_protocols
& doDNS
) {
2189 CFArrayAppendValue(interfacePrivate
->supported_protocol_types
, kSCNetworkProtocolTypeDNS
);
2191 if (configurations
[i
].supported_protocols
& doIPv4
) {
2192 CFArrayAppendValue(interfacePrivate
->supported_protocol_types
, kSCNetworkProtocolTypeIPv4
);
2194 if (configurations
[i
].supported_protocols
& doIPv6
) {
2195 CFArrayAppendValue(interfacePrivate
->supported_protocol_types
, kSCNetworkProtocolTypeIPv6
);
2197 if (configurations
[i
].supported_protocols
& doProxies
) {
2198 CFArrayAppendValue(interfacePrivate
->supported_protocol_types
, kSCNetworkProtocolTypeProxies
);
2205 return interfacePrivate
->supported_protocol_types
;
2209 SCNetworkInterfaceRef
2210 SCNetworkInterfaceCreateWithInterface(SCNetworkInterfaceRef child
, CFStringRef interfaceType
)
2212 SCNetworkInterfacePrivateRef childPrivate
= (SCNetworkInterfacePrivateRef
)child
;
2214 SCNetworkInterfacePrivateRef parentPrivate
;
2216 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
2217 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
2219 childIndex
= findConfiguration(childPrivate
->interface_type
);
2221 parentPrivate
= __SCNetworkInterfaceCreatePrivate(NULL
, child
, childPrivate
->service
, NULL
);
2222 if (parentPrivate
== NULL
) {
2223 _SCErrorSet(kSCStatusFailed
);
2227 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
)) {
2228 parentPrivate
->interface_type
= kSCNetworkInterfaceTypePPP
;
2229 parentPrivate
->entity_type
= kSCEntNetPPP
;
2232 if (childIndex
!= kCFNotFound
) {
2233 if (configurations
[childIndex
].ppp_subtype
!= NULL
) {
2234 parentPrivate
->entity_subtype
= *configurations
[childIndex
].ppp_subtype
;
2236 // sorry, the child interface does not support PPP
2240 // if the child's interface type not known, use the child entities "Type"
2241 parentPrivate
->entity_subtype
= childPrivate
->entity_type
;
2244 if (childPrivate
->entity_device
!= NULL
) {
2245 parentPrivate
->entity_device
= CFStringCreateCopy(NULL
, childPrivate
->entity_device
);
2247 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeL2TP
)) {
2248 if ((childIndex
== kCFNotFound
) ||
2249 ((configurations
[childIndex
].supported_interfaces
& doL2TP
) != doL2TP
)) {
2250 // if the child interface does not support L2TP
2253 parentPrivate
->interface_type
= kSCNetworkInterfaceTypeL2TP
;
2254 parentPrivate
->entity_type
= kSCValNetInterfaceSubTypeL2TP
; // interface config goes into "L2TP"
2255 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPTP
)) {
2256 if ((childIndex
== kCFNotFound
) ||
2257 ((configurations
[childIndex
].supported_interfaces
& doPPTP
) != doPPTP
)) {
2258 // if the child interface does not support PPTP
2261 parentPrivate
->interface_type
= kSCNetworkInterfaceTypePPTP
;
2262 parentPrivate
->entity_type
= kSCValNetInterfaceSubTypePPTP
; // interface config goes into "PPTP"
2263 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceType6to4
)) {
2264 if ((childIndex
== kCFNotFound
) ||
2265 ((configurations
[childIndex
].supported_interfaces
& do6to4
) != do6to4
)) {
2266 // if the child interface does not support 6to4
2270 parentPrivate
->interface_type
= kSCNetworkInterfaceType6to4
;
2271 parentPrivate
->entity_type
= kSCEntNet6to4
;
2272 parentPrivate
->entity_device
= CFRetain(CFSTR("stf0"));
2273 } else if (CFStringFind(interfaceType
, CFSTR("."), 0).location
!= kCFNotFound
) {
2274 // if custom interface type
2275 parentPrivate
->interface_type
= interfaceType
;
2276 parentPrivate
->entity_type
= interfaceType
; // interface config goes into a
2277 // a dictionary with the same
2278 // name as the interfaceType
2280 // unknown interface type
2284 parentPrivate
->sort_order
= childPrivate
->sort_order
;
2286 return (SCNetworkInterfaceRef
)parentPrivate
;
2290 CFRelease(parentPrivate
);
2291 _SCErrorSet(kSCStatusInvalidArgument
);
2296 static CFDictionaryRef
2297 __SCNetworkInterfaceGetConfiguration(SCNetworkInterfaceRef interface
, Boolean okToHold
)
2299 CFDictionaryRef config
= NULL
;
2300 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2303 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
2304 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
2306 paths
= copyConfigurationPaths(interfacePrivate
);
2307 if (paths
!= NULL
) {
2309 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)interfacePrivate
->service
;
2311 path
= CFArrayGetValueAtIndex(paths
, 0);
2312 config
= __getPrefsConfiguration(servicePrivate
->prefs
, path
);
2315 } else if (okToHold
) {
2316 config
= interfacePrivate
->unsaved
;
2324 SCNetworkInterfaceGetConfiguration(SCNetworkInterfaceRef interface
)
2326 return __SCNetworkInterfaceGetConfiguration(interface
, FALSE
);
2331 SCNetworkInterfaceGetBSDName(SCNetworkInterfaceRef interface
)
2333 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2335 if (interfacePrivate
->interface
!= NULL
) {
2339 return interfacePrivate
->entity_device
;
2344 SCNetworkInterfaceGetHardwareAddressString(SCNetworkInterfaceRef interface
)
2346 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2348 return interfacePrivate
->address
;
2352 SCNetworkInterfaceRef
2353 SCNetworkInterfaceGetInterface(SCNetworkInterfaceRef interface
)
2355 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2357 return interfacePrivate
->interface
;
2362 SCNetworkInterfaceGetInterfaceType(SCNetworkInterfaceRef interface
)
2364 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2366 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
2367 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
2369 return interfacePrivate
->interface_type
;
2374 SCNetworkInterfaceGetLocalizedDisplayName(SCNetworkInterfaceRef interface
)
2376 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2378 if (interfacePrivate
->localized_name
== NULL
) {
2379 CFStringRef child
= NULL
;
2380 CFMutableStringRef local
= NULL
;
2382 if (interfacePrivate
->interface
!= NULL
) {
2383 child
= SCNetworkInterfaceGetLocalizedDisplayName(interfacePrivate
->interface
);
2386 if ((bundle
!= NULL
) && (interfacePrivate
->localized_key
!= NULL
)) {
2389 fmt
= CFBundleCopyLocalizedString(bundle
,
2390 interfacePrivate
->localized_key
,
2391 interfacePrivate
->localized_key
,
2392 NETWORKINTERFACE_LOCALIZATIONS
);
2394 local
= CFStringCreateMutable(NULL
, 0);
2395 CFStringAppendFormat(local
,
2398 interfacePrivate
->localized_arg1
,
2399 interfacePrivate
->localized_arg2
);
2404 if (local
== NULL
) {
2405 // create (non-)localized name based on the interface type
2406 local
= CFStringCreateMutableCopy(NULL
, 0, interfacePrivate
->interface_type
);
2408 // ... and, if this is a leaf node, the interface device
2409 if ((interfacePrivate
->entity_device
!= NULL
) && (child
== NULL
)) {
2410 CFStringAppendFormat(local
, NULL
, CFSTR(" (%@)"), interfacePrivate
->entity_device
);
2414 if (child
== NULL
) {
2415 // no child, show just this interfaces localized name
2416 interfacePrivate
->localized_name
= CFStringCreateCopy(NULL
, local
);
2418 // show localized interface name layered over child
2419 interfacePrivate
->localized_name
= CFStringCreateWithFormat(NULL
,
2428 return interfacePrivate
->localized_name
;
2434 __SCNetworkInterfaceGetModemCCL(SCNetworkInterfaceRef interface
)
2436 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2438 return interfacePrivate
->modemCCL
;
2444 __SCNetworkInterfaceIsModemV92(SCNetworkInterfaceRef interface
)
2446 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2448 return interfacePrivate
->modemIsV92
;
2453 SCNetworkInterfaceGetTypeID(void)
2455 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
); /* initialize runtime */
2456 return __kSCNetworkInterfaceTypeID
;
2460 __private_extern__ Boolean
2461 __SCNetworkInterfaceSetConfiguration(SCNetworkInterfaceRef interface
, CFDictionaryRef config
, Boolean okToHold
)
2463 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2467 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
2468 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
2470 paths
= copyConfigurationPaths(interfacePrivate
);
2471 if (paths
!= NULL
) {
2474 SCPreferencesRef prefs
;
2475 SCNetworkServicePrivateRef servicePrivate
;
2477 servicePrivate
= (SCNetworkServicePrivateRef
)interfacePrivate
->service
;
2478 prefs
= servicePrivate
->prefs
;
2480 n
= CFArrayGetCount(paths
);
2481 for (i
= 0; i
< n
; i
++) {
2484 path
= CFArrayGetValueAtIndex(paths
, i
);
2485 ok
= __setPrefsConfiguration(prefs
, path
, config
, FALSE
);
2492 } else if (okToHold
) {
2493 interfacePrivate
->unsaved
= config
;
2496 _SCErrorSet(kSCStatusNoKey
);
2504 SCNetworkInterfaceSetConfiguration(SCNetworkInterfaceRef interface
, CFDictionaryRef config
)
2506 return __SCNetworkInterfaceSetConfiguration(interface
, config
, FALSE
);
2510 /* ---------- SCNetworkInterface internal SPIs ---------- */
2513 __private_extern__ SCNetworkInterfacePrivateRef
2514 __SCNetworkInterfaceCreateCopy(CFAllocatorRef allocator
,
2515 SCNetworkInterfaceRef interface
,
2516 SCNetworkServiceRef service
)
2518 SCNetworkInterfacePrivateRef oldPrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2519 SCNetworkInterfacePrivateRef newPrivate
;
2521 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
2522 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
2524 newPrivate
= __SCNetworkInterfaceCreatePrivate(NULL
, NULL
, NULL
, NULL
);
2525 newPrivate
->interface_type
= oldPrivate
->interface_type
;
2526 if (oldPrivate
->interface
!= NULL
) {
2527 newPrivate
->interface
= (SCNetworkInterfaceRef
)__SCNetworkInterfaceCreateCopy(NULL
, // allocator
2528 oldPrivate
->interface
, // interface
2529 service
); // [new] service
2531 newPrivate
->localized_name
= (oldPrivate
->localized_name
!= NULL
) ? CFRetain(oldPrivate
->localized_name
) : NULL
;
2532 newPrivate
->service
= service
;
2533 newPrivate
->unsaved
= (oldPrivate
->unsaved
!= NULL
) ? CFRetain(oldPrivate
->unsaved
) : NULL
;
2534 newPrivate
->entity_device
= (oldPrivate
->entity_device
!= NULL
) ? CFRetain(oldPrivate
->entity_device
) : NULL
;
2535 newPrivate
->entity_type
= oldPrivate
->entity_type
;
2536 newPrivate
->entity_subtype
= oldPrivate
->entity_subtype
;
2537 if (oldPrivate
->supported_interface_types
!= NULL
) {
2538 newPrivate
->supported_interface_types
= CFArrayCreateMutableCopy(NULL
, 0, oldPrivate
->supported_interface_types
);
2540 if (oldPrivate
->supported_protocol_types
!= NULL
) {
2541 newPrivate
->supported_protocol_types
= CFArrayCreateMutableCopy(NULL
, 0, oldPrivate
->supported_protocol_types
);
2543 newPrivate
->address
= (oldPrivate
->address
!= NULL
) ? CFRetain(oldPrivate
->address
) : NULL
;
2544 newPrivate
->builtin
= oldPrivate
->builtin
;
2545 newPrivate
->path
= (oldPrivate
->path
!= NULL
) ? CFRetain(oldPrivate
->path
) : NULL
;
2546 newPrivate
->location
= (oldPrivate
->location
!= NULL
) ? CFRetain(oldPrivate
->location
) : NULL
;
2547 newPrivate
->modemCCL
= (oldPrivate
->modemCCL
!= NULL
) ? CFRetain(oldPrivate
->modemCCL
) : NULL
;
2548 newPrivate
->modemIsV92
= oldPrivate
->modemIsV92
;
2549 newPrivate
->supportsBond
= oldPrivate
->supportsBond
;
2550 newPrivate
->supportsVLAN
= oldPrivate
->supportsVLAN
;
2551 newPrivate
->sort_order
= oldPrivate
->sort_order
;
2557 __private_extern__ CFArrayRef
2558 __SCNetworkInterfaceCopyDeepConfiguration(SCNetworkInterfaceRef interface
)
2560 CFDictionaryRef config
;
2561 CFMutableArrayRef configs
;
2563 configs
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
2565 while (interface
!= NULL
) {
2566 config
= __SCNetworkInterfaceGetConfiguration(interface
, TRUE
);
2567 CFArrayAppendValue(configs
,
2568 (config
!= NULL
) ? config
: (CFDictionaryRef
)kCFNull
);
2569 interface
= SCNetworkInterfaceGetInterface(interface
);
2576 __private_extern__
void
2577 __SCNetworkInterfaceSetDeepConfiguration(SCNetworkInterfaceRef interface
, CFArrayRef configs
)
2581 for (i
= 0; interface
!= NULL
; i
++) {
2582 CFDictionaryRef config
;
2584 config
= (configs
!= NULL
) ? CFArrayGetValueAtIndex(configs
, i
) : NULL
;
2585 if (!isA_CFDictionary(config
) || (CFDictionaryGetCount(config
) == 0)) {
2589 (void) __SCNetworkInterfaceSetConfiguration(interface
, config
, TRUE
);
2590 interface
= SCNetworkInterfaceGetInterface(interface
);