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"
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
,
597 (const char *)CFDataGetBytePtr(ioVal
),
598 kCFStringEncodingUTF8
);
606 IODictionaryCopyCFStringValue(CFDictionaryRef io_dict
, CFStringRef io_key
)
610 ioVal
= CFDictionaryGetValue(io_dict
, io_key
);
611 return IOCopyCFStringValue(ioVal
);
616 IOStringValueHasPrefix(CFTypeRef ioVal
, CFStringRef prefix
)
618 Boolean match
= FALSE
;
619 CFIndex prefixLen
= CFStringGetLength(prefix
);
620 CFStringRef str
= ioVal
;
622 if (!isA_CFString(ioVal
)) {
623 if (isA_CFData(ioVal
)) {
624 str
= CFStringCreateWithCStringNoCopy(NULL
,
625 (const char *)CFDataGetBytePtr(ioVal
),
626 kCFStringEncodingUTF8
,
634 (CFStringGetLength(str
) >= prefixLen
) &&
635 (CFStringCompareWithOptions(str
,
637 CFRangeMake(0, prefixLen
),
638 kCFCompareCaseInsensitive
) == kCFCompareEqualTo
)) {
642 if (str
!= ioVal
) CFRelease(str
);
648 copyMACAddress(CFDictionaryRef controller_dict
)
650 CFStringRef address
= NULL
;
655 char mac
[sizeof("xx:xx:xx:xx:xx:xx:xx:xx")];
658 data
= CFDictionaryGetValue(controller_dict
, CFSTR(kIOMACAddress
));
663 bp
= (uint8_t *)CFDataGetBytePtr(data
);
664 n
= CFDataGetLength(data
) * 3;
666 if (n
> sizeof(mac
)) {
667 mac_p
= CFAllocatorAllocate(NULL
, 0, n
);
670 for (cp
= mac_p
; n
> 0; n
-= 3) {
671 cp
+= snprintf(cp
, n
, "%2.2x:", *bp
++);
674 address
= CFStringCreateWithCString(NULL
, mac_p
, kCFStringEncodingUTF8
);
675 if (mac_p
!= mac
) CFAllocatorDeallocate(NULL
, mac_p
);
680 static const struct {
681 const CFStringRef name
;
682 const CFStringRef slot
;
683 } slot_mappings
[] = {
685 { CFSTR("A1") , CFSTR("1") },
686 { CFSTR("B1") , CFSTR("2") },
687 { CFSTR("C1") , CFSTR("3") },
689 // Blue&White G3, Yikes G4
690 { CFSTR("J12"), CFSTR("1") },
691 { CFSTR("J11"), CFSTR("2") },
692 { CFSTR("J10"), CFSTR("3") },
693 { CFSTR("J9"), CFSTR("4") },
696 { CFSTR("A") , CFSTR("1") },
697 { CFSTR("B") , CFSTR("2") },
698 { CFSTR("C") , CFSTR("3") },
699 { CFSTR("D") , CFSTR("4") },
701 // Digital Audio G4 (and later models)
702 { CFSTR("1") , CFSTR("1") },
703 { CFSTR("2") , CFSTR("2") },
704 { CFSTR("3") , CFSTR("3") },
705 { CFSTR("4") , CFSTR("4") },
706 { CFSTR("5") , CFSTR("5") }
711 pci_slot(io_registry_entry_t interface
, CFTypeRef
*pci_slot_name
)
714 io_registry_entry_t slot
= interface
;
716 if (pci_slot_name
!= NULL
) *pci_slot_name
= NULL
;
718 while (slot
!= MACH_PORT_NULL
) {
719 io_registry_entry_t parent
;
722 slot_name
= IORegistryEntryCreateCFProperty(slot
, CFSTR("AAPL,slot-name"), NULL
, 0);
723 if (slot_name
!= NULL
) {
726 found
= IOStringValueHasPrefix(slot_name
, CFSTR("slot"));
729 CFMutableStringRef name
;
731 // if we found a slot #
732 name
= CFStringCreateMutable(NULL
, 0);
733 if (isA_CFString(slot_name
)) {
734 if (pci_slot_name
!= NULL
) *pci_slot_name
= CFStringCreateCopy(NULL
, slot_name
);
735 CFStringAppend(name
, slot_name
);
736 } else if (isA_CFData(slot_name
)) {
737 if (pci_slot_name
!= NULL
) *pci_slot_name
= CFDataCreateCopy(NULL
, slot_name
);
738 CFStringAppendCString(name
,
739 (const char *)CFDataGetBytePtr(slot_name
),
740 kCFStringEncodingUTF8
);
743 (void) CFStringFindAndReplace(name
,
747 kCFCompareCaseInsensitive
|kCFCompareAnchored
);
748 for (i
= 0; i
< sizeof(slot_mappings
)/sizeof(slot_mappings
[0]); i
++) {
749 if (CFStringCompareWithOptions(name
,
750 slot_mappings
[i
].name
,
751 CFRangeMake(0, CFStringGetLength(slot_mappings
[i
].name
)),
752 kCFCompareCaseInsensitive
) == kCFCompareEqualTo
) {
754 name
= (CFMutableStringRef
)CFRetain(slot_mappings
[i
].slot
);
759 CFRelease(slot_name
);
760 if (slot
!= interface
) IOObjectRelease(slot
);
764 CFRelease(slot_name
);
767 kr
= IORegistryEntryGetParentEntry(slot
, kIOServicePlane
, &parent
);
768 if (slot
!= interface
) IOObjectRelease(slot
);
770 case kIOReturnSuccess
:
773 case kIOReturnNoDevice
:
774 // if we have hit the root node without finding a slot #
777 SCLog(TRUE
, LOG_INFO
, CFSTR("pci_slot IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr
);
788 static CFComparisonResult
789 compare_bsdNames(const void *val1
, const void *val2
, void *context
)
791 CFStringRef bsd1
= (CFStringRef
)val1
;
792 CFStringRef bsd2
= (CFStringRef
)val2
;
794 return CFStringCompare(bsd1
, bsd2
, 0);
799 pci_port(mach_port_t masterPort
, CFTypeRef slot_name
, CFStringRef bsdName
)
802 CFStringRef port_name
= NULL
;
803 CFMutableArrayRef port_names
;
806 CFStringRef match_keys
[2];
807 CFTypeRef match_vals
[2];
808 CFDictionaryRef match_dict
;
809 CFDictionaryRef matching
;
810 io_registry_entry_t slot
;
811 io_iterator_t slot_iterator
= MACH_PORT_NULL
;
813 match_keys
[0] = CFSTR("AAPL,slot-name");
814 match_vals
[0] = slot_name
;
816 match_dict
= CFDictionaryCreate(NULL
,
817 (const void **)match_keys
,
818 (const void **)match_vals
,
820 &kCFTypeDictionaryKeyCallBacks
,
821 &kCFTypeDictionaryValueCallBacks
);
823 match_keys
[0] = CFSTR(kIOProviderClassKey
);
824 match_vals
[0] = CFSTR("IOPCIDevice");
826 match_keys
[1] = CFSTR(kIOPropertyMatchKey
);
827 match_vals
[1] = match_dict
;
829 // note: the "matching" dictionary will be consumed by the following
830 matching
= CFDictionaryCreate(NULL
,
831 (const void **)match_keys
,
832 (const void **)match_vals
,
833 sizeof(match_keys
)/sizeof(match_keys
[0]),
834 &kCFTypeDictionaryKeyCallBacks
,
835 &kCFTypeDictionaryValueCallBacks
);
836 CFRelease(match_dict
);
838 kr
= IOServiceGetMatchingServices(masterPort
, matching
, &slot_iterator
);
839 if (kr
!= kIOReturnSuccess
) {
840 SCPrint(TRUE
, stderr
, CFSTR("IOServiceGetMatchingServices() failed, kr = 0x%x\n"), kr
);
841 return MACH_PORT_NULL
;
844 port_names
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
846 while ((slot
= IOIteratorNext(slot_iterator
)) != MACH_PORT_NULL
) {
847 io_registry_entry_t child
;
848 io_iterator_t child_iterator
= MACH_PORT_NULL
;
850 kr
= IORegistryEntryCreateIterator(slot
,
852 kIORegistryIterateRecursively
,
854 if (kr
!= kIOReturnSuccess
) {
855 SCPrint(TRUE
, stderr
, CFSTR("IORegistryEntryCreateIterator() failed, kr = 0x%x\n"), kr
);
856 return MACH_PORT_NULL
;
859 while ((child
= IOIteratorNext(child_iterator
)) != MACH_PORT_NULL
) {
860 if (IOObjectConformsTo(child
, kIONetworkInterfaceClass
)) {
861 CFStringRef if_bsdName
;
863 if_bsdName
= IORegistryEntryCreateCFProperty(child
,
864 CFSTR(kIOBSDNameKey
),
867 if (if_bsdName
!= NULL
) {
868 CFArrayAppendValue(port_names
, if_bsdName
);
869 CFRelease(if_bsdName
);
872 IOObjectRelease(child
);
874 IOObjectRelease(child_iterator
);
875 IOObjectRelease(slot
);
877 IOObjectRelease(slot_iterator
);
879 n
= CFArrayGetCount(port_names
);
881 CFArraySortValues(port_names
, CFRangeMake(0, n
), compare_bsdNames
, NULL
);
882 n
= CFArrayGetFirstIndexOfValue(port_names
, CFRangeMake(0, n
), bsdName
);
883 if (n
!= kCFNotFound
) {
884 port_name
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%d"), n
+ 1);
888 CFRelease(port_names
);
894 pci_slot_info(mach_port_t masterPort
, io_registry_entry_t interface
, CFStringRef
*slot_name
, CFStringRef
*port_name
)
896 CFStringRef bsd_name
;
898 CFTypeRef pci_slot_name
;
903 bsd_name
= IORegistryEntryCreateCFProperty(interface
, CFSTR(kIOBSDNameKey
), NULL
, 0);
904 if (bsd_name
== NULL
) {
908 *slot_name
= pci_slot(interface
, &pci_slot_name
);
909 if (*slot_name
!= NULL
) {
910 if (pci_slot_name
!= NULL
) {
911 *port_name
= pci_port(masterPort
, pci_slot_name
, bsd_name
);
912 CFRelease(pci_slot_name
);
923 isBuiltIn(io_registry_entry_t interface
)
926 io_registry_entry_t slot
= interface
;
928 while (slot
!= MACH_PORT_NULL
) {
929 io_registry_entry_t parent
;
932 slot_name
= IORegistryEntryCreateCFProperty(slot
, CFSTR("AAPL,slot-name"), NULL
, 0);
933 if (slot_name
!= NULL
) {
936 found
= IOStringValueHasPrefix(slot_name
, CFSTR("slot"));
937 CFRelease(slot_name
);
940 // if we found a slot # then this is not a built-in interface
941 if (slot
!= interface
) IOObjectRelease(slot
);
946 kr
= IORegistryEntryGetParentEntry(slot
, kIOServicePlane
, &parent
);
947 if (slot
!= interface
) IOObjectRelease(slot
);
949 case kIOReturnSuccess
:
952 case kIOReturnNoDevice
:
953 // if we have hit the root node without finding a slot #
956 SCLog(TRUE
, LOG_INFO
, CFSTR("isBuiltIn IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr
);
965 /* ---------- interface enumeration ---------- */
968 typedef Boolean (*processInterface
)(mach_port_t masterPort
,
969 SCNetworkInterfacePrivateRef interfacePrivate
,
970 io_registry_entry_t interface
,
971 CFDictionaryRef interface_dict
,
972 io_registry_entry_t controller
,
973 CFDictionaryRef controller_dict
,
974 io_registry_entry_t bus
,
975 CFDictionaryRef bus_dict
);
979 processNetworkInterface(mach_port_t masterPort
,
980 SCNetworkInterfacePrivateRef interfacePrivate
,
981 io_registry_entry_t interface
,
982 CFDictionaryRef interface_dict
,
983 io_registry_entry_t controller
,
984 CFDictionaryRef controller_dict
,
985 io_registry_entry_t bus
,
986 CFDictionaryRef bus_dict
)
997 // get the interface type
999 num
= CFDictionaryGetValue(interface_dict
, CFSTR(kIOInterfaceType
));
1000 if (!isA_CFNumber(num
) ||
1001 !CFNumberGetValue(num
, kCFNumberIntType
, &ift
)) {
1002 SCPrint(TRUE
, stderr
, CFSTR("Could not get interface type\n"));
1010 if (IOObjectGetClass(interface
, i_IOClass
) != KERN_SUCCESS
) {
1011 i_IOClass
[0] = '\0';
1013 if (IOObjectGetClass(controller
, c_IOClass
) != KERN_SUCCESS
) {
1014 c_IOClass
[0] = '\0';
1016 if (IORegistryEntryGetName(controller
, c_IOName
) != KERN_SUCCESS
) {
1020 if ((strcmp(i_IOClass
, "IO80211Interface" ) == 0) ||
1021 (strcmp(c_IOClass
, "AirPortPCI" ) == 0) ||
1022 (strcmp(c_IOClass
, "AirPortDriver" ) == 0) ||
1023 (strcmp(c_IOName
, "AppleWireless80211") == 0)) {
1024 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeIEEE80211
;
1025 interfacePrivate
->entity_type
= kSCEntNetEthernet
;
1026 interfacePrivate
->entity_hardware
= kSCEntNetAirPort
;
1027 interfacePrivate
->sort_order
= kSortAirPort
;
1029 str
= IODictionaryCopyCFStringValue(bus_dict
, CFSTR("name"));
1030 if ((str
!= NULL
) && CFEqual(str
, CFSTR("radio"))) {
1031 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
; // ??
1032 interfacePrivate
->entity_type
= kSCEntNetEthernet
;
1033 interfacePrivate
->entity_hardware
= kSCEntNetEthernet
; // ??
1034 interfacePrivate
->sort_order
= kSortOtherWireless
;
1036 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
;
1037 interfacePrivate
->entity_type
= kSCEntNetEthernet
;
1038 interfacePrivate
->entity_hardware
= kSCEntNetEthernet
;
1039 interfacePrivate
->sort_order
= kSortEthernet
;
1041 // BOND support only enabled for ethernet devices
1042 interfacePrivate
->supportsBond
= TRUE
;
1045 if (str
!= NULL
) CFRelease(str
);
1049 bVal
= isA_CFBoolean(CFDictionaryGetValue(interface_dict
, CFSTR(kIOBuiltin
)));
1050 if ((bVal
== NULL
) || !CFBooleanGetValue(bVal
)) {
1051 bVal
= isA_CFBoolean(CFDictionaryGetValue(interface_dict
, CFSTR(kIOPrimaryInterface
)));
1054 interfacePrivate
->builtin
= CFBooleanGetValue(bVal
);
1056 interfacePrivate
->builtin
= isBuiltIn(interface
);
1060 interfacePrivate
->location
= IODictionaryCopyCFStringValue(interface_dict
, CFSTR(kIOLocation
));
1063 num
= CFDictionaryGetValue(controller_dict
, CFSTR(kIOFeatures
));
1064 if (isA_CFNumber(num
) &&
1065 CFNumberGetValue(num
, kCFNumberIntType
, & iVal
)) {
1066 if (iVal
& (kIONetworkFeatureHardwareVlan
| kIONetworkFeatureSoftwareVlan
)) {
1067 interfacePrivate
->supportsVLAN
= TRUE
;
1072 if (interfacePrivate
->builtin
) {
1073 if ((interfacePrivate
->location
== NULL
) ||
1074 (CFStringGetLength(interfacePrivate
->location
) == 0)) {
1075 interfacePrivate
->localized_key
= CFSTR("ether");
1077 interfacePrivate
->localized_key
= CFSTR("multiether");
1078 interfacePrivate
->localized_arg1
= CFRetain(interfacePrivate
->location
);
1080 } else if (CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeIEEE80211
)) {
1081 interfacePrivate
->localized_key
= CFSTR("airport");
1082 } else if (interfacePrivate
->sort_order
== kSortOtherWireless
) {
1083 interfacePrivate
->localized_key
= CFSTR("wireless");
1084 interfacePrivate
->localized_arg1
= CFRetain(CFSTR("")); // ??
1086 CFStringRef provider
;
1088 // check provider class
1089 provider
= IORegistryEntrySearchCFProperty(interface
,
1091 CFSTR(kIOProviderClassKey
),
1093 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1094 if (provider
!= NULL
) {
1095 if (CFEqual(provider
, CFSTR("IOPCIDevice"))) {
1096 CFStringRef port_name
;
1097 CFStringRef slot_name
;
1099 if (pci_slot_info(masterPort
, interface
, &slot_name
, &port_name
)) {
1100 if (port_name
== NULL
) {
1101 interfacePrivate
->localized_key
= CFSTR("pci-ether");
1102 interfacePrivate
->localized_arg1
= slot_name
;
1104 interfacePrivate
->localized_key
= CFSTR("pci-multiether");
1105 interfacePrivate
->localized_arg1
= slot_name
;
1106 interfacePrivate
->localized_arg2
= port_name
;
1110 CFRelease(provider
);
1113 if (interfacePrivate
->localized_key
== NULL
) {
1114 // if no provider, not a PCI device, or no slot information
1115 interfacePrivate
->localized_key
= CFSTR("generic-ether");
1116 interfacePrivate
->localized_arg1
= IODictionaryCopyCFStringValue(interface_dict
, CFSTR(kIOBSDNameKey
));
1123 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeFireWire
;
1126 interfacePrivate
->entity_type
= kSCEntNetFireWire
;
1127 interfacePrivate
->entity_hardware
= kSCEntNetFireWire
;
1130 interfacePrivate
->builtin
= isBuiltIn(interface
);
1133 interfacePrivate
->sort_order
= kSortFireWire
;
1136 if (interfacePrivate
->builtin
) {
1137 interfacePrivate
->localized_key
= CFSTR("firewire");
1139 CFStringRef slot_name
;
1141 slot_name
= pci_slot(interface
, NULL
);
1142 if (slot_name
!= NULL
) {
1143 interfacePrivate
->localized_key
= CFSTR("pci-firewire");
1144 interfacePrivate
->localized_arg1
= slot_name
;
1150 SCPrint(TRUE
, stderr
, CFSTR("Unknown interface type = %d\n"), ift
);
1155 interfacePrivate
->entity_device
= IODictionaryCopyCFStringValue(interface_dict
, CFSTR(kIOBSDNameKey
));
1157 // Hardware (MAC) address
1158 interfacePrivate
->address
= copyMACAddress(controller_dict
);
1165 processSerialInterface(mach_port_t masterPort
,
1166 SCNetworkInterfacePrivateRef interfacePrivate
,
1167 io_registry_entry_t interface
,
1168 CFDictionaryRef interface_dict
,
1169 io_registry_entry_t controller
,
1170 CFDictionaryRef controller_dict
,
1171 io_registry_entry_t bus
,
1172 CFDictionaryRef bus_dict
)
1175 Boolean isModem
= FALSE
;
1180 val
= IORegistryEntrySearchCFProperty(interface
,
1182 CFSTR("HiddenPort"),
1184 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1187 return FALSE
; // if this interface should not be exposed
1191 str
= CFDictionaryGetValue(interface_dict
, CFSTR(kIOTTYBaseNameKey
));
1199 * Exclude ports named "irda" because otherwise the IrDA ports on the
1200 * original iMac (rev's A through D) show up as serial ports. Given
1201 * that only the rev A actually had an IrDA port, and Mac OS X doesn't
1202 * even support it, these ports definitely shouldn't be listed.
1204 if (CFStringCompare(str
,
1206 kCFCompareCaseInsensitive
) == kCFCompareEqualTo
) {
1210 if (IOStringValueHasPrefix(str
, CFSTR("irda-ircomm"))) {
1212 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeIrDA
;
1213 interfacePrivate
->sort_order
= kSortIrDA
;
1214 } else if (IOStringValueHasPrefix(str
, CFSTR("bluetooth"))) {
1216 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeBluetooth
;
1217 interfacePrivate
->sort_order
= kSortBluetooth
;
1220 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeModem
;
1222 // DeviceOnHold support
1223 val
= IORegistryEntrySearchCFProperty(interface
,
1225 CFSTR(kIODeviceSupportsHoldKey
),
1227 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1229 uint32_t supportsHold
;
1231 if (isA_CFNumber(val
) &&
1232 CFNumberGetValue(val
, kCFNumberSInt32Type
, &supportsHold
)) {
1233 interfacePrivate
->supportsDeviceOnHold
= (supportsHold
== 1);
1240 interfacePrivate
->entity_type
= kSCEntNetModem
;
1242 // Entity (Hardware)
1243 ift
= CFDictionaryGetValue(interface_dict
, CFSTR(kIOSerialBSDTypeKey
));
1244 if (!isA_CFString(ift
)) {
1248 if (CFEqual(ift
, CFSTR(kIOSerialBSDModemType
))) {
1251 interfacePrivate
->entity_hardware
= kSCEntNetModem
;
1253 if (CFEqual(str
, CFSTR("modem"))) {
1254 interfacePrivate
->builtin
= TRUE
;
1255 interfacePrivate
->sort_order
= kSortInternalModem
;
1256 } else if (CFEqual(str
, CFSTR("usbmodem"))) {
1257 interfacePrivate
->sort_order
= kSortUSBModem
;
1259 interfacePrivate
->sort_order
= kSortModem
;
1261 } else if (CFEqual(ift
, CFSTR(kIOSerialBSDRS232Type
))) {
1263 interfacePrivate
->entity_hardware
= kSCEntNetModem
;
1264 interfacePrivate
->sort_order
= kSortSerialPort
;
1270 interfacePrivate
->entity_device
= IODictionaryCopyCFStringValue(interface_dict
, CFSTR(kIOTTYDeviceKey
));
1273 if (CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeIrDA
)) {
1274 interfacePrivate
->localized_key
= CFSTR("irda");
1275 } else if (CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeBluetooth
)) {
1276 interfacePrivate
->localized_key
= CFSTR("bluetooth");
1278 CFStringRef localized
;
1279 CFMutableStringRef port
;
1281 port
= CFStringCreateMutableCopy(NULL
, 0, str
);
1282 CFStringLowercase(port
, NULL
);
1285 CFStringAppend(port
, CFSTR("-port"));
1288 localized
= CFBundleCopyLocalizedString(bundle
,
1291 NETWORKINTERFACE_LOCALIZATIONS
);
1292 if (localized
!= NULL
) {
1293 if (!CFEqual(port
, localized
)) {
1294 // if localization available
1295 interfacePrivate
->localized_name
= localized
;
1297 // if no localization available, use TTY base name
1298 CFRelease(localized
);
1299 interfacePrivate
->localized_name
= CFStringCreateCopy(NULL
, str
);
1302 interfacePrivate
->localized_name
= CFStringCreateCopy(NULL
, str
);
1305 if (!isModem
|| !CFEqual(str
, CFSTR("modem"))) {
1306 CFStringRef productName
;
1308 // check if a "Product Name" has been provided
1309 val
= IORegistryEntrySearchCFProperty(interface
,
1311 CFSTR(kIOPropertyProductNameKey
),
1313 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1315 productName
= IOCopyCFStringValue(val
);
1318 if (productName
!= NULL
) {
1319 if (CFStringGetLength(productName
) > 0) {
1320 // if we have a [somewhat reasonable?] product name
1321 CFRelease(interfacePrivate
->localized_name
);
1322 interfacePrivate
->localized_name
= CFRetain(productName
);
1324 CFRelease(productName
);
1337 findMatchingInterfaces(mach_port_t masterPort
, CFDictionaryRef matching
, processInterface func
)
1339 CFMutableArrayRef interfaces
;
1340 io_registry_entry_t interface
;
1342 io_iterator_t iterator
= MACH_PORT_NULL
;
1344 kr
= IOServiceGetMatchingServices(masterPort
, matching
, &iterator
);
1345 if (kr
!= kIOReturnSuccess
) {
1346 SCPrint(TRUE
, stderr
, CFSTR("IOServiceGetMatchingServices() failed, kr = 0x%x\n"), kr
);
1350 interfaces
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1352 while ((interface
= IOIteratorNext(iterator
)) != MACH_PORT_NULL
) {
1353 io_registry_entry_t bus
= MACH_PORT_NULL
;
1354 CFMutableDictionaryRef bus_dict
= NULL
;
1355 io_registry_entry_t controller
= MACH_PORT_NULL
;
1356 CFMutableDictionaryRef controller_dict
= NULL
;
1357 SCNetworkInterfacePrivateRef interfacePrivate
= NULL
;
1358 CFMutableDictionaryRef interface_dict
= NULL
;
1361 kr
= IORegistryEntryGetPath(interface
, kIOServicePlane
, path
);
1362 if (kr
!= kIOReturnSuccess
) {
1363 SCPrint(TRUE
, stderr
, CFSTR("IORegistryEntryGetPath() failed, kr = 0x%x"), kr
);
1367 kr
= IORegistryEntryCreateCFProperties(interface
, &interface_dict
, NULL
, kNilOptions
);
1368 if (kr
!= kIOReturnSuccess
) {
1369 SCPrint(TRUE
, stderr
, CFSTR("IORegistryEntryCreateCFProperties() failed, kr = 0x%x\n"), kr
);
1373 /* get the controller node */
1374 kr
= IORegistryEntryGetParentEntry(interface
, kIOServicePlane
, &controller
);
1375 if (kr
!= KERN_SUCCESS
) {
1376 SCLog(TRUE
, LOG_INFO
, CFSTR("findMatchingInterfaces IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr
);
1380 /* get the dictionary associated with the node */
1381 kr
= IORegistryEntryCreateCFProperties(controller
, &controller_dict
, NULL
, kNilOptions
);
1382 if (kr
!= KERN_SUCCESS
) {
1383 SCLog(TRUE
, LOG_INFO
, CFSTR("findMatchingInterfaces IORegistryEntryCreateCFProperties() failed, kr = 0x%x"), kr
);
1387 /* get the bus node */
1388 kr
= IORegistryEntryGetParentEntry(controller
, kIOServicePlane
, &bus
);
1389 if (kr
!= KERN_SUCCESS
) {
1390 SCLog(TRUE
, LOG_INFO
, CFSTR("findMatchingInterfaces IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr
);
1394 /* get the dictionary associated with the node */
1395 kr
= IORegistryEntryCreateCFProperties(bus
, &bus_dict
, NULL
, kNilOptions
);
1396 if (kr
!= KERN_SUCCESS
) {
1397 SCLog(TRUE
, LOG_INFO
, CFSTR("findMatchingInterfaces IORegistryEntryCreateCFProperties() failed, kr = 0x%x"), kr
);
1401 interfacePrivate
= __SCNetworkInterfaceCreatePrivate(NULL
, NULL
, NULL
, path
);
1403 if ((*func
)(masterPort
, interfacePrivate
, interface
, interface_dict
, controller
, controller_dict
, bus
, bus_dict
)) {
1404 CFArrayAppendValue(interfaces
, (SCNetworkInterfaceRef
)interfacePrivate
);
1407 CFRelease(interfacePrivate
);
1411 if (interface
!= MACH_PORT_NULL
) IOObjectRelease(interface
);
1412 if (interface_dict
!= NULL
) CFRelease(interface_dict
);
1414 if (controller
!= MACH_PORT_NULL
) IOObjectRelease(controller
);
1415 if (controller_dict
!= NULL
) CFRelease(controller_dict
);
1417 if (bus
!= MACH_PORT_NULL
) IOObjectRelease(bus
);
1418 if (bus_dict
!= NULL
) CFRelease(bus_dict
);
1421 IOObjectRelease(iterator
);
1427 /* ---------- Bond configuration ---------- */
1430 SCNetworkInterfaceSupportsBonding(SCNetworkInterfaceRef interface
)
1432 return ((SCNetworkInterfacePrivateRef
)interface
)->supportsBond
;
1436 SCNetworkInterfaceRef
1437 SCNetworkInterfaceCreateWithBond(BondInterfaceRef bond
)
1439 SCNetworkInterfacePrivateRef interfacePrivate
;
1440 CFStringRef bond_if
;
1442 bond_if
= BondInterfaceGetInterface(bond
);
1443 if (bond_if
== NULL
) {
1447 interfacePrivate
= __SCNetworkInterfaceCreatePrivate(NULL
, NULL
, NULL
, NULL
);
1448 if (interfacePrivate
== NULL
) {
1452 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeBond
;
1453 interfacePrivate
->entity_type
= kSCEntNetEthernet
;
1454 interfacePrivate
->entity_hardware
= kSCEntNetEthernet
;
1455 interfacePrivate
->entity_device
= CFStringCreateCopy(NULL
, bond_if
);
1456 interfacePrivate
->builtin
= TRUE
;
1457 interfacePrivate
->sort_order
= kSortBond
;
1459 interfacePrivate
->localized_key
= CFSTR("bond");
1460 interfacePrivate
->localized_arg1
= CFRetain(interfacePrivate
->entity_device
);
1462 return (SCNetworkInterfaceRef
)interfacePrivate
;
1467 findBondInterfaces(CFStringRef match
)
1469 CFMutableArrayRef interfaces
= NULL
;
1472 BondPreferencesRef prefs
;
1473 CFArrayRef bonds
= NULL
;
1475 prefs
= BondPreferencesCreate(NULL
);
1476 if (prefs
== NULL
) {
1481 bonds
= BondPreferencesCopyInterfaces(prefs
);
1482 if (bonds
== NULL
) {
1487 n
= CFArrayGetCount(bonds
);
1493 interfaces
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1495 for (i
= 0; i
< n
; i
++) {
1496 SCNetworkInterfaceRef interface
;
1497 BondInterfaceRef bond
= CFArrayGetValueAtIndex(bonds
, i
);
1498 CFStringRef bond_if
;
1500 bond_if
= BondInterfaceGetInterface(bond
);
1501 if (bond_if
== NULL
) {
1505 if ((match
!= NULL
) && !CFEqual(bond_if
, match
)) {
1509 interface
= SCNetworkInterfaceCreateWithBond(bond
);
1510 CFArrayAppendValue(interfaces
, interface
);
1511 CFRelease(interface
);
1516 if (bonds
!= NULL
) CFRelease(bonds
);
1522 /* ---------- VLAN configuration ---------- */
1524 SCNetworkInterfaceRef
1525 SCNetworkInterfaceCreateWithVLAN(VLANInterfaceRef vlan
)
1527 SCNetworkInterfacePrivateRef interfacePrivate
;
1528 CFStringRef vlan_if
;
1530 vlan_if
= VLANInterfaceGetInterface(vlan
);
1531 if (vlan_if
== NULL
) {
1535 interfacePrivate
= __SCNetworkInterfaceCreatePrivate(NULL
, NULL
, NULL
, NULL
);
1536 if (interfacePrivate
== NULL
) {
1540 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeVLAN
;
1541 interfacePrivate
->entity_type
= kSCEntNetEthernet
;
1542 interfacePrivate
->entity_hardware
= kSCEntNetEthernet
;
1543 interfacePrivate
->entity_device
= CFStringCreateCopy(NULL
, vlan_if
);
1544 interfacePrivate
->builtin
= TRUE
;
1545 interfacePrivate
->sort_order
= kSortVLAN
;
1547 interfacePrivate
->localized_key
= CFSTR("vlan");
1548 interfacePrivate
->localized_arg1
= CFRetain(interfacePrivate
->entity_device
);
1550 return (SCNetworkInterfaceRef
)interfacePrivate
;
1555 findVLANInterfaces(CFStringRef match
)
1557 CFMutableArrayRef interfaces
= NULL
;
1560 VLANPreferencesRef prefs
;
1561 CFArrayRef vlans
= NULL
;
1563 prefs
= VLANPreferencesCreate(NULL
);
1564 if (prefs
== NULL
) {
1569 vlans
= VLANPreferencesCopyInterfaces(prefs
);
1570 if (vlans
== NULL
) {
1575 n
= CFArrayGetCount(vlans
);
1581 interfaces
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1583 for (i
= 0; i
< n
; i
++) {
1584 SCNetworkInterfaceRef interface
;
1585 VLANInterfaceRef vlan
= CFArrayGetValueAtIndex(vlans
, i
);
1586 CFStringRef vlan_if
;
1588 vlan_if
= VLANInterfaceGetInterface(vlan
);
1589 if (vlan_if
== NULL
) {
1593 if ((match
!= NULL
) && !CFEqual(vlan_if
, match
)) {
1597 interface
= SCNetworkInterfaceCreateWithVLAN(vlan
);
1598 CFArrayAppendValue(interfaces
, interface
);
1599 CFRelease(interface
);
1604 if (vlans
!= NULL
) CFRelease(vlans
);
1610 /* ---------- interface from preferences ---------- */
1613 __private_extern__ SCNetworkInterfaceRef
1614 __SCNetworkInterfaceCreateWithEntity(CFAllocatorRef allocator
,
1615 CFDictionaryRef interface_entity
,
1616 SCNetworkServiceRef service
)
1618 SCNetworkInterfacePrivateRef interfacePrivate
= NULL
;
1619 CFStringRef ifDevice
;
1620 CFStringRef ifSubType
;
1622 static mach_port_t masterPort
= MACH_PORT_NULL
;
1623 CFArrayRef matching_interfaces
= NULL
;
1625 if (masterPort
== MACH_PORT_NULL
) {
1628 kr
= IOMasterPort(MACH_PORT_NULL
, &masterPort
);
1629 if (kr
!= KERN_SUCCESS
) {
1634 ifType
= CFDictionaryGetValue(interface_entity
, kSCPropNetInterfaceType
);
1635 if (!isA_CFString(ifType
)) {
1639 ifSubType
= CFDictionaryGetValue(interface_entity
, kSCPropNetInterfaceSubType
);
1640 if (CFEqual(ifType
, kSCValNetInterfaceTypePPP
)) {
1641 if (!isA_CFString(ifSubType
)) {
1646 ifDevice
= CFDictionaryGetValue(interface_entity
, kSCPropNetInterfaceDeviceName
);
1648 if (CFEqual(ifType
, kSCValNetInterfaceTypeEthernet
) ||
1649 CFEqual(ifType
, kSCValNetInterfaceTypeFireWire
) ||
1650 (CFEqual(ifType
, kSCValNetInterfaceTypePPP
) && CFEqual(ifSubType
, kSCValNetInterfaceSubTypePPPoE
))) {
1651 char bsdName
[IFNAMSIZ
+ 1];
1652 CFMutableDictionaryRef matching
;
1654 if (!isA_CFString(ifDevice
)) {
1658 if (_SC_cfstring_to_cstring(ifDevice
, bsdName
, sizeof(bsdName
), kCFStringEncodingASCII
) == NULL
) {
1662 matching
= IOBSDNameMatching(masterPort
, 0, bsdName
);
1663 if (matching
== NULL
) {
1667 // note: the "matching" dictionary will be consumed by the following
1668 matching_interfaces
= findMatchingInterfaces(masterPort
, matching
, processNetworkInterface
);
1670 } else if (CFEqual(ifType
, kSCValNetInterfaceTypePPP
)) {
1671 if (CFEqual(ifSubType
, kSCValNetInterfaceSubTypePPPSerial
)) {
1672 CFDictionaryRef matching
;
1673 CFStringRef match_keys
[2];
1674 CFStringRef match_vals
[2];
1676 if (!isA_CFString(ifDevice
)) {
1680 match_keys
[0] = CFSTR(kIOProviderClassKey
);
1681 match_vals
[0] = CFSTR(kIOSerialBSDServiceValue
);
1683 match_keys
[1] = CFSTR(kIOTTYDeviceKey
);
1684 match_vals
[1] = ifDevice
;
1686 matching
= CFDictionaryCreate(NULL
,
1687 (const void **)match_keys
,
1688 (const void **)match_vals
,
1689 sizeof(match_keys
)/sizeof(match_keys
[0]),
1690 &kCFTypeDictionaryKeyCallBacks
,
1691 &kCFTypeDictionaryValueCallBacks
);
1693 // note: the "matching" dictionary will be consumed by the following
1694 matching_interfaces
= findMatchingInterfaces(masterPort
, matching
, processSerialInterface
);
1696 } else if (CFEqual(ifSubType
, kSCValNetInterfaceSubTypeL2TP
)) {
1697 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
1698 kSCNetworkInterfaceTypeL2TP
);
1699 } else if (CFEqual(ifSubType
, kSCValNetInterfaceSubTypePPTP
)) {
1700 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
1701 kSCNetworkInterfaceTypePPTP
);
1703 // XXX do we allow non-Apple variants of PPP??? XXX
1704 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
1707 } else if (CFEqual(ifType
, kSCValNetInterfaceType6to4
)) {
1708 if (!isA_CFString(ifDevice
)) {
1712 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
1713 kSCNetworkInterfaceType6to4
);
1716 if (matching_interfaces
!= NULL
) {
1719 n
= CFArrayGetCount(matching_interfaces
);
1722 if (CFEqual(ifType
, kSCValNetInterfaceTypeEthernet
)) {
1726 bonds
= findBondInterfaces(ifDevice
);
1727 if (bonds
!= NULL
) {
1728 if (CFArrayGetCount(bonds
) == 1) {
1729 interfacePrivate
= (SCNetworkInterfacePrivateRef
)CFArrayGetValueAtIndex(bonds
, 0);
1730 CFRetain(interfacePrivate
);
1736 vlans
= findVLANInterfaces(ifDevice
);
1737 if (vlans
!= NULL
) {
1738 if (CFArrayGetCount(vlans
) == 1) {
1739 interfacePrivate
= (SCNetworkInterfacePrivateRef
)CFArrayGetValueAtIndex(vlans
, 0);
1740 CFRetain(interfacePrivate
);
1748 interfacePrivate
= (SCNetworkInterfacePrivateRef
)CFArrayGetValueAtIndex(matching_interfaces
, 0);
1749 CFRetain(interfacePrivate
);
1752 SCPrint(TRUE
, stderr
, CFSTR("more than one interface matches %@\n"), ifDevice
);
1753 if (matching_interfaces
!= NULL
) CFRelease(matching_interfaces
);
1754 _SCErrorSet(kSCStatusFailed
);
1757 CFRelease(matching_interfaces
);
1762 if (interfacePrivate
== NULL
) {
1764 * if device not present on this system
1766 interfacePrivate
= __SCNetworkInterfaceCreatePrivate(NULL
, NULL
, NULL
, NULL
);
1767 interfacePrivate
->entity_type
= ifType
;
1768 interfacePrivate
->entity_subtype
= ifSubType
;
1769 interfacePrivate
->entity_device
= (ifDevice
!= NULL
) ? CFStringCreateCopy(NULL
, ifDevice
) : NULL
;
1770 interfacePrivate
->entity_hardware
= CFDictionaryGetValue(interface_entity
, kSCPropNetInterfaceHardware
);
1772 if (CFEqual(ifType
, kSCValNetInterfaceTypeEthernet
)) {
1773 if ((interfacePrivate
->entity_hardware
!= NULL
) &&
1774 CFEqual(interfacePrivate
->entity_hardware
, kSCEntNetAirPort
)) {
1775 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeIEEE80211
;
1777 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
;
1779 } else if (CFEqual(ifType
, kSCValNetInterfaceTypeFireWire
)) {
1780 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeFireWire
;
1781 } else if (CFEqual(ifType
, kSCValNetInterfaceTypePPP
)) {
1782 if (CFEqual(ifSubType
, kSCValNetInterfaceSubTypePPPoE
)) {
1783 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
;
1784 } else if (CFEqual(ifSubType
, kSCValNetInterfaceSubTypePPPSerial
)) {
1785 if (CFStringHasPrefix(ifDevice
, CFSTR("irda"))) {
1786 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeIrDA
;
1787 } else if (CFStringHasPrefix(ifDevice
, CFSTR("Bluetooth"))) {
1788 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeBluetooth
;
1790 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeModem
;
1794 CFRelease(interfacePrivate
);
1795 interfacePrivate
= (SCNetworkInterfacePrivateRef
)kSCNetworkInterfaceIPv4
;
1796 CFRetain(interfacePrivate
);
1799 // unknown interface type
1800 CFRelease(interfacePrivate
);
1801 interfacePrivate
= NULL
;
1805 if ((interfacePrivate
!= NULL
) && (service
!= NULL
)) {
1806 interfacePrivate
->service
= service
;
1809 if (CFEqual(ifType
, kSCValNetInterfaceTypePPP
)) {
1810 SCNetworkInterfaceRef parent
;
1812 parent
= SCNetworkInterfaceCreateWithInterface((SCNetworkInterfaceRef
)interfacePrivate
,
1813 kSCNetworkInterfaceTypePPP
);
1814 CFRelease(interfacePrivate
);
1815 interfacePrivate
= (SCNetworkInterfacePrivateRef
)parent
;
1818 return (SCNetworkInterfaceRef
)interfacePrivate
;
1822 /* ---------- helper functions ---------- */
1826 findConfiguration(CFStringRef interface_type
)
1830 for (i
= 0; i
< sizeof(configurations
)/sizeof(configurations
[0]); i
++) {
1831 if (CFEqual(interface_type
, *configurations
[i
].interface_type
)) {
1841 copyConfigurationPaths(SCNetworkInterfacePrivateRef interfacePrivate
)
1843 CFMutableArrayRef array
= NULL
;
1844 CFIndex interfaceIndex
;
1846 SCNetworkServicePrivateRef servicePrivate
;
1848 interfaceIndex
= findConfiguration(interfacePrivate
->interface_type
);
1849 if (interfaceIndex
== kCFNotFound
) {
1850 // if unknown interface type
1854 servicePrivate
= (SCNetworkServicePrivateRef
)interfacePrivate
->service
;
1855 if (servicePrivate
== NULL
) {
1856 // if not associated with a service (yet)
1860 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1862 if (configurations
[interfaceIndex
].per_interface_config
) {
1868 * per-interface configuration preferences
1870 * 1. look for all sets which contain the associated service
1871 * 2. add a per-set path for the interface configuration for
1875 sets
= SCNetworkSetCopyAll(servicePrivate
->prefs
);
1876 n
= (sets
!= NULL
) ? CFArrayGetCount(sets
) : 0;
1878 for (i
= 0; i
< n
; i
++) {
1879 CFArrayRef services
;
1880 SCNetworkSetRef set
;
1882 set
= CFArrayGetValueAtIndex(sets
, i
);
1883 services
= SCNetworkSetCopyServices(set
);
1884 if (CFArrayContainsValue(services
,
1885 CFRangeMake(0, CFArrayGetCount(services
)),
1886 interfacePrivate
->service
)) {
1887 path
= SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL
, // allocator
1888 SCNetworkSetGetSetID(set
), // set
1889 interfacePrivate
->entity_device
, // service
1890 interfacePrivate
->entity_type
); // entity
1891 CFArrayAppendValue(array
, path
);
1894 CFRelease(services
);
1897 if (CFArrayGetCount(array
) == 0) {
1904 // per-service configuration preferences
1905 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1906 servicePrivate
->serviceID
, // service
1907 interfacePrivate
->entity_type
); // entity
1908 CFArrayAppendValue(array
, path
);
1916 /* ---------- SCNetworkInterface APIs ---------- */
1919 CFArrayRef
/* of SCNetworkInterfaceRef's */
1920 SCNetworkInterfaceCopyAll()
1922 CFMutableArrayRef all_interfaces
;
1923 static mach_port_t masterPort
= MACH_PORT_NULL
;
1924 CFDictionaryRef matching
;
1925 CFStringRef match_keys
[2];
1926 CFStringRef match_vals
[2];
1927 CFArrayRef new_interfaces
;
1929 if (masterPort
== MACH_PORT_NULL
) {
1932 kr
= IOMasterPort(MACH_PORT_NULL
, &masterPort
);
1933 if (kr
!= KERN_SUCCESS
) {
1938 all_interfaces
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1940 // get Ethernet, Firewire, and AirPort interfaces
1942 matching
= IOServiceMatching(kIONetworkInterfaceClass
);
1943 new_interfaces
= findMatchingInterfaces(masterPort
, matching
, processNetworkInterface
);
1944 if (new_interfaces
!= NULL
) {
1945 CFArrayAppendArray(all_interfaces
, new_interfaces
, CFRangeMake(0, CFArrayGetCount(new_interfaces
)));
1946 CFRelease(new_interfaces
);
1949 // get Modem interfaces
1951 match_keys
[0] = CFSTR(kIOProviderClassKey
);
1952 match_vals
[0] = CFSTR(kIOSerialBSDServiceValue
);
1954 match_keys
[1] = CFSTR(kIOSerialBSDTypeKey
);
1955 match_vals
[1] = CFSTR(kIOSerialBSDModemType
);
1957 matching
= CFDictionaryCreate(NULL
,
1958 (const void **)match_keys
,
1959 (const void **)match_vals
,
1960 sizeof(match_keys
)/sizeof(match_keys
[0]),
1961 &kCFTypeDictionaryKeyCallBacks
,
1962 &kCFTypeDictionaryValueCallBacks
);
1963 new_interfaces
= findMatchingInterfaces(masterPort
, matching
, processSerialInterface
);
1964 if (new_interfaces
!= NULL
) {
1965 CFArrayAppendArray(all_interfaces
, new_interfaces
, CFRangeMake(0, CFArrayGetCount(new_interfaces
)));
1966 CFRelease(new_interfaces
);
1969 // get serial (RS232) interfaces
1971 match_keys
[0] = CFSTR(kIOProviderClassKey
);
1972 match_vals
[0] = CFSTR(kIOSerialBSDServiceValue
);
1974 match_keys
[1] = CFSTR(kIOSerialBSDTypeKey
);
1975 match_vals
[1] = CFSTR(kIOSerialBSDRS232Type
);
1977 matching
= CFDictionaryCreate(NULL
,
1978 (const void **)match_keys
,
1979 (const void **)match_vals
,
1980 sizeof(match_keys
)/sizeof(match_keys
[0]),
1981 &kCFTypeDictionaryKeyCallBacks
,
1982 &kCFTypeDictionaryValueCallBacks
);
1983 new_interfaces
= findMatchingInterfaces(masterPort
, matching
, processSerialInterface
);
1984 if (new_interfaces
!= NULL
) {
1985 CFArrayAppendArray(all_interfaces
, new_interfaces
, CFRangeMake(0, CFArrayGetCount(new_interfaces
)));
1986 CFRelease(new_interfaces
);
1989 new_interfaces
= findBondInterfaces(NULL
);
1990 if (new_interfaces
!= NULL
) {
1991 CFArrayAppendArray(all_interfaces
, new_interfaces
, CFRangeMake(0, CFArrayGetCount(new_interfaces
)));
1992 CFRelease(new_interfaces
);
1995 new_interfaces
= findVLANInterfaces(NULL
);
1996 if (new_interfaces
!= NULL
) {
1997 CFArrayAppendArray(all_interfaces
, new_interfaces
, CFRangeMake(0, CFArrayGetCount(new_interfaces
)));
1998 CFRelease(new_interfaces
);
2001 sort_interfaces(all_interfaces
);
2003 return all_interfaces
;
2007 CFArrayRef
/* of kSCNetworkInterfaceTypeXXX CFStringRef's */
2008 SCNetworkInterfaceGetSupportedInterfaceTypes(SCNetworkInterfaceRef interface
)
2011 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2013 if (interfacePrivate
->supported_interface_types
!= NULL
) {
2017 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
2018 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
2020 i
= findConfiguration(interfacePrivate
->interface_type
);
2021 if (i
!= kCFNotFound
) {
2022 if (configurations
[i
].supported_interfaces
!= doNone
) {
2023 interfacePrivate
->supported_interface_types
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
2024 if (configurations
[i
].supported_interfaces
& do6to4
) {
2025 CFArrayAppendValue(interfacePrivate
->supported_interface_types
, kSCNetworkInterfaceType6to4
);
2027 if (configurations
[i
].supported_interfaces
& doL2TP
) {
2028 CFArrayAppendValue(interfacePrivate
->supported_interface_types
, kSCNetworkInterfaceTypeL2TP
);
2030 if (configurations
[i
].supported_interfaces
& doPPP
) {
2031 CFArrayAppendValue(interfacePrivate
->supported_interface_types
, kSCNetworkInterfaceTypePPP
);
2033 if (configurations
[i
].supported_interfaces
& doPPTP
) {
2034 CFArrayAppendValue(interfacePrivate
->supported_interface_types
, kSCNetworkInterfaceTypePPTP
);
2041 return interfacePrivate
->supported_interface_types
;
2045 CFArrayRef
/* of kSCNetworkProtocolTypeXXX CFStringRef's */
2046 SCNetworkInterfaceGetSupportedProtocolTypes(SCNetworkInterfaceRef interface
)
2049 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2051 if (interfacePrivate
->supported_protocol_types
!= NULL
) {
2055 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
2056 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
2058 i
= findConfiguration(interfacePrivate
->interface_type
);
2059 if (i
!= kCFNotFound
) {
2060 if (configurations
[i
].supported_protocols
!= doNone
) {
2061 interfacePrivate
->supported_protocol_types
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
2062 if (configurations
[i
].supported_protocols
& doAppleTalk
) {
2063 CFArrayAppendValue(interfacePrivate
->supported_protocol_types
, kSCNetworkProtocolTypeAppleTalk
);
2065 if (configurations
[i
].supported_protocols
& doDNS
) {
2066 CFArrayAppendValue(interfacePrivate
->supported_protocol_types
, kSCNetworkProtocolTypeDNS
);
2068 if (configurations
[i
].supported_protocols
& doIPv4
) {
2069 CFArrayAppendValue(interfacePrivate
->supported_protocol_types
, kSCNetworkProtocolTypeIPv4
);
2071 if (configurations
[i
].supported_protocols
& doIPv6
) {
2072 CFArrayAppendValue(interfacePrivate
->supported_protocol_types
, kSCNetworkProtocolTypeIPv6
);
2074 if (configurations
[i
].supported_protocols
& doProxies
) {
2075 CFArrayAppendValue(interfacePrivate
->supported_protocol_types
, kSCNetworkProtocolTypeProxies
);
2082 return interfacePrivate
->supported_protocol_types
;
2086 SCNetworkInterfaceRef
2087 SCNetworkInterfaceCreateWithInterface(SCNetworkInterfaceRef child
, CFStringRef interfaceType
)
2089 SCNetworkInterfacePrivateRef childPrivate
= (SCNetworkInterfacePrivateRef
)child
;
2091 SCNetworkInterfacePrivateRef parentPrivate
;
2093 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
2094 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
2096 childIndex
= findConfiguration(childPrivate
->interface_type
);
2098 parentPrivate
= __SCNetworkInterfaceCreatePrivate(NULL
, child
, childPrivate
->service
, NULL
);
2099 if (parentPrivate
== NULL
) {
2100 _SCErrorSet(kSCStatusFailed
);
2104 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
)) {
2105 parentPrivate
->interface_type
= kSCNetworkInterfaceTypePPP
;
2106 parentPrivate
->entity_type
= kSCEntNetPPP
;
2109 if (childIndex
!= kCFNotFound
) {
2110 if (configurations
[childIndex
].ppp_subtype
!= NULL
) {
2111 parentPrivate
->entity_subtype
= *configurations
[childIndex
].ppp_subtype
;
2113 // sorry, the child interface does not support PPP
2117 // if the child's interface type not known, use the child entities "Type"
2118 parentPrivate
->entity_subtype
= childPrivate
->entity_type
;
2121 if (childPrivate
->entity_device
!= NULL
) {
2122 parentPrivate
->entity_device
= CFStringCreateCopy(NULL
, childPrivate
->entity_device
);
2124 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeL2TP
)) {
2125 if ((childIndex
== kCFNotFound
) ||
2126 ((configurations
[childIndex
].supported_interfaces
& doL2TP
) != doL2TP
)) {
2127 // if the child interface does not support L2TP
2130 parentPrivate
->interface_type
= kSCNetworkInterfaceTypeL2TP
;
2131 parentPrivate
->entity_type
= kSCValNetInterfaceSubTypeL2TP
; // interface config goes into "L2TP"
2132 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPTP
)) {
2133 if ((childIndex
== kCFNotFound
) ||
2134 ((configurations
[childIndex
].supported_interfaces
& doPPTP
) != doPPTP
)) {
2135 // if the child interface does not support PPTP
2138 parentPrivate
->interface_type
= kSCNetworkInterfaceTypePPTP
;
2139 parentPrivate
->entity_type
= kSCValNetInterfaceSubTypePPTP
; // interface config goes into "PPTP"
2140 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceType6to4
)) {
2141 if ((childIndex
== kCFNotFound
) ||
2142 ((configurations
[childIndex
].supported_interfaces
& do6to4
) != do6to4
)) {
2143 // if the child interface does not support 6to4
2147 parentPrivate
->interface_type
= kSCNetworkInterfaceType6to4
;
2148 parentPrivate
->entity_type
= kSCEntNet6to4
;
2149 parentPrivate
->entity_device
= CFRetain(CFSTR("stf0"));
2150 CFRetain(parentPrivate
->entity_device
);
2152 // unknown interface type
2156 parentPrivate
->entity_hardware
= childPrivate
->entity_hardware
;
2157 parentPrivate
->sort_order
= childPrivate
->sort_order
;
2159 return (SCNetworkInterfaceRef
)parentPrivate
;
2163 CFRelease(parentPrivate
);
2164 _SCErrorSet(kSCStatusInvalidArgument
);
2169 static CFDictionaryRef
2170 __SCNetworkInterfaceGetConfiguration(SCNetworkInterfaceRef interface
, Boolean okToHold
)
2172 CFDictionaryRef config
= NULL
;
2173 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2176 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
2177 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
2179 paths
= copyConfigurationPaths(interfacePrivate
);
2180 if (paths
!= NULL
) {
2182 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)interfacePrivate
->service
;
2184 path
= CFArrayGetValueAtIndex(paths
, 0);
2185 config
= __getPrefsConfiguration(servicePrivate
->prefs
, path
);
2188 } else if (okToHold
) {
2189 config
= interfacePrivate
->unsaved
;
2197 SCNetworkInterfaceGetConfiguration(SCNetworkInterfaceRef interface
)
2199 return __SCNetworkInterfaceGetConfiguration(interface
, FALSE
);
2204 SCNetworkInterfaceGetBSDName(SCNetworkInterfaceRef interface
)
2206 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2208 if (interfacePrivate
->interface
!= NULL
) {
2212 return interfacePrivate
->entity_device
;
2217 SCNetworkInterfaceGetHardwareAddressString(SCNetworkInterfaceRef interface
)
2219 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2221 return interfacePrivate
->address
;
2224 SCNetworkInterfaceRef
2225 SCNetworkInterfaceGetInterface(SCNetworkInterfaceRef interface
)
2227 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2229 return interfacePrivate
->interface
;
2234 SCNetworkInterfaceGetInterfaceType(SCNetworkInterfaceRef interface
)
2236 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2238 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
2239 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
2241 return interfacePrivate
->interface_type
;
2246 SCNetworkInterfaceGetLocalizedDisplayName(SCNetworkInterfaceRef interface
)
2248 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2250 if (interfacePrivate
->localized_name
== NULL
) {
2251 CFStringRef child
= NULL
;
2252 CFMutableStringRef local
= NULL
;
2254 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
); /* initialize runtime */
2256 if (interfacePrivate
->interface
!= NULL
) {
2257 child
= SCNetworkInterfaceGetLocalizedDisplayName(interfacePrivate
->interface
);
2260 if (interfacePrivate
->localized_key
!= NULL
) {
2263 fmt
= CFBundleCopyLocalizedString(bundle
,
2264 interfacePrivate
->localized_key
,
2265 interfacePrivate
->localized_key
,
2266 NETWORKINTERFACE_LOCALIZATIONS
);
2268 local
= CFStringCreateMutable(NULL
, 0);
2269 CFStringAppendFormat(local
,
2272 interfacePrivate
->localized_arg1
,
2273 interfacePrivate
->localized_arg2
);
2278 if (local
== NULL
) {
2279 // create (non-)localized name based on the interface type
2280 local
= CFStringCreateMutableCopy(NULL
, 0, interfacePrivate
->interface_type
);
2282 // ... and, if this is a leaf node, the interface device
2283 if ((interfacePrivate
->entity_device
!= NULL
) && (child
== NULL
)) {
2284 CFStringAppendFormat(local
, NULL
, CFSTR(" (%@)"), interfacePrivate
->entity_device
);
2288 if (child
== NULL
) {
2289 // no child, show just this interfaces localized name
2290 interfacePrivate
->localized_name
= CFStringCreateCopy(NULL
, local
);
2292 // show localized interface name layered over child
2293 interfacePrivate
->localized_name
= CFStringCreateWithFormat(NULL
,
2302 return interfacePrivate
->localized_name
;
2307 SCNetworkInterfaceGetTypeID(void)
2309 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
); /* initialize runtime */
2310 return __kSCNetworkInterfaceTypeID
;
2314 __private_extern__ Boolean
2315 __SCNetworkInterfaceSetConfiguration(SCNetworkInterfaceRef interface
, CFDictionaryRef config
, Boolean okToHold
)
2317 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2321 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
2322 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
2324 paths
= copyConfigurationPaths(interfacePrivate
);
2325 if (paths
!= NULL
) {
2328 SCPreferencesRef prefs
;
2329 SCNetworkServicePrivateRef servicePrivate
;
2331 servicePrivate
= (SCNetworkServicePrivateRef
)interfacePrivate
->service
;
2332 prefs
= servicePrivate
->prefs
;
2334 n
= CFArrayGetCount(paths
);
2335 for (i
= 0; i
< n
; i
++) {
2338 path
= CFArrayGetValueAtIndex(paths
, i
);
2339 ok
= __setPrefsConfiguration(prefs
, path
, config
, FALSE
);
2346 } else if (okToHold
) {
2347 interfacePrivate
->unsaved
= config
;
2350 _SCErrorSet(kSCStatusNoKey
);
2358 SCNetworkInterfaceSetConfiguration(SCNetworkInterfaceRef interface
, CFDictionaryRef config
)
2360 return __SCNetworkInterfaceSetConfiguration(interface
, config
, FALSE
);
2364 /* ---------- SCNetworkInterface internal SPIs ---------- */
2367 __private_extern__ SCNetworkInterfacePrivateRef
2368 __SCNetworkInterfaceCreateCopy(CFAllocatorRef allocator
,
2369 SCNetworkInterfaceRef interface
,
2370 SCNetworkServiceRef service
)
2372 SCNetworkInterfacePrivateRef oldPrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2373 SCNetworkInterfacePrivateRef newPrivate
;
2375 newPrivate
= __SCNetworkInterfaceCreatePrivate(NULL
, NULL
, NULL
, NULL
);
2376 newPrivate
->interface_type
= CFRetain(oldPrivate
->interface_type
);
2377 if (oldPrivate
->interface
!= NULL
) {
2378 newPrivate
->interface
= (SCNetworkInterfaceRef
)__SCNetworkInterfaceCreateCopy(NULL
, // allocator
2379 oldPrivate
->interface
, // interface
2380 service
); // [new] service
2382 newPrivate
->localized_name
= (oldPrivate
->localized_name
!= NULL
) ? CFRetain(oldPrivate
->localized_name
) : NULL
;
2383 newPrivate
->service
= service
;
2384 newPrivate
->unsaved
= (oldPrivate
->unsaved
!= NULL
) ? CFRetain(oldPrivate
->unsaved
) : NULL
;
2385 newPrivate
->entity_device
= (oldPrivate
->entity_device
!= NULL
) ? CFRetain(oldPrivate
->entity_device
) : NULL
;
2386 newPrivate
->entity_hardware
= CFRetain(oldPrivate
->entity_hardware
);
2387 newPrivate
->entity_type
= oldPrivate
->entity_type
;
2388 newPrivate
->entity_subtype
= oldPrivate
->entity_subtype
;
2389 if (oldPrivate
->supported_interface_types
!= NULL
) {
2390 newPrivate
->supported_interface_types
= CFArrayCreateMutableCopy(NULL
, 0, oldPrivate
->supported_interface_types
);
2392 if (oldPrivate
->supported_protocol_types
!= NULL
) {
2393 newPrivate
->supported_protocol_types
= CFArrayCreateMutableCopy(NULL
, 0, oldPrivate
->supported_protocol_types
);
2395 newPrivate
->address
= (oldPrivate
->address
!= NULL
) ? CFRetain(oldPrivate
->address
) : NULL
;
2396 newPrivate
->builtin
= oldPrivate
->builtin
;
2397 newPrivate
->path
= (oldPrivate
->path
!= NULL
) ? CFRetain(oldPrivate
->path
) : NULL
;
2398 newPrivate
->location
= (oldPrivate
->location
!= NULL
) ? CFRetain(oldPrivate
->location
) : NULL
;
2399 newPrivate
->supportsDeviceOnHold
= oldPrivate
->supportsDeviceOnHold
;
2400 newPrivate
->supportsBond
= oldPrivate
->supportsBond
;
2401 newPrivate
->supportsVLAN
= oldPrivate
->supportsVLAN
;
2402 newPrivate
->sort_order
= oldPrivate
->sort_order
;
2408 __private_extern__ CFArrayRef
2409 __SCNetworkInterfaceCopyDeepConfiguration(SCNetworkInterfaceRef interface
)
2411 CFDictionaryRef config
;
2412 CFMutableArrayRef configs
;
2414 configs
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
2416 while (interface
!= NULL
) {
2417 config
= __SCNetworkInterfaceGetConfiguration(interface
, TRUE
);
2418 CFArrayAppendValue(configs
,
2419 (config
!= NULL
) ? config
: (CFDictionaryRef
)kCFNull
);
2420 interface
= SCNetworkInterfaceGetInterface(interface
);
2427 __private_extern__
void
2428 __SCNetworkInterfaceSetDeepConfiguration(SCNetworkInterfaceRef interface
, CFArrayRef configs
)
2432 for (i
= 0; interface
!= NULL
; i
++) {
2433 CFDictionaryRef config
;
2435 config
= (configs
!= NULL
) ? CFArrayGetValueAtIndex(configs
, i
) : NULL
;
2436 if (!isA_CFDictionary(config
) || (CFDictionaryGetCount(config
) == 0)) {
2440 (void) __SCNetworkInterfaceSetConfiguration(interface
, config
, TRUE
);
2441 interface
= SCNetworkInterfaceGetInterface(interface
);