2 * Copyright (c) 2004 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"
62 #include <mach/mach.h>
64 #include <net/if_types.h>
68 static CFStringRef
__SCNetworkInterfaceCopyDescription (CFTypeRef cf
);
69 static void __SCNetworkInterfaceDeallocate (CFTypeRef cf
);
70 static Boolean
__SCNetworkInterfaceEqual (CFTypeRef cf1
, CFTypeRef cf2
);
90 const CFStringRef kSCNetworkInterfaceType6to4
= CFSTR("6to4");
91 const CFStringRef kSCNetworkInterfaceTypeBluetooth
= CFSTR("Bluetooth");
92 const CFStringRef kSCNetworkInterfaceTypeBond
= CFSTR("Bond");
93 const CFStringRef kSCNetworkInterfaceTypeEthernet
= CFSTR("Ethernet");
94 const CFStringRef kSCNetworkInterfaceTypeFireWire
= CFSTR("FireWire");
95 const CFStringRef kSCNetworkInterfaceTypeIEEE80211
= CFSTR("IEEE80211"); // IEEE 802.11, AirPort
96 const CFStringRef kSCNetworkInterfaceTypeIrDA
= CFSTR("IrDA");
97 const CFStringRef kSCNetworkInterfaceTypeL2TP
= CFSTR("L2TP");
98 const CFStringRef kSCNetworkInterfaceTypeModem
= CFSTR("Modem");
99 const CFStringRef kSCNetworkInterfaceTypePPP
= CFSTR("PPP");
100 const CFStringRef kSCNetworkInterfaceTypePPTP
= CFSTR("PPTP");
101 const CFStringRef kSCNetworkInterfaceTypeSerial
= CFSTR("Serial");
102 const CFStringRef kSCNetworkInterfaceTypeVLAN
= CFSTR("VLAN");
104 const CFStringRef kSCNetworkInterfaceTypeIPv4
= CFSTR("IPv4");
106 static SCNetworkInterfacePrivate __kSCNetworkInterfaceIPv4
= {
107 INIT_CFRUNTIME_BASE(NULL
, 0, 0x0080), // cfBase
108 NULL
, // interface type
109 NULL
, // localized name
110 NULL
, // localization key
111 NULL
, // localization arg1
112 NULL
, // localization arg2
113 NULL
, // [layered] interface
116 NULL
, // entity_device
117 NULL
, // entity_hardware
119 NULL
, // entity_subtype
120 NULL
, // supported_interface_types
121 NULL
, // supported_protocol_types
126 FALSE
, // supportsDeviceOnHold
127 FALSE
, // supportsBond
128 FALSE
, // supportsVLAN
129 kSortUnknown
// sort_order
132 const SCNetworkInterfaceRef kSCNetworkInterfaceIPv4
= (SCNetworkInterfaceRef
)&__kSCNetworkInterfaceIPv4
;
141 #define doAppleTalk 1<<0
145 #define doProxies 1<<4
147 static const struct {
148 const CFStringRef
*interface_type
;
149 Boolean per_interface_config
;
150 uint32_t supported_interfaces
;
151 const CFStringRef
*ppp_subtype
;
152 uint32_t supported_protocols
;
153 } configurations
[] = {
154 // interface type if config? interface types PPP sub-type interface protocols
155 // ===================================== ========== ======================= ======================================= =========================================
156 { &kSCNetworkInterfaceType6to4
, FALSE
, doNone
, NULL
, doIPv6
},
157 { &kSCNetworkInterfaceTypeBluetooth
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypePPPSerial
, doNone
},
158 { &kSCNetworkInterfaceTypeBond
, TRUE
, doNone
, NULL
, doAppleTalk
|doDNS
|doIPv4
|doIPv6
|doProxies
},
159 { &kSCNetworkInterfaceTypeEthernet
, TRUE
, doPPP
, &kSCValNetInterfaceSubTypePPPoE
, doAppleTalk
|doDNS
|doIPv4
|doIPv6
|doProxies
},
160 { &kSCNetworkInterfaceTypeFireWire
, TRUE
, doNone
, NULL
, doDNS
|doIPv4
|doIPv6
|doProxies
},
161 { &kSCNetworkInterfaceTypeIEEE80211
, TRUE
, doPPP
, &kSCValNetInterfaceSubTypePPPoE
, doAppleTalk
|doDNS
|doIPv4
|doIPv6
|doProxies
},
162 { &kSCNetworkInterfaceTypeIrDA
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypePPPSerial
, doNone
},
163 { &kSCNetworkInterfaceTypeL2TP
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypeL2TP
, doNone
},
164 { &kSCNetworkInterfaceTypeModem
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypePPPSerial
, doNone
},
165 { &kSCNetworkInterfaceTypePPP
, FALSE
, doNone
, NULL
, doDNS
|doIPv4
|doIPv6
|doProxies
},
166 { &kSCNetworkInterfaceTypePPTP
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypePPTP
, doNone
},
167 { &kSCNetworkInterfaceTypeSerial
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypePPPSerial
, doNone
},
168 { &kSCNetworkInterfaceTypeVLAN
, TRUE
, doNone
, NULL
, doAppleTalk
|doDNS
|doIPv4
|doIPv6
|doProxies
},
169 // ===================================== ========== ======================= ======================================= =========================================
170 { &kSCNetworkInterfaceTypeIPv4
, FALSE
, do6to4
|doPPTP
|doL2TP
, NULL
, doNone
}
174 #define SYSTEMCONFIGURATION_BUNDLE_ID CFSTR("com.apple.SystemConfiguration")
175 #define NETWORKINTERFACE_LOCALIZATIONS CFSTR("NetworkInterface")
176 static CFBundleRef bundle
= NULL
;
179 static CFTypeID __kSCNetworkInterfaceTypeID
= _kCFRuntimeNotATypeID
;
182 static const CFRuntimeClass __SCNetworkInterfaceClass
= {
184 "SCNetworkInterface", // className
187 __SCNetworkInterfaceDeallocate
, // dealloc
188 __SCNetworkInterfaceEqual
, // equal
190 NULL
, // copyFormattingDesc
191 __SCNetworkInterfaceCopyDescription
// copyDebugDesc
195 static pthread_once_t initialized
= PTHREAD_ONCE_INIT
;
198 static __inline__ CFTypeRef
199 isA_SCNetworkInterface(CFTypeRef obj
)
201 return (isA_CFType(obj
, SCNetworkInterfaceGetTypeID()));
206 __SCNetworkInterfaceCopyDescription(CFTypeRef cf
)
208 CFAllocatorRef allocator
= CFGetAllocator(cf
);
209 CFMutableStringRef result
;
210 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)cf
;
212 result
= CFStringCreateMutable(allocator
, 0);
213 CFStringAppendFormat(result
, NULL
, CFSTR("<SCNetworkInterface %p [%p]> { "), cf
, allocator
);
214 CFStringAppendFormat(result
, NULL
, CFSTR("type = %@"), interfacePrivate
->interface_type
);
215 CFStringAppendFormat(result
, NULL
, CFSTR(", entity = %@ / %@ / %@"),
216 interfacePrivate
->entity_device
,
217 interfacePrivate
->entity_hardware
,
218 interfacePrivate
->entity_type
);
219 if (interfacePrivate
->entity_subtype
!= NULL
) {
220 CFStringAppendFormat(result
, NULL
, CFSTR(" / %@"), interfacePrivate
->entity_subtype
);
222 if (interfacePrivate
->localized_name
!= NULL
) {
223 CFStringAppendFormat(result
, NULL
, CFSTR(", name = %@"), interfacePrivate
->localized_name
);
225 if (interfacePrivate
->localized_key
!= NULL
) {
226 CFStringAppendFormat(result
, NULL
, CFSTR(", name = \"%@\""), interfacePrivate
->localized_key
);
227 if (interfacePrivate
->localized_arg1
!= NULL
) {
228 CFStringAppendFormat(result
, NULL
, CFSTR("+\"%@\""), interfacePrivate
->localized_arg1
);
230 if (interfacePrivate
->localized_arg2
!= NULL
) {
231 CFStringAppendFormat(result
, NULL
, CFSTR("+\"%@\""), interfacePrivate
->localized_arg2
);
235 if (interfacePrivate
->address
!= NULL
) {
236 CFStringAppendFormat(result
, NULL
, CFSTR(", address = %@"), interfacePrivate
->address
);
238 CFStringAppendFormat(result
, NULL
, CFSTR(", builtin = %s"), interfacePrivate
->builtin
? "TRUE" : "FALSE");
239 if (interfacePrivate
->location
!= NULL
) {
240 CFStringAppendFormat(result
, NULL
, CFSTR(", location = %@"), interfacePrivate
->location
);
242 CFStringAppendFormat(result
, NULL
, CFSTR(", path = %@"), interfacePrivate
->path
);
243 CFStringAppendFormat(result
, NULL
, CFSTR(", order = %d"), interfacePrivate
->sort_order
);
245 if (interfacePrivate
->service
!= NULL
) {
246 CFStringAppendFormat(result
, NULL
, CFSTR(", service=%@"), interfacePrivate
->service
);
249 if (interfacePrivate
->interface
!= NULL
) {
250 CFStringAppendFormat(result
, NULL
, CFSTR(", interface=%@"), interfacePrivate
->interface
);
253 if (interfacePrivate
->unsaved
!= NULL
) {
254 CFStringAppendFormat(result
, NULL
, CFSTR(", unsaved=%@"), interfacePrivate
->unsaved
);
256 CFStringAppendFormat(result
, NULL
, CFSTR(" }"));
263 __SCNetworkInterfaceDeallocate(CFTypeRef cf
)
265 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)cf
;
267 /* release resources */
269 if (interfacePrivate
->interface
!= NULL
)
270 CFRelease(interfacePrivate
->interface
);
272 if (interfacePrivate
->localized_name
!= NULL
)
273 CFRelease(interfacePrivate
->localized_name
);
275 if (interfacePrivate
->localized_arg1
!= NULL
)
276 CFRelease(interfacePrivate
->localized_arg1
);
278 if (interfacePrivate
->localized_arg2
!= NULL
)
279 CFRelease(interfacePrivate
->localized_arg2
);
281 if (interfacePrivate
->unsaved
!= NULL
)
282 CFRelease(interfacePrivate
->unsaved
);
284 if (interfacePrivate
->entity_device
!= NULL
)
285 CFRelease(interfacePrivate
->entity_device
);
287 if (interfacePrivate
->supported_interface_types
!= NULL
)
288 CFRelease(interfacePrivate
->supported_interface_types
);
290 if (interfacePrivate
->supported_protocol_types
!= NULL
)
291 CFRelease(interfacePrivate
->supported_protocol_types
);
293 if (interfacePrivate
->address
!= NULL
)
294 CFRelease(interfacePrivate
->address
);
296 if (interfacePrivate
->location
!= NULL
)
297 CFRelease(interfacePrivate
->location
);
299 if (interfacePrivate
->path
!= NULL
)
300 CFRelease(interfacePrivate
->path
);
307 __SCNetworkInterfaceEqual(CFTypeRef cf1
, CFTypeRef cf2
)
309 SCNetworkInterfacePrivateRef if1
= (SCNetworkInterfacePrivateRef
)cf1
;
310 SCNetworkInterfacePrivateRef if2
= (SCNetworkInterfacePrivateRef
)cf2
;
315 if (!CFEqual(if1
->interface_type
, if2
->interface_type
)) {
316 return FALSE
; // if not the same interface type
319 if (if1
->entity_device
!= if2
->entity_device
) {
320 if ((if1
->entity_device
!= NULL
) && (if2
->entity_device
!= NULL
)) {
321 if (!CFEqual(if1
->entity_device
, if2
->entity_device
)) {
322 return FALSE
; // if not the same device
325 return FALSE
; // if only one interface has a device
334 __SCNetworkInterfaceInitialize(void)
337 __kSCNetworkInterfaceTypeID
= _CFRuntimeRegisterClass(&__SCNetworkInterfaceClass
);
339 // initialize __kSCNetworkInterfaceIPv4
340 _CFRuntimeSetInstanceTypeID(&__kSCNetworkInterfaceIPv4
, __kSCNetworkInterfaceTypeID
);
341 __kSCNetworkInterfaceIPv4
.interface_type
= kSCNetworkInterfaceTypeIPv4
;
342 __kSCNetworkInterfaceIPv4
.localized_key
= CFSTR("ipv4");
344 // get CFBundleRef for SystemConfiguration.framework
345 bundle
= CFBundleGetBundleWithIdentifier(SYSTEMCONFIGURATION_BUNDLE_ID
);
346 if (bundle
== NULL
) {
350 url
= CFURLCreateWithFileSystemPath(NULL
,
351 CFSTR("/System/Library/Frameworks/SystemConfiguration.framework"),
352 kCFURLPOSIXPathStyle
,
354 bundle
= CFBundleCreate(NULL
, url
);
362 __private_extern__ SCNetworkInterfacePrivateRef
363 __SCNetworkInterfaceCreatePrivate(CFAllocatorRef allocator
,
364 SCNetworkInterfaceRef interface
,
365 SCNetworkServiceRef service
,
368 SCNetworkInterfacePrivateRef interfacePrivate
;
371 /* initialize runtime */
372 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
374 /* allocate target */
375 size
= sizeof(SCNetworkInterfacePrivate
) - sizeof(CFRuntimeBase
);
376 interfacePrivate
= (SCNetworkInterfacePrivateRef
)_CFRuntimeCreateInstance(allocator
,
377 __kSCNetworkInterfaceTypeID
,
380 if (interfacePrivate
== NULL
) {
384 interfacePrivate
->interface_type
= NULL
;
385 interfacePrivate
->localized_name
= NULL
;
386 interfacePrivate
->localized_key
= NULL
;
387 interfacePrivate
->localized_arg1
= NULL
;
388 interfacePrivate
->localized_arg2
= NULL
;
389 interfacePrivate
->interface
= (interface
!= NULL
) ? CFRetain(interface
) : NULL
;
390 interfacePrivate
->service
= service
;
391 interfacePrivate
->unsaved
= NULL
;
392 interfacePrivate
->entity_device
= NULL
;
393 interfacePrivate
->entity_hardware
= NULL
;
394 interfacePrivate
->entity_type
= NULL
;
395 interfacePrivate
->entity_subtype
= NULL
;
396 interfacePrivate
->supported_interface_types
= NULL
;
397 interfacePrivate
->supported_protocol_types
= NULL
;
398 interfacePrivate
->address
= NULL
;
399 interfacePrivate
->builtin
= FALSE
;
400 interfacePrivate
->path
= (path
!= NULL
) ? CFStringCreateWithCString(NULL
, path
, kCFStringEncodingUTF8
)
402 interfacePrivate
->location
= NULL
;
403 interfacePrivate
->supportsDeviceOnHold
= FALSE
;
404 interfacePrivate
->supportsBond
= FALSE
;
405 interfacePrivate
->supportsVLAN
= FALSE
;
406 interfacePrivate
->sort_order
= kSortUnknown
;
408 return interfacePrivate
;
412 /* ---------- ordering ---------- */
416 split_path(CFStringRef path
)
418 CFArrayRef components
;
419 CFMutableStringRef nPath
;
421 // turn '@'s into '/'s
422 nPath
= CFStringCreateMutableCopy(NULL
, 0, path
);
423 (void) CFStringFindAndReplace(nPath
,
426 CFRangeMake(0, CFStringGetLength(nPath
)),
429 // split path into components to be compared
430 components
= CFStringCreateArrayBySeparatingStrings(NULL
, nPath
, CFSTR("/"));
437 static CFComparisonResult
438 compare_interfaces(const void *val1
, const void *val2
, void *context
)
440 SCNetworkInterfacePrivateRef dev1
= (SCNetworkInterfacePrivateRef
)val1
;
441 SCNetworkInterfacePrivateRef dev2
= (SCNetworkInterfacePrivateRef
)val2
;
442 CFComparisonResult res
= kCFCompareEqualTo
;
444 /* sort by interface type */
445 if (dev1
->sort_order
!= dev2
->sort_order
) {
446 if (dev1
->sort_order
< dev2
->sort_order
) {
447 res
= kCFCompareLessThan
;
449 res
= kCFCompareGreaterThan
;
454 /* built-in interfaces sort first */
455 if (dev1
->builtin
!= dev2
->builtin
) {
457 res
= kCFCompareLessThan
;
459 res
= kCFCompareGreaterThan
;
464 /* ... and then, sort built-in interfaces by "location" */
466 if (dev1
->location
!= dev2
->location
) {
467 if (isA_CFString(dev1
->location
)) {
468 if (isA_CFString(dev2
->location
)) {
469 res
= CFStringCompare(dev1
->location
, dev2
->location
, 0);
471 res
= kCFCompareLessThan
;
474 res
= kCFCompareGreaterThan
;
477 if (res
!= kCFCompareEqualTo
) {
483 /* ... and, then sort by IOPathMatch */
484 if ((dev1
->path
!= NULL
) && (dev2
->path
!= NULL
)) {
485 CFArrayRef elements1
;
486 CFArrayRef elements2
;
492 elements1
= split_path(dev1
->path
);
493 n1
= CFArrayGetCount(elements1
);
495 elements2
= split_path(dev2
->path
);
496 n2
= CFArrayGetCount(elements2
);
498 n
= (n1
<= n2
) ? n1
: n2
;
499 for (i
= 0; i
< n
; i
++) {
508 e1
= CFArrayGetValueAtIndex(elements1
, i
);
509 e2
= CFArrayGetValueAtIndex(elements2
, i
);
511 str
= _SC_cfstring_to_cstring(e1
, NULL
, 0, kCFStringEncodingUTF8
);
513 q1
= strtoq(str
, &end
, 16);
514 isNum
= ((*str
!= '\0') && (*end
== '\0') && (errno
== 0));
515 CFAllocatorDeallocate(NULL
, str
);
518 // if e1 is a valid numeric string
519 str
= _SC_cfstring_to_cstring(e2
, NULL
, 0, kCFStringEncodingUTF8
);
521 q2
= strtoq(str
, &end
, 16);
522 isNum
= ((*str
!= '\0') && (*end
== '\0') && (errno
== 0));
523 CFAllocatorDeallocate(NULL
, str
);
526 // if e2 is also a valid numeric string
529 res
= kCFCompareEqualTo
;
531 } else if (q1
< q2
) {
532 res
= kCFCompareLessThan
;
534 res
= kCFCompareGreaterThan
;
540 res
= CFStringCompare(e1
, e2
, 0);
541 if (res
!= kCFCompareEqualTo
) {
546 if (res
== kCFCompareEqualTo
) {
548 res
= kCFCompareLessThan
;
549 } else if (n1
< n2
) {
550 res
= kCFCompareGreaterThan
;
554 CFRelease(elements1
);
555 CFRelease(elements2
);
557 if (res
!= kCFCompareEqualTo
) {
562 /* ... and lastly, sort by BSD interface name */
563 if ((dev1
->entity_device
!= NULL
) && (dev2
->entity_device
!= NULL
)) {
564 res
= CFStringCompare(dev1
->entity_device
, dev2
->entity_device
, 0);
572 sort_interfaces(CFMutableArrayRef all_interfaces
)
574 int n
= CFArrayGetCount(all_interfaces
);
580 CFArraySortValues(all_interfaces
, CFRangeMake(0, n
), compare_interfaces
, NULL
);
585 /* ---------- interface details ---------- */
589 IOCopyCFStringValue(CFTypeRef ioVal
)
591 if (isA_CFString(ioVal
)) {
592 return CFStringCreateCopy(NULL
, ioVal
);
595 if (isA_CFData(ioVal
)) {
596 return CFStringCreateWithCString(NULL
, CFDataGetBytePtr(ioVal
), kCFStringEncodingUTF8
);
604 IODictionaryCopyCFStringValue(CFDictionaryRef io_dict
, CFStringRef io_key
)
608 ioVal
= CFDictionaryGetValue(io_dict
, io_key
);
609 return IOCopyCFStringValue(ioVal
);
614 IOStringValueHasPrefix(CFTypeRef ioVal
, CFStringRef prefix
)
616 Boolean match
= FALSE
;
617 CFIndex prefixLen
= CFStringGetLength(prefix
);
618 CFStringRef str
= ioVal
;
620 if (!isA_CFString(ioVal
)) {
621 if (isA_CFData(ioVal
)) {
622 str
= CFStringCreateWithCStringNoCopy(NULL
,
623 (const char *)CFDataGetBytePtr(ioVal
),
624 kCFStringEncodingUTF8
,
632 (CFStringGetLength(str
) >= prefixLen
) &&
633 (CFStringCompareWithOptions(str
,
635 CFRangeMake(0, prefixLen
),
636 kCFCompareCaseInsensitive
) == kCFCompareEqualTo
)) {
640 if (str
!= ioVal
) CFRelease(str
);
646 copyMACAddress(CFDictionaryRef controller_dict
)
648 CFStringRef address
= NULL
;
653 char mac
[sizeof("xx:xx:xx:xx:xx:xx:xx:xx")];
656 data
= CFDictionaryGetValue(controller_dict
, CFSTR(kIOMACAddress
));
661 bp
= (uint8_t *)CFDataGetBytePtr(data
);
662 n
= CFDataGetLength(data
) * 3;
664 if (n
> sizeof(mac
)) {
665 mac_p
= CFAllocatorAllocate(NULL
, 0, n
);
668 for (cp
= mac_p
; n
> 0; n
-= 3) {
669 cp
+= snprintf(cp
, n
, "%2.2x:", *bp
++);
672 address
= CFStringCreateWithCString(NULL
, mac_p
, kCFStringEncodingUTF8
);
673 if (mac_p
!= mac
) CFAllocatorDeallocate(NULL
, mac_p
);
678 static const struct {
679 const CFStringRef name
;
680 const CFStringRef slot
;
681 } slot_mappings
[] = {
683 { CFSTR("A1") , CFSTR("1") },
684 { CFSTR("B1") , CFSTR("2") },
685 { CFSTR("C1") , CFSTR("3") },
687 // Blue&White G3, Yikes G4
688 { CFSTR("J12"), CFSTR("1") },
689 { CFSTR("J11"), CFSTR("2") },
690 { CFSTR("J10"), CFSTR("3") },
691 { CFSTR("J9"), CFSTR("4") },
694 { CFSTR("A") , CFSTR("1") },
695 { CFSTR("B") , CFSTR("2") },
696 { CFSTR("C") , CFSTR("3") },
697 { CFSTR("D") , CFSTR("4") },
699 // Digital Audio G4 (and later models)
700 { CFSTR("1") , CFSTR("1") },
701 { CFSTR("2") , CFSTR("2") },
702 { CFSTR("3") , CFSTR("3") },
703 { CFSTR("4") , CFSTR("4") },
704 { CFSTR("5") , CFSTR("5") }
709 pci_slot(io_registry_entry_t interface
, CFTypeRef
*pci_slot_name
)
712 io_registry_entry_t slot
= interface
;
714 if (pci_slot_name
!= NULL
) *pci_slot_name
= NULL
;
716 while (slot
!= MACH_PORT_NULL
) {
717 io_registry_entry_t parent
;
720 slot_name
= IORegistryEntryCreateCFProperty(slot
, CFSTR("AAPL,slot-name"), NULL
, 0);
721 if (slot_name
!= NULL
) {
724 found
= IOStringValueHasPrefix(slot_name
, CFSTR("slot"));
727 CFMutableStringRef name
;
729 // if we found a slot #
730 name
= CFStringCreateMutable(NULL
, 0);
731 if (isA_CFString(slot_name
)) {
732 if (pci_slot_name
!= NULL
) *pci_slot_name
= CFStringCreateCopy(NULL
, slot_name
);
733 CFStringAppend(name
, slot_name
);
734 } else if (isA_CFData(slot_name
)) {
735 if (pci_slot_name
!= NULL
) *pci_slot_name
= CFDataCreateCopy(NULL
, slot_name
);
736 CFStringAppendCString(name
, CFDataGetBytePtr(slot_name
), kCFStringEncodingUTF8
);
739 (void) CFStringFindAndReplace(name
,
743 kCFCompareCaseInsensitive
|kCFCompareAnchored
);
744 for (i
= 0; i
< sizeof(slot_mappings
)/sizeof(slot_mappings
[0]); i
++) {
745 if (CFStringCompareWithOptions(name
,
746 slot_mappings
[i
].name
,
747 CFRangeMake(0, CFStringGetLength(slot_mappings
[i
].name
)),
748 kCFCompareCaseInsensitive
) == kCFCompareEqualTo
) {
750 name
= (CFMutableStringRef
)CFRetain(slot_mappings
[i
].slot
);
755 CFRelease(slot_name
);
756 if (slot
!= interface
) IOObjectRelease(slot
);
760 CFRelease(slot_name
);
763 kr
= IORegistryEntryGetParentEntry(slot
, kIOServicePlane
, &parent
);
764 if (slot
!= interface
) IOObjectRelease(slot
);
766 case kIOReturnSuccess
:
769 case kIOReturnNoDevice
:
770 // if we have hit the root node without finding a slot #
773 SCLog(TRUE
, LOG_INFO
, CFSTR("pci_slot IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr
);
784 static CFComparisonResult
785 compare_bsdNames(const void *val1
, const void *val2
, void *context
)
787 CFStringRef bsd1
= (CFStringRef
)val1
;
788 CFStringRef bsd2
= (CFStringRef
)val2
;
790 return CFStringCompare(bsd1
, bsd2
, 0);
795 pci_port(mach_port_t masterPort
, CFTypeRef slot_name
, CFStringRef bsdName
)
798 CFStringRef port_name
= NULL
;
799 CFMutableArrayRef port_names
;
802 CFStringRef match_keys
[2];
803 CFTypeRef match_vals
[2];
804 CFDictionaryRef match_dict
;
805 CFDictionaryRef matching
;
806 io_registry_entry_t slot
;
807 io_iterator_t slot_iterator
= MACH_PORT_NULL
;
809 match_keys
[0] = CFSTR("AAPL,slot-name");
810 match_vals
[0] = slot_name
;
812 match_dict
= CFDictionaryCreate(NULL
,
813 (const void **)match_keys
,
814 (const void **)match_vals
,
816 &kCFTypeDictionaryKeyCallBacks
,
817 &kCFTypeDictionaryValueCallBacks
);
819 match_keys
[0] = CFSTR(kIOProviderClassKey
);
820 match_vals
[0] = CFSTR("IOPCIDevice");
822 match_keys
[1] = CFSTR(kIOPropertyMatchKey
);
823 match_vals
[1] = match_dict
;
825 // note: the "matching" dictionary will be consumed by the following
826 matching
= CFDictionaryCreate(NULL
,
827 (const void **)match_keys
,
828 (const void **)match_vals
,
829 sizeof(match_keys
)/sizeof(match_keys
[0]),
830 &kCFTypeDictionaryKeyCallBacks
,
831 &kCFTypeDictionaryValueCallBacks
);
832 CFRelease(match_dict
);
834 kr
= IOServiceGetMatchingServices(masterPort
, matching
, &slot_iterator
);
835 if (kr
!= kIOReturnSuccess
) {
836 SCPrint(TRUE
, stderr
, CFSTR("IOServiceGetMatchingServices() failed, kr = 0x%x\n"), kr
);
837 return MACH_PORT_NULL
;
840 port_names
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
842 while ((slot
= IOIteratorNext(slot_iterator
)) != MACH_PORT_NULL
) {
843 io_registry_entry_t child
;
844 io_iterator_t child_iterator
= MACH_PORT_NULL
;
846 kr
= IORegistryEntryCreateIterator(slot
,
848 kIORegistryIterateRecursively
,
850 if (kr
!= kIOReturnSuccess
) {
851 SCPrint(TRUE
, stderr
, CFSTR("IORegistryEntryCreateIterator() failed, kr = 0x%x\n"), kr
);
852 return MACH_PORT_NULL
;
855 while ((child
= IOIteratorNext(child_iterator
)) != MACH_PORT_NULL
) {
856 if (IOObjectConformsTo(child
, kIONetworkInterfaceClass
)) {
857 CFStringRef if_bsdName
;
859 if_bsdName
= IORegistryEntryCreateCFProperty(child
,
860 CFSTR(kIOBSDNameKey
),
863 if (if_bsdName
!= NULL
) {
864 CFArrayAppendValue(port_names
, if_bsdName
);
865 CFRelease(if_bsdName
);
868 IOObjectRelease(child
);
870 IOObjectRelease(child_iterator
);
871 IOObjectRelease(slot
);
873 IOObjectRelease(slot_iterator
);
875 n
= CFArrayGetCount(port_names
);
877 CFArraySortValues(port_names
, CFRangeMake(0, n
), compare_bsdNames
, NULL
);
878 n
= CFArrayGetFirstIndexOfValue(port_names
, CFRangeMake(0, n
), bsdName
);
879 if (n
!= kCFNotFound
) {
880 port_name
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%d"), n
+ 1);
884 CFRelease(port_names
);
890 pci_slot_info(mach_port_t masterPort
, io_registry_entry_t interface
, CFStringRef
*slot_name
, CFStringRef
*port_name
)
892 CFStringRef bsd_name
;
894 CFTypeRef pci_slot_name
;
899 bsd_name
= IORegistryEntryCreateCFProperty(interface
, CFSTR(kIOBSDNameKey
), NULL
, 0);
900 if (bsd_name
== NULL
) {
904 *slot_name
= pci_slot(interface
, &pci_slot_name
);
905 if (*slot_name
!= NULL
) {
906 if (pci_slot_name
!= NULL
) {
907 *port_name
= pci_port(masterPort
, pci_slot_name
, bsd_name
);
908 CFRelease(pci_slot_name
);
919 isBuiltIn(io_registry_entry_t interface
)
922 io_registry_entry_t slot
= interface
;
924 while (slot
!= MACH_PORT_NULL
) {
925 io_registry_entry_t parent
;
928 slot_name
= IORegistryEntryCreateCFProperty(slot
, CFSTR("AAPL,slot-name"), NULL
, 0);
929 if (slot_name
!= NULL
) {
932 found
= IOStringValueHasPrefix(slot_name
, CFSTR("slot"));
933 CFRelease(slot_name
);
936 // if we found a slot # then this is not a built-in interface
937 if (slot
!= interface
) IOObjectRelease(slot
);
942 kr
= IORegistryEntryGetParentEntry(slot
, kIOServicePlane
, &parent
);
943 if (slot
!= interface
) IOObjectRelease(slot
);
945 case kIOReturnSuccess
:
948 case kIOReturnNoDevice
:
949 // if we have hit the root node without finding a slot #
952 SCLog(TRUE
, LOG_INFO
, CFSTR("isBuiltIn IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr
);
961 /* ---------- interface enumeration ---------- */
964 typedef Boolean (*processInterface
)(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
);
975 processNetworkInterface(mach_port_t masterPort
,
976 SCNetworkInterfacePrivateRef interfacePrivate
,
977 io_registry_entry_t interface
,
978 CFDictionaryRef interface_dict
,
979 io_registry_entry_t controller
,
980 CFDictionaryRef controller_dict
,
981 io_registry_entry_t bus
,
982 CFDictionaryRef bus_dict
)
993 // get the interface type
995 num
= CFDictionaryGetValue(interface_dict
, CFSTR(kIOInterfaceType
));
996 if (!isA_CFNumber(num
) ||
997 !CFNumberGetValue(num
, kCFNumberIntType
, &ift
)) {
998 SCPrint(TRUE
, stderr
, CFSTR("Could not get interface type\n"));
1006 if (IOObjectGetClass(interface
, i_IOClass
) != KERN_SUCCESS
) {
1007 i_IOClass
[0] = '\0';
1009 if (IOObjectGetClass(controller
, c_IOClass
) != KERN_SUCCESS
) {
1010 c_IOClass
[0] = '\0';
1012 if (IORegistryEntryGetName(controller
, c_IOName
) != KERN_SUCCESS
) {
1016 if ((strcmp(i_IOClass
, "IO80211Interface" ) == 0) ||
1017 (strcmp(c_IOClass
, "AirPortPCI" ) == 0) ||
1018 (strcmp(c_IOClass
, "AirPortDriver" ) == 0) ||
1019 (strcmp(c_IOName
, "AppleWireless80211") == 0)) {
1020 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeIEEE80211
;
1021 interfacePrivate
->entity_type
= kSCEntNetEthernet
;
1022 interfacePrivate
->entity_hardware
= kSCEntNetAirPort
;
1023 interfacePrivate
->sort_order
= kSortAirPort
;
1025 str
= IODictionaryCopyCFStringValue(bus_dict
, CFSTR("name"));
1026 if ((str
!= NULL
) && CFEqual(str
, CFSTR("radio"))) {
1027 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
; // ??
1028 interfacePrivate
->entity_type
= kSCEntNetEthernet
;
1029 interfacePrivate
->entity_hardware
= kSCEntNetEthernet
; // ??
1030 interfacePrivate
->sort_order
= kSortOtherWireless
;
1032 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
;
1033 interfacePrivate
->entity_type
= kSCEntNetEthernet
;
1034 interfacePrivate
->entity_hardware
= kSCEntNetEthernet
;
1035 interfacePrivate
->sort_order
= kSortEthernet
;
1037 // BOND support only enabled for ethernet devices
1038 interfacePrivate
->supportsBond
= TRUE
;
1041 if (str
!= NULL
) CFRelease(str
);
1045 bVal
= isA_CFBoolean(CFDictionaryGetValue(interface_dict
, CFSTR(kIOBuiltin
)));
1046 if ((bVal
== NULL
) || !CFBooleanGetValue(bVal
)) {
1047 bVal
= isA_CFBoolean(CFDictionaryGetValue(interface_dict
, CFSTR(kIOPrimaryInterface
)));
1050 interfacePrivate
->builtin
= CFBooleanGetValue(bVal
);
1052 interfacePrivate
->builtin
= isBuiltIn(interface
);
1056 interfacePrivate
->location
= IODictionaryCopyCFStringValue(interface_dict
, CFSTR(kIOLocation
));
1059 num
= CFDictionaryGetValue(controller_dict
, CFSTR(kIOFeatures
));
1060 if (isA_CFNumber(num
) &&
1061 CFNumberGetValue(num
, kCFNumberIntType
, & iVal
)) {
1062 if (iVal
& (kIONetworkFeatureHardwareVlan
| kIONetworkFeatureSoftwareVlan
)) {
1063 interfacePrivate
->supportsVLAN
= TRUE
;
1068 if (interfacePrivate
->builtin
) {
1069 if ((interfacePrivate
->location
== NULL
) ||
1070 (CFStringGetLength(interfacePrivate
->location
) == 0)) {
1071 interfacePrivate
->localized_key
= CFSTR("ether");
1073 interfacePrivate
->localized_key
= CFSTR("multiether");
1074 interfacePrivate
->localized_arg1
= CFRetain(interfacePrivate
->location
);
1076 } else if (CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeIEEE80211
)) {
1077 interfacePrivate
->localized_key
= CFSTR("airport");
1078 } else if (interfacePrivate
->sort_order
== kSortOtherWireless
) {
1079 interfacePrivate
->localized_key
= CFSTR("wireless");
1080 interfacePrivate
->localized_arg1
= CFRetain(CFSTR("")); // ??
1082 CFStringRef provider
;
1084 // check provider class
1085 provider
= IORegistryEntrySearchCFProperty(interface
,
1087 CFSTR(kIOProviderClassKey
),
1089 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1090 if (provider
!= NULL
) {
1091 if (CFEqual(provider
, CFSTR("IOPCIDevice"))) {
1092 CFStringRef port_name
;
1093 CFStringRef slot_name
;
1095 if (pci_slot_info(masterPort
, interface
, &slot_name
, &port_name
)) {
1096 if (port_name
== NULL
) {
1097 interfacePrivate
->localized_key
= CFSTR("pci-ether");
1098 interfacePrivate
->localized_arg1
= slot_name
;
1100 interfacePrivate
->localized_key
= CFSTR("pci-multiether");
1101 interfacePrivate
->localized_arg1
= slot_name
;
1102 interfacePrivate
->localized_arg2
= port_name
;
1106 CFRelease(provider
);
1109 if (interfacePrivate
->localized_key
== NULL
) {
1110 // if no provider, not a PCI device, or no slot information
1111 interfacePrivate
->localized_key
= CFSTR("generic-ether");
1112 interfacePrivate
->localized_arg1
= IODictionaryCopyCFStringValue(interface_dict
, CFSTR(kIOBSDNameKey
));
1119 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeFireWire
;
1122 interfacePrivate
->entity_type
= kSCEntNetFireWire
;
1123 interfacePrivate
->entity_hardware
= kSCEntNetFireWire
;
1126 interfacePrivate
->builtin
= isBuiltIn(interface
);
1129 interfacePrivate
->sort_order
= kSortFireWire
;
1132 if (interfacePrivate
->builtin
) {
1133 interfacePrivate
->localized_key
= CFSTR("firewire");
1135 CFStringRef slot_name
;
1137 slot_name
= pci_slot(interface
, NULL
);
1138 if (slot_name
!= NULL
) {
1139 interfacePrivate
->localized_key
= CFSTR("pci-firewire");
1140 interfacePrivate
->localized_arg1
= slot_name
;
1146 SCPrint(TRUE
, stderr
, CFSTR("Unknown interface type = %d\n"), ift
);
1151 interfacePrivate
->entity_device
= IODictionaryCopyCFStringValue(interface_dict
, CFSTR(kIOBSDNameKey
));
1153 // Hardware (MAC) address
1154 interfacePrivate
->address
= copyMACAddress(controller_dict
);
1161 processSerialInterface(mach_port_t masterPort
,
1162 SCNetworkInterfacePrivateRef interfacePrivate
,
1163 io_registry_entry_t interface
,
1164 CFDictionaryRef interface_dict
,
1165 io_registry_entry_t controller
,
1166 CFDictionaryRef controller_dict
,
1167 io_registry_entry_t bus
,
1168 CFDictionaryRef bus_dict
)
1171 Boolean isModem
= FALSE
;
1176 val
= IORegistryEntrySearchCFProperty(interface
,
1178 CFSTR("HiddenPort"),
1180 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1183 return FALSE
; // if this interface should not be exposed
1187 str
= CFDictionaryGetValue(interface_dict
, CFSTR(kIOTTYBaseNameKey
));
1195 * Exclude ports named "irda" because otherwise the IrDA ports on the
1196 * original iMac (rev's A through D) show up as serial ports. Given
1197 * that only the rev A actually had an IrDA port, and Mac OS X doesn't
1198 * even support it, these ports definitely shouldn't be listed.
1200 if (CFStringCompare(str
,
1202 kCFCompareCaseInsensitive
) == kCFCompareEqualTo
) {
1206 if (IOStringValueHasPrefix(str
, CFSTR("irda-ircomm"))) {
1208 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeIrDA
;
1209 interfacePrivate
->sort_order
= kSortIrDA
;
1210 } else if (IOStringValueHasPrefix(str
, CFSTR("bluetooth"))) {
1212 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeBluetooth
;
1213 interfacePrivate
->sort_order
= kSortBluetooth
;
1216 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeModem
;
1218 // DeviceOnHold support
1219 val
= IORegistryEntrySearchCFProperty(interface
,
1221 CFSTR(kIODeviceSupportsHoldKey
),
1223 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1225 uint32_t supportsHold
;
1227 if (isA_CFNumber(val
) &&
1228 CFNumberGetValue(val
, kCFNumberSInt32Type
, &supportsHold
)) {
1229 interfacePrivate
->supportsDeviceOnHold
= (supportsHold
== 1);
1236 interfacePrivate
->entity_type
= kSCEntNetModem
;
1238 // Entity (Hardware)
1239 ift
= CFDictionaryGetValue(interface_dict
, CFSTR(kIOSerialBSDTypeKey
));
1240 if (!isA_CFString(ift
)) {
1244 if (CFEqual(ift
, CFSTR(kIOSerialBSDModemType
))) {
1247 interfacePrivate
->entity_hardware
= kSCEntNetModem
;
1249 if (CFEqual(str
, CFSTR("modem"))) {
1250 interfacePrivate
->builtin
= TRUE
;
1251 interfacePrivate
->sort_order
= kSortInternalModem
;
1252 } else if (CFEqual(str
, CFSTR("usbmodem"))) {
1253 interfacePrivate
->sort_order
= kSortUSBModem
;
1255 interfacePrivate
->sort_order
= kSortModem
;
1257 } else if (CFEqual(ift
, CFSTR(kIOSerialBSDRS232Type
))) {
1259 interfacePrivate
->entity_hardware
= kSCEntNetModem
;
1260 interfacePrivate
->sort_order
= kSortSerialPort
;
1266 interfacePrivate
->entity_device
= IODictionaryCopyCFStringValue(interface_dict
, CFSTR(kIOTTYDeviceKey
));
1269 if (CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeIrDA
)) {
1270 interfacePrivate
->localized_key
= CFSTR("irda");
1271 } else if (CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeBluetooth
)) {
1272 interfacePrivate
->localized_key
= CFSTR("bluetooth");
1274 CFStringRef localized
;
1275 CFMutableStringRef port
;
1277 port
= CFStringCreateMutableCopy(NULL
, 0, str
);
1278 CFStringLowercase(port
, NULL
);
1281 CFStringAppend(port
, CFSTR("-port"));
1284 localized
= CFBundleCopyLocalizedString(bundle
,
1287 NETWORKINTERFACE_LOCALIZATIONS
);
1288 if (localized
!= NULL
) {
1289 if (!CFEqual(port
, localized
)) {
1290 // if localization available
1291 interfacePrivate
->localized_name
= localized
;
1293 // if no localization available, use TTY base name
1294 CFRelease(localized
);
1295 interfacePrivate
->localized_name
= CFStringCreateCopy(NULL
, str
);
1298 interfacePrivate
->localized_name
= CFStringCreateCopy(NULL
, str
);
1301 if (!isModem
|| !CFEqual(str
, CFSTR("modem"))) {
1302 CFStringRef productName
;
1304 // check if a "Product Name" has been provided
1305 val
= IORegistryEntrySearchCFProperty(interface
,
1307 CFSTR(kIOPropertyProductNameKey
),
1309 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1311 productName
= IOCopyCFStringValue(val
);
1314 if (productName
!= NULL
) {
1315 if (CFStringGetLength(productName
) > 0) {
1316 // if we have a [somewhat reasonable?] product name
1317 CFRelease(interfacePrivate
->localized_name
);
1318 interfacePrivate
->localized_name
= CFRetain(productName
);
1320 CFRelease(productName
);
1333 findMatchingInterfaces(mach_port_t masterPort
, CFDictionaryRef matching
, processInterface func
)
1335 CFMutableArrayRef interfaces
;
1336 io_registry_entry_t interface
;
1338 io_iterator_t iterator
= MACH_PORT_NULL
;
1340 kr
= IOServiceGetMatchingServices(masterPort
, matching
, &iterator
);
1341 if (kr
!= kIOReturnSuccess
) {
1342 SCPrint(TRUE
, stderr
, CFSTR("IOServiceGetMatchingServices() failed, kr = 0x%x\n"), kr
);
1346 interfaces
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1348 while ((interface
= IOIteratorNext(iterator
)) != MACH_PORT_NULL
) {
1349 io_registry_entry_t bus
= MACH_PORT_NULL
;
1350 CFMutableDictionaryRef bus_dict
= NULL
;
1351 io_registry_entry_t controller
= MACH_PORT_NULL
;
1352 CFMutableDictionaryRef controller_dict
= NULL
;
1353 SCNetworkInterfacePrivateRef interfacePrivate
= NULL
;
1354 CFMutableDictionaryRef interface_dict
= NULL
;
1357 kr
= IORegistryEntryGetPath(interface
, kIOServicePlane
, path
);
1358 if (kr
!= kIOReturnSuccess
) {
1359 SCPrint(TRUE
, stderr
, CFSTR("IORegistryEntryGetPath() failed, kr = 0x%x"), kr
);
1363 kr
= IORegistryEntryCreateCFProperties(interface
, &interface_dict
, NULL
, kNilOptions
);
1364 if (kr
!= kIOReturnSuccess
) {
1365 SCPrint(TRUE
, stderr
, CFSTR("IORegistryEntryCreateCFProperties() failed, kr = 0x%x\n"), kr
);
1369 /* get the controller node */
1370 kr
= IORegistryEntryGetParentEntry(interface
, kIOServicePlane
, &controller
);
1371 if (kr
!= KERN_SUCCESS
) {
1372 SCLog(TRUE
, LOG_INFO
, CFSTR("findMatchingInterfaces IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr
);
1376 /* get the dictionary associated with the node */
1377 kr
= IORegistryEntryCreateCFProperties(controller
, &controller_dict
, NULL
, kNilOptions
);
1378 if (kr
!= KERN_SUCCESS
) {
1379 SCLog(TRUE
, LOG_INFO
, CFSTR("findMatchingInterfaces IORegistryEntryCreateCFProperties() failed, kr = 0x%x"), kr
);
1383 /* get the bus node */
1384 kr
= IORegistryEntryGetParentEntry(controller
, kIOServicePlane
, &bus
);
1385 if (kr
!= KERN_SUCCESS
) {
1386 SCLog(TRUE
, LOG_INFO
, CFSTR("findMatchingInterfaces IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr
);
1390 /* get the dictionary associated with the node */
1391 kr
= IORegistryEntryCreateCFProperties(bus
, &bus_dict
, NULL
, kNilOptions
);
1392 if (kr
!= KERN_SUCCESS
) {
1393 SCLog(TRUE
, LOG_INFO
, CFSTR("findMatchingInterfaces IORegistryEntryCreateCFProperties() failed, kr = 0x%x"), kr
);
1397 interfacePrivate
= __SCNetworkInterfaceCreatePrivate(NULL
, NULL
, NULL
, path
);
1399 if ((*func
)(masterPort
, interfacePrivate
, interface
, interface_dict
, controller
, controller_dict
, bus
, bus_dict
)) {
1400 CFArrayAppendValue(interfaces
, (SCNetworkInterfaceRef
)interfacePrivate
);
1403 CFRelease(interfacePrivate
);
1407 if (interface
!= MACH_PORT_NULL
) IOObjectRelease(interface
);
1408 if (interface_dict
!= NULL
) CFRelease(interface_dict
);
1410 if (controller
!= MACH_PORT_NULL
) IOObjectRelease(controller
);
1411 if (controller_dict
!= NULL
) CFRelease(controller_dict
);
1413 if (bus
!= MACH_PORT_NULL
) IOObjectRelease(bus
);
1414 if (bus_dict
!= NULL
) CFRelease(bus_dict
);
1417 IOObjectRelease(iterator
);
1423 /* ---------- Bond configuration ---------- */
1426 SCNetworkInterfaceSupportsBonding(SCNetworkInterfaceRef interface
)
1428 return ((SCNetworkInterfacePrivateRef
)interface
)->supportsBond
;
1432 SCNetworkInterfaceRef
1433 SCNetworkInterfaceCreateWithBond(BondInterfaceRef bond
)
1435 SCNetworkInterfacePrivateRef interfacePrivate
;
1436 CFStringRef bond_if
;
1438 bond_if
= BondInterfaceGetInterface(bond
);
1439 if (bond_if
== NULL
) {
1443 interfacePrivate
= __SCNetworkInterfaceCreatePrivate(NULL
, NULL
, NULL
, NULL
);
1444 if (interfacePrivate
== NULL
) {
1448 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeBond
;
1449 interfacePrivate
->entity_type
= kSCEntNetEthernet
;
1450 interfacePrivate
->entity_hardware
= kSCEntNetEthernet
;
1451 interfacePrivate
->entity_device
= CFStringCreateCopy(NULL
, bond_if
);
1452 interfacePrivate
->builtin
= TRUE
;
1453 interfacePrivate
->sort_order
= kSortBond
;
1455 interfacePrivate
->localized_key
= CFSTR("bond");
1456 interfacePrivate
->localized_arg1
= CFRetain(interfacePrivate
->entity_device
);
1458 return (SCNetworkInterfaceRef
)interfacePrivate
;
1463 findBondInterfaces(CFStringRef match
)
1465 CFMutableArrayRef interfaces
= NULL
;
1468 BondPreferencesRef prefs
;
1469 CFArrayRef bonds
= NULL
;
1471 prefs
= BondPreferencesCreate(NULL
);
1472 if (prefs
== NULL
) {
1477 bonds
= BondPreferencesCopyInterfaces(prefs
);
1478 if (bonds
== NULL
) {
1483 n
= CFArrayGetCount(bonds
);
1489 interfaces
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1491 for (i
= 0; i
< n
; i
++) {
1492 SCNetworkInterfaceRef interface
;
1493 BondInterfaceRef bond
= CFArrayGetValueAtIndex(bonds
, i
);
1494 CFStringRef bond_if
;
1496 bond_if
= BondInterfaceGetInterface(bond
);
1497 if (bond_if
== NULL
) {
1501 if ((match
!= NULL
) && !CFEqual(bond_if
, match
)) {
1505 interface
= SCNetworkInterfaceCreateWithBond(bond
);
1506 CFArrayAppendValue(interfaces
, interface
);
1507 CFRelease(interface
);
1512 if (bonds
!= NULL
) CFRelease(bonds
);
1518 /* ---------- VLAN configuration ---------- */
1520 SCNetworkInterfaceRef
1521 SCNetworkInterfaceCreateWithVLAN(VLANInterfaceRef vlan
)
1523 SCNetworkInterfacePrivateRef interfacePrivate
;
1524 CFStringRef vlan_if
;
1526 vlan_if
= VLANInterfaceGetInterface(vlan
);
1527 if (vlan_if
== NULL
) {
1531 interfacePrivate
= __SCNetworkInterfaceCreatePrivate(NULL
, NULL
, NULL
, NULL
);
1532 if (interfacePrivate
== NULL
) {
1536 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeVLAN
;
1537 interfacePrivate
->entity_type
= kSCEntNetEthernet
;
1538 interfacePrivate
->entity_hardware
= kSCEntNetEthernet
;
1539 interfacePrivate
->entity_device
= CFStringCreateCopy(NULL
, vlan_if
);
1540 interfacePrivate
->builtin
= TRUE
;
1541 interfacePrivate
->sort_order
= kSortVLAN
;
1543 interfacePrivate
->localized_key
= CFSTR("vlan");
1544 interfacePrivate
->localized_arg1
= CFRetain(interfacePrivate
->entity_device
);
1546 return (SCNetworkInterfaceRef
)interfacePrivate
;
1551 findVLANInterfaces(CFStringRef match
)
1553 CFMutableArrayRef interfaces
= NULL
;
1556 VLANPreferencesRef prefs
;
1557 CFArrayRef vlans
= NULL
;
1559 prefs
= VLANPreferencesCreate(NULL
);
1560 if (prefs
== NULL
) {
1565 vlans
= VLANPreferencesCopyInterfaces(prefs
);
1566 if (vlans
== NULL
) {
1571 n
= CFArrayGetCount(vlans
);
1577 interfaces
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1579 for (i
= 0; i
< n
; i
++) {
1580 SCNetworkInterfaceRef interface
;
1581 VLANInterfaceRef vlan
= CFArrayGetValueAtIndex(vlans
, i
);
1582 CFStringRef vlan_if
;
1584 vlan_if
= VLANInterfaceGetInterface(vlan
);
1585 if (vlan_if
== NULL
) {
1589 if ((match
!= NULL
) && !CFEqual(vlan_if
, match
)) {
1593 interface
= SCNetworkInterfaceCreateWithVLAN(vlan
);
1594 CFArrayAppendValue(interfaces
, interface
);
1595 CFRelease(interface
);
1600 if (vlans
!= NULL
) CFRelease(vlans
);
1606 /* ---------- interface from preferences ---------- */
1609 __private_extern__ SCNetworkInterfaceRef
1610 __SCNetworkInterfaceCreateWithEntity(CFAllocatorRef allocator
,
1611 CFDictionaryRef interface_entity
,
1612 SCNetworkServiceRef service
)
1614 SCNetworkInterfacePrivateRef interfacePrivate
= NULL
;
1615 CFStringRef ifDevice
;
1616 CFStringRef ifSubType
;
1618 static mach_port_t masterPort
= MACH_PORT_NULL
;
1619 CFArrayRef matching_interfaces
= NULL
;
1621 if (masterPort
== MACH_PORT_NULL
) {
1624 kr
= IOMasterPort(MACH_PORT_NULL
, &masterPort
);
1625 if (kr
!= KERN_SUCCESS
) {
1630 ifType
= CFDictionaryGetValue(interface_entity
, kSCPropNetInterfaceType
);
1631 if (!isA_CFString(ifType
)) {
1635 ifSubType
= CFDictionaryGetValue(interface_entity
, kSCPropNetInterfaceSubType
);
1636 if (CFEqual(ifType
, kSCValNetInterfaceTypePPP
)) {
1637 if (!isA_CFString(ifSubType
)) {
1642 ifDevice
= CFDictionaryGetValue(interface_entity
, kSCPropNetInterfaceDeviceName
);
1644 if (CFEqual(ifType
, kSCValNetInterfaceTypeEthernet
) ||
1645 CFEqual(ifType
, kSCValNetInterfaceTypeFireWire
) ||
1646 (CFEqual(ifType
, kSCValNetInterfaceTypePPP
) && CFEqual(ifSubType
, kSCValNetInterfaceSubTypePPPoE
))) {
1647 char bsdName
[IFNAMSIZ
+ 1];
1648 CFMutableDictionaryRef matching
;
1650 if (!isA_CFString(ifDevice
)) {
1654 if (_SC_cfstring_to_cstring(ifDevice
, bsdName
, sizeof(bsdName
), kCFStringEncodingASCII
) == NULL
) {
1658 matching
= IOBSDNameMatching(masterPort
, 0, bsdName
);
1659 if (matching
== NULL
) {
1663 // note: the "matching" dictionary will be consumed by the following
1664 matching_interfaces
= findMatchingInterfaces(masterPort
, matching
, processNetworkInterface
);
1666 } else if (CFEqual(ifType
, kSCValNetInterfaceTypePPP
)) {
1667 if (CFEqual(ifSubType
, kSCValNetInterfaceSubTypePPPSerial
)) {
1668 CFDictionaryRef matching
;
1669 CFStringRef match_keys
[2];
1670 CFStringRef match_vals
[2];
1672 if (!isA_CFString(ifDevice
)) {
1676 match_keys
[0] = CFSTR(kIOProviderClassKey
);
1677 match_vals
[0] = CFSTR(kIOSerialBSDServiceValue
);
1679 match_keys
[1] = CFSTR(kIOTTYDeviceKey
);
1680 match_vals
[1] = ifDevice
;
1682 matching
= CFDictionaryCreate(NULL
,
1683 (const void **)match_keys
,
1684 (const void **)match_vals
,
1685 sizeof(match_keys
)/sizeof(match_keys
[0]),
1686 &kCFTypeDictionaryKeyCallBacks
,
1687 &kCFTypeDictionaryValueCallBacks
);
1689 // note: the "matching" dictionary will be consumed by the following
1690 matching_interfaces
= findMatchingInterfaces(masterPort
, matching
, processSerialInterface
);
1692 } else if (CFEqual(ifSubType
, kSCValNetInterfaceSubTypeL2TP
)) {
1693 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
1694 kSCNetworkInterfaceTypeL2TP
);
1695 } else if (CFEqual(ifSubType
, kSCValNetInterfaceSubTypePPTP
)) {
1696 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
1697 kSCNetworkInterfaceTypePPTP
);
1699 // XXX do we allow non-Apple variants of PPP??? XXX
1700 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
1703 } else if (CFEqual(ifType
, kSCValNetInterfaceType6to4
)) {
1704 if (!isA_CFString(ifDevice
)) {
1708 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
1709 kSCNetworkInterfaceType6to4
);
1712 if (matching_interfaces
!= NULL
) {
1715 n
= CFArrayGetCount(matching_interfaces
);
1718 if (CFEqual(ifType
, kSCValNetInterfaceTypeEthernet
)) {
1722 bonds
= findBondInterfaces(ifDevice
);
1723 if (bonds
!= NULL
) {
1724 if (CFArrayGetCount(bonds
) == 1) {
1725 interfacePrivate
= (SCNetworkInterfacePrivateRef
)CFArrayGetValueAtIndex(bonds
, 0);
1726 CFRetain(interfacePrivate
);
1732 vlans
= findVLANInterfaces(ifDevice
);
1733 if (vlans
!= NULL
) {
1734 if (CFArrayGetCount(vlans
) == 1) {
1735 interfacePrivate
= (SCNetworkInterfacePrivateRef
)CFArrayGetValueAtIndex(vlans
, 0);
1736 CFRetain(interfacePrivate
);
1744 interfacePrivate
= (SCNetworkInterfacePrivateRef
)CFArrayGetValueAtIndex(matching_interfaces
, 0);
1745 CFRetain(interfacePrivate
);
1748 SCPrint(TRUE
, stderr
, CFSTR("more than one interface matches %@\n"), ifDevice
);
1749 if (matching_interfaces
!= NULL
) CFRelease(matching_interfaces
);
1750 _SCErrorSet(kSCStatusFailed
);
1753 CFRelease(matching_interfaces
);
1758 if (interfacePrivate
== NULL
) {
1760 * if device not present on this system
1762 interfacePrivate
= __SCNetworkInterfaceCreatePrivate(NULL
, NULL
, NULL
, NULL
);
1763 interfacePrivate
->entity_type
= ifType
;
1764 interfacePrivate
->entity_subtype
= ifSubType
;
1765 interfacePrivate
->entity_device
= (ifDevice
!= NULL
) ? CFStringCreateCopy(NULL
, ifDevice
) : NULL
;
1766 interfacePrivate
->entity_hardware
= CFDictionaryGetValue(interface_entity
, kSCPropNetInterfaceHardware
);
1768 if (CFEqual(ifType
, kSCValNetInterfaceTypeEthernet
)) {
1769 if ((interfacePrivate
->entity_hardware
!= NULL
) &&
1770 CFEqual(interfacePrivate
->entity_hardware
, kSCEntNetAirPort
)) {
1771 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeIEEE80211
;
1773 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
;
1775 } else if (CFEqual(ifType
, kSCValNetInterfaceTypeFireWire
)) {
1776 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeFireWire
;
1777 } else if (CFEqual(ifType
, kSCValNetInterfaceTypePPP
)) {
1778 if (CFEqual(ifSubType
, kSCValNetInterfaceSubTypePPPoE
)) {
1779 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
;
1780 } else if (CFEqual(ifSubType
, kSCValNetInterfaceSubTypePPPSerial
)) {
1781 if (CFStringHasPrefix(ifDevice
, CFSTR("irda"))) {
1782 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeIrDA
;
1783 } else if (CFStringHasPrefix(ifDevice
, CFSTR("Bluetooth"))) {
1784 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeBluetooth
;
1786 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeModem
;
1790 CFRelease(interfacePrivate
);
1791 interfacePrivate
= (SCNetworkInterfacePrivateRef
)kSCNetworkInterfaceIPv4
;
1792 CFRetain(interfacePrivate
);
1795 // unknown interface type
1796 CFRelease(interfacePrivate
);
1797 interfacePrivate
= NULL
;
1801 if ((interfacePrivate
!= NULL
) && (service
!= NULL
)) {
1802 interfacePrivate
->service
= service
;
1805 if (CFEqual(ifType
, kSCValNetInterfaceTypePPP
)) {
1806 SCNetworkInterfaceRef parent
;
1808 parent
= SCNetworkInterfaceCreateWithInterface((SCNetworkInterfaceRef
)interfacePrivate
,
1809 kSCNetworkInterfaceTypePPP
);
1810 CFRelease(interfacePrivate
);
1811 interfacePrivate
= (SCNetworkInterfacePrivateRef
)parent
;
1814 return (SCNetworkInterfaceRef
)interfacePrivate
;
1818 /* ---------- helper functions ---------- */
1822 findConfiguration(CFStringRef interface_type
)
1826 for (i
= 0; i
< sizeof(configurations
)/sizeof(configurations
[0]); i
++) {
1827 if (CFEqual(interface_type
, *configurations
[i
].interface_type
)) {
1837 copyConfigurationPaths(SCNetworkInterfacePrivateRef interfacePrivate
)
1839 CFMutableArrayRef array
= NULL
;
1840 CFIndex interfaceIndex
;
1842 SCNetworkServicePrivateRef servicePrivate
;
1844 interfaceIndex
= findConfiguration(interfacePrivate
->interface_type
);
1845 if (interfaceIndex
== kCFNotFound
) {
1846 // if unknown interface type
1850 servicePrivate
= (SCNetworkServicePrivateRef
)interfacePrivate
->service
;
1851 if (servicePrivate
== NULL
) {
1852 // if not associated with a service (yet)
1856 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1858 if (configurations
[interfaceIndex
].per_interface_config
) {
1864 * per-interface configuration preferences
1866 * 1. look for all sets which contain the associated service
1867 * 2. add a per-set path for the interface configuration for
1871 sets
= SCNetworkSetCopyAll(servicePrivate
->prefs
);
1872 n
= (sets
!= NULL
) ? CFArrayGetCount(sets
) : 0;
1874 for (i
= 0; i
< n
; i
++) {
1875 CFArrayRef services
;
1876 SCNetworkSetRef set
;
1878 set
= CFArrayGetValueAtIndex(sets
, i
);
1879 services
= SCNetworkSetCopyServices(set
);
1880 if (CFArrayContainsValue(services
,
1881 CFRangeMake(0, CFArrayGetCount(services
)),
1882 interfacePrivate
->service
)) {
1883 path
= SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL
, // allocator
1884 SCNetworkSetGetSetID(set
), // set
1885 interfacePrivate
->entity_device
, // service
1886 interfacePrivate
->entity_type
); // entity
1887 CFArrayAppendValue(array
, path
);
1890 CFRelease(services
);
1893 if (CFArrayGetCount(array
) == 0) {
1900 // per-service configuration preferences
1901 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1902 servicePrivate
->serviceID
, // service
1903 interfacePrivate
->entity_type
); // entity
1904 CFArrayAppendValue(array
, path
);
1912 /* ---------- SCNetworkInterface APIs ---------- */
1915 CFArrayRef
/* of SCNetworkInterfaceRef's */
1916 SCNetworkInterfaceCopyAll()
1918 CFMutableArrayRef all_interfaces
;
1919 static mach_port_t masterPort
= MACH_PORT_NULL
;
1920 CFDictionaryRef matching
;
1921 CFStringRef match_keys
[2];
1922 CFStringRef match_vals
[2];
1923 CFArrayRef new_interfaces
;
1925 if (masterPort
== MACH_PORT_NULL
) {
1928 kr
= IOMasterPort(MACH_PORT_NULL
, &masterPort
);
1929 if (kr
!= KERN_SUCCESS
) {
1934 all_interfaces
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1936 // get Ethernet, Firewire, and AirPort interfaces
1938 matching
= IOServiceMatching(kIONetworkInterfaceClass
);
1939 new_interfaces
= findMatchingInterfaces(masterPort
, matching
, processNetworkInterface
);
1940 if (new_interfaces
!= NULL
) {
1941 CFArrayAppendArray(all_interfaces
, new_interfaces
, CFRangeMake(0, CFArrayGetCount(new_interfaces
)));
1942 CFRelease(new_interfaces
);
1945 // get Modem interfaces
1947 match_keys
[0] = CFSTR(kIOProviderClassKey
);
1948 match_vals
[0] = CFSTR(kIOSerialBSDServiceValue
);
1950 match_keys
[1] = CFSTR(kIOSerialBSDTypeKey
);
1951 match_vals
[1] = CFSTR(kIOSerialBSDModemType
);
1953 matching
= CFDictionaryCreate(NULL
,
1954 (const void **)match_keys
,
1955 (const void **)match_vals
,
1956 sizeof(match_keys
)/sizeof(match_keys
[0]),
1957 &kCFTypeDictionaryKeyCallBacks
,
1958 &kCFTypeDictionaryValueCallBacks
);
1959 new_interfaces
= findMatchingInterfaces(masterPort
, matching
, processSerialInterface
);
1960 if (new_interfaces
!= NULL
) {
1961 CFArrayAppendArray(all_interfaces
, new_interfaces
, CFRangeMake(0, CFArrayGetCount(new_interfaces
)));
1962 CFRelease(new_interfaces
);
1965 // get serial (RS232) interfaces
1967 match_keys
[0] = CFSTR(kIOProviderClassKey
);
1968 match_vals
[0] = CFSTR(kIOSerialBSDServiceValue
);
1970 match_keys
[1] = CFSTR(kIOSerialBSDTypeKey
);
1971 match_vals
[1] = CFSTR(kIOSerialBSDRS232Type
);
1973 matching
= CFDictionaryCreate(NULL
,
1974 (const void **)match_keys
,
1975 (const void **)match_vals
,
1976 sizeof(match_keys
)/sizeof(match_keys
[0]),
1977 &kCFTypeDictionaryKeyCallBacks
,
1978 &kCFTypeDictionaryValueCallBacks
);
1979 new_interfaces
= findMatchingInterfaces(masterPort
, matching
, processSerialInterface
);
1980 if (new_interfaces
!= NULL
) {
1981 CFArrayAppendArray(all_interfaces
, new_interfaces
, CFRangeMake(0, CFArrayGetCount(new_interfaces
)));
1982 CFRelease(new_interfaces
);
1985 new_interfaces
= findBondInterfaces(NULL
);
1986 if (new_interfaces
!= NULL
) {
1987 CFArrayAppendArray(all_interfaces
, new_interfaces
, CFRangeMake(0, CFArrayGetCount(new_interfaces
)));
1988 CFRelease(new_interfaces
);
1991 new_interfaces
= findVLANInterfaces(NULL
);
1992 if (new_interfaces
!= NULL
) {
1993 CFArrayAppendArray(all_interfaces
, new_interfaces
, CFRangeMake(0, CFArrayGetCount(new_interfaces
)));
1994 CFRelease(new_interfaces
);
1997 sort_interfaces(all_interfaces
);
1999 return all_interfaces
;
2003 CFArrayRef
/* of kSCNetworkInterfaceTypeXXX CFStringRef's */
2004 SCNetworkInterfaceGetSupportedInterfaceTypes(SCNetworkInterfaceRef interface
)
2007 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2009 if (interfacePrivate
->supported_interface_types
!= NULL
) {
2013 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
2014 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
2016 i
= findConfiguration(interfacePrivate
->interface_type
);
2017 if (i
!= kCFNotFound
) {
2018 if (configurations
[i
].supported_interfaces
!= doNone
) {
2019 interfacePrivate
->supported_interface_types
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
2020 if (configurations
[i
].supported_interfaces
& do6to4
) {
2021 CFArrayAppendValue(interfacePrivate
->supported_interface_types
, kSCNetworkInterfaceType6to4
);
2023 if (configurations
[i
].supported_interfaces
& doL2TP
) {
2024 CFArrayAppendValue(interfacePrivate
->supported_interface_types
, kSCNetworkInterfaceTypeL2TP
);
2026 if (configurations
[i
].supported_interfaces
& doPPP
) {
2027 CFArrayAppendValue(interfacePrivate
->supported_interface_types
, kSCNetworkInterfaceTypePPP
);
2029 if (configurations
[i
].supported_interfaces
& doPPTP
) {
2030 CFArrayAppendValue(interfacePrivate
->supported_interface_types
, kSCNetworkInterfaceTypePPTP
);
2037 return interfacePrivate
->supported_interface_types
;
2041 CFArrayRef
/* of kSCNetworkProtocolTypeXXX CFStringRef's */
2042 SCNetworkInterfaceGetSupportedProtocolTypes(SCNetworkInterfaceRef interface
)
2045 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2047 if (interfacePrivate
->supported_protocol_types
!= NULL
) {
2051 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
2052 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
2054 i
= findConfiguration(interfacePrivate
->interface_type
);
2055 if (i
!= kCFNotFound
) {
2056 if (configurations
[i
].supported_protocols
!= doNone
) {
2057 interfacePrivate
->supported_protocol_types
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
2058 if (configurations
[i
].supported_protocols
& doAppleTalk
) {
2059 CFArrayAppendValue(interfacePrivate
->supported_protocol_types
, kSCNetworkProtocolTypeAppleTalk
);
2061 if (configurations
[i
].supported_protocols
& doDNS
) {
2062 CFArrayAppendValue(interfacePrivate
->supported_protocol_types
, kSCNetworkProtocolTypeDNS
);
2064 if (configurations
[i
].supported_protocols
& doIPv4
) {
2065 CFArrayAppendValue(interfacePrivate
->supported_protocol_types
, kSCNetworkProtocolTypeIPv4
);
2067 if (configurations
[i
].supported_protocols
& doIPv6
) {
2068 CFArrayAppendValue(interfacePrivate
->supported_protocol_types
, kSCNetworkProtocolTypeIPv6
);
2070 if (configurations
[i
].supported_protocols
& doProxies
) {
2071 CFArrayAppendValue(interfacePrivate
->supported_protocol_types
, kSCNetworkProtocolTypeProxies
);
2078 return interfacePrivate
->supported_protocol_types
;
2082 SCNetworkInterfaceRef
2083 SCNetworkInterfaceCreateWithInterface(SCNetworkInterfaceRef child
, CFStringRef interfaceType
)
2085 SCNetworkInterfacePrivateRef childPrivate
= (SCNetworkInterfacePrivateRef
)child
;
2087 SCNetworkInterfacePrivateRef parentPrivate
;
2089 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
2090 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
2092 childIndex
= findConfiguration(childPrivate
->interface_type
);
2094 parentPrivate
= __SCNetworkInterfaceCreatePrivate(NULL
, child
, childPrivate
->service
, NULL
);
2095 if (parentPrivate
== NULL
) {
2096 _SCErrorSet(kSCStatusFailed
);
2100 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
)) {
2101 parentPrivate
->interface_type
= kSCNetworkInterfaceTypePPP
;
2102 parentPrivate
->entity_type
= kSCEntNetPPP
;
2105 if (childIndex
!= kCFNotFound
) {
2106 if (configurations
[childIndex
].ppp_subtype
!= NULL
) {
2107 parentPrivate
->entity_subtype
= *configurations
[childIndex
].ppp_subtype
;
2109 // sorry, the child interface does not support PPP
2113 // if the child's interface type not known, use the child entities "Type"
2114 parentPrivate
->entity_subtype
= childPrivate
->entity_type
;
2117 if (childPrivate
->entity_device
!= NULL
) {
2118 parentPrivate
->entity_device
= CFStringCreateCopy(NULL
, childPrivate
->entity_device
);
2120 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeL2TP
)) {
2121 if ((childIndex
== kCFNotFound
) ||
2122 ((configurations
[childIndex
].supported_interfaces
& doL2TP
) != doL2TP
)) {
2123 // if the child interface does not support L2TP
2126 parentPrivate
->interface_type
= kSCNetworkInterfaceTypeL2TP
;
2127 parentPrivate
->entity_type
= kSCValNetInterfaceSubTypeL2TP
; // interface config goes into "L2TP"
2128 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPTP
)) {
2129 if ((childIndex
== kCFNotFound
) ||
2130 ((configurations
[childIndex
].supported_interfaces
& doPPTP
) != doPPTP
)) {
2131 // if the child interface does not support PPTP
2134 parentPrivate
->interface_type
= kSCNetworkInterfaceTypePPTP
;
2135 parentPrivate
->entity_type
= kSCValNetInterfaceSubTypePPTP
; // interface config goes into "PPTP"
2136 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceType6to4
)) {
2137 if ((childIndex
== kCFNotFound
) ||
2138 ((configurations
[childIndex
].supported_interfaces
& do6to4
) != do6to4
)) {
2139 // if the child interface does not support 6to4
2143 parentPrivate
->interface_type
= kSCNetworkInterfaceType6to4
;
2144 parentPrivate
->entity_type
= kSCEntNet6to4
;
2145 parentPrivate
->entity_device
= CFRetain(CFSTR("stf0"));
2146 CFRetain(parentPrivate
->entity_device
);
2148 // unknown interface type
2152 parentPrivate
->entity_hardware
= childPrivate
->entity_hardware
;
2153 parentPrivate
->sort_order
= childPrivate
->sort_order
;
2155 return (SCNetworkInterfaceRef
)parentPrivate
;
2159 CFRelease(parentPrivate
);
2160 _SCErrorSet(kSCStatusInvalidArgument
);
2165 static CFDictionaryRef
2166 __SCNetworkInterfaceGetConfiguration(SCNetworkInterfaceRef interface
, Boolean okToHold
)
2168 CFDictionaryRef config
= NULL
;
2169 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2172 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
2173 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
2175 paths
= copyConfigurationPaths(interfacePrivate
);
2176 if (paths
!= NULL
) {
2178 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)interfacePrivate
->service
;
2180 path
= CFArrayGetValueAtIndex(paths
, 0);
2181 config
= __getPrefsConfiguration(servicePrivate
->prefs
, path
);
2184 } else if (okToHold
) {
2185 config
= interfacePrivate
->unsaved
;
2193 SCNetworkInterfaceGetConfiguration(SCNetworkInterfaceRef interface
)
2195 return __SCNetworkInterfaceGetConfiguration(interface
, FALSE
);
2200 SCNetworkInterfaceGetBSDName(SCNetworkInterfaceRef interface
)
2202 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2204 if (interfacePrivate
->interface
!= NULL
) {
2208 return interfacePrivate
->entity_device
;
2213 SCNetworkInterfaceGetHardwareAddressString(SCNetworkInterfaceRef interface
)
2215 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2217 return interfacePrivate
->address
;
2220 SCNetworkInterfaceRef
2221 SCNetworkInterfaceGetInterface(SCNetworkInterfaceRef interface
)
2223 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2225 return interfacePrivate
->interface
;
2230 SCNetworkInterfaceGetInterfaceType(SCNetworkInterfaceRef interface
)
2232 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2234 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
2235 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
2237 return interfacePrivate
->interface_type
;
2242 SCNetworkInterfaceGetLocalizedDisplayName(SCNetworkInterfaceRef interface
)
2244 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2246 if (interfacePrivate
->localized_name
== NULL
) {
2247 CFStringRef child
= NULL
;
2248 CFMutableStringRef local
= NULL
;
2250 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
); /* initialize runtime */
2252 if (interfacePrivate
->interface
!= NULL
) {
2253 child
= SCNetworkInterfaceGetLocalizedDisplayName(interfacePrivate
->interface
);
2256 if (interfacePrivate
->localized_key
!= NULL
) {
2259 fmt
= CFBundleCopyLocalizedString(bundle
,
2260 interfacePrivate
->localized_key
,
2261 interfacePrivate
->localized_key
,
2262 NETWORKINTERFACE_LOCALIZATIONS
);
2264 local
= CFStringCreateMutable(NULL
, 0);
2265 CFStringAppendFormat(local
,
2268 interfacePrivate
->localized_arg1
,
2269 interfacePrivate
->localized_arg2
);
2274 if (local
== NULL
) {
2275 // create (non-)localized name based on the interface type
2276 local
= CFStringCreateMutableCopy(NULL
, 0, interfacePrivate
->interface_type
);
2278 // ... and, if this is a leaf node, the interface device
2279 if ((interfacePrivate
->entity_device
!= NULL
) && (child
== NULL
)) {
2280 CFStringAppendFormat(local
, NULL
, CFSTR(" (%@)"), interfacePrivate
->entity_device
);
2284 if (child
== NULL
) {
2285 // no child, show just this interfaces localized name
2286 interfacePrivate
->localized_name
= CFStringCreateCopy(NULL
, local
);
2288 // show localized interface name layered over child
2289 interfacePrivate
->localized_name
= CFStringCreateWithFormat(NULL
,
2298 return interfacePrivate
->localized_name
;
2303 SCNetworkInterfaceGetTypeID(void)
2305 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
); /* initialize runtime */
2306 return __kSCNetworkInterfaceTypeID
;
2310 __private_extern__ Boolean
2311 __SCNetworkInterfaceSetConfiguration(SCNetworkInterfaceRef interface
, CFDictionaryRef config
, Boolean okToHold
)
2313 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2317 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
2318 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
2320 paths
= copyConfigurationPaths(interfacePrivate
);
2321 if (paths
!= NULL
) {
2324 SCPreferencesRef prefs
;
2325 SCNetworkServicePrivateRef servicePrivate
;
2327 servicePrivate
= (SCNetworkServicePrivateRef
)interfacePrivate
->service
;
2328 prefs
= servicePrivate
->prefs
;
2330 n
= CFArrayGetCount(paths
);
2331 for (i
= 0; i
< n
; i
++) {
2334 path
= CFArrayGetValueAtIndex(paths
, i
);
2335 ok
= __setPrefsConfiguration(prefs
, path
, config
, FALSE
);
2342 } else if (okToHold
) {
2343 interfacePrivate
->unsaved
= config
;
2346 _SCErrorSet(kSCStatusNoKey
);
2354 SCNetworkInterfaceSetConfiguration(SCNetworkInterfaceRef interface
, CFDictionaryRef config
)
2356 return __SCNetworkInterfaceSetConfiguration(interface
, config
, FALSE
);
2360 /* ---------- SCNetworkInterface internal SPIs ---------- */
2363 __private_extern__ SCNetworkInterfacePrivateRef
2364 __SCNetworkInterfaceCreateCopy(CFAllocatorRef allocator
,
2365 SCNetworkInterfaceRef interface
,
2366 SCNetworkServiceRef service
)
2368 SCNetworkInterfacePrivateRef oldPrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2369 SCNetworkInterfacePrivateRef newPrivate
;
2371 newPrivate
= __SCNetworkInterfaceCreatePrivate(NULL
, NULL
, NULL
, NULL
);
2372 newPrivate
->interface_type
= CFRetain(oldPrivate
->interface_type
);
2373 if (oldPrivate
->interface
!= NULL
) {
2374 newPrivate
->interface
= (SCNetworkInterfaceRef
)__SCNetworkInterfaceCreateCopy(NULL
, // allocator
2375 oldPrivate
->interface
, // interface
2376 service
); // [new] service
2378 newPrivate
->localized_name
= (oldPrivate
->localized_name
!= NULL
) ? CFRetain(oldPrivate
->localized_name
) : NULL
;
2379 newPrivate
->service
= service
;
2380 newPrivate
->unsaved
= (oldPrivate
->unsaved
!= NULL
) ? CFRetain(oldPrivate
->unsaved
) : NULL
;
2381 newPrivate
->entity_device
= (oldPrivate
->entity_device
!= NULL
) ? CFRetain(oldPrivate
->entity_device
) : NULL
;
2382 newPrivate
->entity_hardware
= CFRetain(oldPrivate
->entity_hardware
);
2383 newPrivate
->entity_type
= oldPrivate
->entity_type
;
2384 newPrivate
->entity_subtype
= oldPrivate
->entity_subtype
;
2385 if (oldPrivate
->supported_interface_types
!= NULL
) {
2386 newPrivate
->supported_interface_types
= CFArrayCreateMutableCopy(NULL
, 0, oldPrivate
->supported_interface_types
);
2388 if (oldPrivate
->supported_protocol_types
!= NULL
) {
2389 newPrivate
->supported_protocol_types
= CFArrayCreateMutableCopy(NULL
, 0, oldPrivate
->supported_protocol_types
);
2391 newPrivate
->address
= (oldPrivate
->address
!= NULL
) ? CFRetain(oldPrivate
->address
) : NULL
;
2392 newPrivate
->builtin
= oldPrivate
->builtin
;
2393 newPrivate
->path
= (oldPrivate
->path
!= NULL
) ? CFRetain(oldPrivate
->path
) : NULL
;
2394 newPrivate
->location
= (oldPrivate
->location
!= NULL
) ? CFRetain(oldPrivate
->location
) : NULL
;
2395 newPrivate
->supportsDeviceOnHold
= oldPrivate
->supportsDeviceOnHold
;
2396 newPrivate
->supportsBond
= oldPrivate
->supportsBond
;
2397 newPrivate
->supportsVLAN
= oldPrivate
->supportsVLAN
;
2398 newPrivate
->sort_order
= oldPrivate
->sort_order
;
2404 __private_extern__ CFArrayRef
2405 __SCNetworkInterfaceCopyDeepConfiguration(SCNetworkInterfaceRef interface
)
2407 CFDictionaryRef config
;
2408 CFMutableArrayRef configs
;
2410 configs
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
2412 while (interface
!= NULL
) {
2413 config
= __SCNetworkInterfaceGetConfiguration(interface
, TRUE
);
2414 CFArrayAppendValue(configs
,
2415 (config
!= NULL
) ? config
: (CFDictionaryRef
)kCFNull
);
2416 interface
= SCNetworkInterfaceGetInterface(interface
);
2423 __private_extern__
void
2424 __SCNetworkInterfaceSetDeepConfiguration(SCNetworkInterfaceRef interface
, CFArrayRef configs
)
2428 for (i
= 0; interface
!= NULL
; i
++) {
2429 CFDictionaryRef config
;
2431 config
= (configs
!= NULL
) ? CFArrayGetValueAtIndex(configs
, i
) : NULL
;
2432 if (!isA_CFDictionary(config
) || (CFDictionaryGetCount(config
) == 0)) {
2436 (void) __SCNetworkInterfaceSetConfiguration(interface
, config
, TRUE
);
2437 interface
= SCNetworkInterfaceGetInterface(interface
);