2 * Copyright (c) 2004-2013 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 * Modification History
27 * May 13, 2004 Allan Nathanson <ajn@apple.com>
29 * which includes code originally authored by
30 * Robert Ulrich <rulrich@apple.com>
31 * Elizabeth Douglas <elizabeth@apple.com>
32 * Quinn <eskimo1@apple.com>
36 #include <Availability.h>
37 #include <TargetConditionals.h>
38 #include <CoreFoundation/CoreFoundation.h>
39 #include <CoreFoundation/CFRuntime.h>
40 #include <SystemConfiguration/SystemConfiguration.h>
41 #include "SCNetworkConfigurationInternal.h"
42 #include <SystemConfiguration/SCValidation.h>
43 #include <SystemConfiguration/SCPrivate.h>
44 #include "SCPreferencesInternal.h"
45 #include "SCHelper_client.h"
48 #include <EAP8021X/EAPClientProperties.h>
49 #else // !TARGET_OS_IPHONE
50 #ifndef kEAPClientPropUserName
51 #define kEAPClientPropUserName CFSTR("UserName")
53 #ifndef kEAPClientPropUserPasswordKeychainItemID
54 #define kEAPClientPropUserPasswordKeychainItemID CFSTR("UserPasswordKeychainItemID")
56 #endif // !TARGET_OS_IPHONE
58 #include <IOKit/IOKitLib.h>
59 #include <IOKit/IOCFBundle.h>
60 #include <IOKit/IOBSD.h>
61 #include <IOKit/network/IONetworkController.h>
62 #include <IOKit/network/IONetworkInterface.h>
63 #include <IOKit/network/IOEthernetInterface.h> // for kIOEthernetInterfaceClass
64 #include <IOKit/serial/IOSerialKeys.h>
65 #include <IOKit/storage/IOStorageDeviceCharacteristics.h>
66 #if !TARGET_IPHONE_SIMULATOR
67 #include <IOKit/usb/USB.h>
68 #endif // !TARGET_IPHONE_SIMULATOR
70 #include "dy_framework.h"
72 #ifndef kIODeviceSupportsHoldKey
73 #define kIODeviceSupportsHoldKey "V92Modem"
76 #ifndef kPCIThunderboltString
77 #define kPCIThunderboltString "PCI-Thunderbolt"
80 #ifndef kIOUserEthernetInterfaceRoleKey
81 #define kIOUserEthernetInterfaceRoleKey "InterfaceRole"
85 #include <mach/mach.h>
87 #include <net/if_types.h>
88 #include <net/route.h>
89 #include <sys/param.h>
90 #include <sys/types.h>
91 #include <sys/socket.h>
93 #include <sys/sysctl.h>
95 #include <NSSystemDirectories.h>
98 static CFStringRef
copy_interface_string (CFBundleRef bundle
, CFStringRef key
, Boolean localized
);
99 static CFStringRef
__SCNetworkInterfaceCopyDescription (CFTypeRef cf
);
100 static void __SCNetworkInterfaceDeallocate (CFTypeRef cf
);
101 static Boolean
__SCNetworkInterfaceEqual (CFTypeRef cf1
, CFTypeRef cf2
);
102 static CFHashCode
__SCNetworkInterfaceHash (CFTypeRef cf
);
121 kSortBluetoothPAN_GN
,
122 kSortBluetoothPAN_NAP
,
132 const CFStringRef kSCNetworkInterfaceType6to4
= CFSTR("6to4");
133 const CFStringRef kSCNetworkInterfaceTypeBluetooth
= CFSTR("Bluetooth");
134 const CFStringRef kSCNetworkInterfaceTypeBond
= CFSTR("Bond");
135 const CFStringRef kSCNetworkInterfaceTypeBridge
= CFSTR("Bridge");
136 const CFStringRef kSCNetworkInterfaceTypeEthernet
= CFSTR("Ethernet");
137 const CFStringRef kSCNetworkInterfaceTypeFireWire
= CFSTR("FireWire");
138 const CFStringRef kSCNetworkInterfaceTypeIEEE80211
= CFSTR("IEEE80211"); // IEEE 802.11, AirPort
139 const CFStringRef kSCNetworkInterfaceTypeIPSec
= CFSTR("IPSec");
140 const CFStringRef kSCNetworkInterfaceTypeIrDA
= CFSTR("IrDA");
141 const CFStringRef kSCNetworkInterfaceTypeL2TP
= CFSTR("L2TP");
142 const CFStringRef kSCNetworkInterfaceTypeLoopback
= CFSTR("Loopback");
143 const CFStringRef kSCNetworkInterfaceTypeModem
= CFSTR("Modem");
144 const CFStringRef kSCNetworkInterfaceTypePPP
= CFSTR("PPP");
145 const CFStringRef kSCNetworkInterfaceTypePPTP
= CFSTR("PPTP");
146 const CFStringRef kSCNetworkInterfaceTypeSerial
= CFSTR("Serial");
147 const CFStringRef kSCNetworkInterfaceTypeVLAN
= CFSTR("VLAN");
148 const CFStringRef kSCNetworkInterfaceTypeVPN
= CFSTR("VPN");
149 const CFStringRef kSCNetworkInterfaceTypeWWAN
= CFSTR("WWAN");
151 const CFStringRef kSCNetworkInterfaceTypeIPv4
= CFSTR("IPv4");
153 static SCNetworkInterfacePrivate __kSCNetworkInterfaceIPv4
= {
154 INIT_CFRUNTIME_BASE(), // cfBase
155 NULL
, // interface type
157 NULL
, // localized name
158 NULL
, // localization key
159 NULL
, // localization arg1
160 NULL
, // localization arg2
161 NULL
, // [layered] interface
166 NULL
, // entity_device
167 NULL
, // entity_device_unique
169 NULL
, // entity_subtype
170 NULL
, // supported_interface_types
171 NULL
, // supported_protocol_types
173 NULL
, // addressString
175 NULL
, // configurationAction
185 { NULL
, 0, 0 }, // usb { name, vid, pid }
186 kSortUnknown
, // sort_order
187 FALSE
, // supportsBond
188 { NULL
, NULL
, NULL
}, // bond { interfaces, mode, options }
189 FALSE
, // supportsBridge
190 { NULL
, NULL
}, // bridge { interfaces, options }
191 FALSE
, // supportsVLAN
192 { NULL
, NULL
, NULL
} // vlan { interface, tag, options }
195 const SCNetworkInterfaceRef kSCNetworkInterfaceIPv4
= (SCNetworkInterfaceRef
)&__kSCNetworkInterfaceIPv4
;
197 static SCNetworkInterfacePrivate __kSCNetworkInterfaceLoopback
= {
198 INIT_CFRUNTIME_BASE(), // cfBase
199 NULL
, // interface type
201 NULL
, // localized name
202 NULL
, // localization key
203 NULL
, // localization arg1
204 NULL
, // localization arg2
205 NULL
, // [layered] interface
210 NULL
, // entity_device
211 NULL
, // entity_device_unique
213 NULL
, // entity_subtype
214 NULL
, // supported_interface_types
215 NULL
, // supported_protocol_types
217 NULL
, // addressString
219 NULL
, // configurationAction
229 { NULL
, 0, 0 }, // usb { name, vid, pid }
230 kSortUnknown
, // sort_order
231 FALSE
, // supportsBond
232 { NULL
, NULL
, NULL
}, // bond { interfaces, mode, options }
233 FALSE
, // supportsBridge
234 { NULL
, NULL
}, // bridge { interfaces, options }
235 FALSE
, // supportsVLAN
236 { NULL
, NULL
, NULL
} // vlan { interface, tag, options }
239 const SCNetworkInterfaceRef kSCNetworkInterfaceLoopback
= (SCNetworkInterfaceRef
)&__kSCNetworkInterfaceLoopback
;
241 static CFMutableSetRef vendor_interface_types
= NULL
;
244 #pragma mark SCNetworkInterface configuration details
253 #define doOverIP do6to4|doL2TP|doPPTP|doIPSec
258 #define doProxies 1<<4
259 #if !TARGET_OS_IPHONE
261 #else // !TARGET_OS_IPHONE
263 #endif // !TARGET_OS_IPHONE
265 static const struct {
266 const CFStringRef
*interface_type
;
267 const CFStringRef
*entity_hardware
;
268 Boolean per_interface_config
;
269 uint32_t supported_interfaces
;
270 const CFStringRef
*ppp_subtype
;
271 uint32_t supported_protocols
;
272 } configurations
[] = {
273 // interface type entity_hardware if config? interface types PPP sub-type interface protocols
274 // ===================================== ================= ========== =============== ======================================= =========================================
275 { &kSCNetworkInterfaceType6to4
, &kSCEntNet6to4
, FALSE
, doNone
, NULL
, doIPv6
},
276 { &kSCNetworkInterfaceTypeBluetooth
, &kSCEntNetModem
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypePPPSerial
, doNone
},
277 { &kSCNetworkInterfaceTypeBond
, &kSCEntNetEthernet
, TRUE
, doNone
, NULL
, doDNS
|doIPv4
|doIPv6
|doProxies
|doSMB
},
278 { &kSCNetworkInterfaceTypeBridge
, &kSCEntNetEthernet
, TRUE
, doNone
, NULL
, doDNS
|doIPv4
|doIPv6
|doProxies
|doSMB
},
279 { &kSCNetworkInterfaceTypeEthernet
, &kSCEntNetEthernet
, TRUE
, doPPP
, &kSCValNetInterfaceSubTypePPPoE
, doDNS
|doIPv4
|doIPv6
|doProxies
|doSMB
},
280 { &kSCNetworkInterfaceTypeFireWire
, &kSCEntNetFireWire
, TRUE
, doNone
, NULL
, doDNS
|doIPv4
|doIPv6
|doProxies
|doSMB
},
281 { &kSCNetworkInterfaceTypeIEEE80211
, &kSCEntNetAirPort
, TRUE
, doPPP
, &kSCValNetInterfaceSubTypePPPoE
, doDNS
|doIPv4
|doIPv6
|doProxies
|doSMB
},
282 { &kSCNetworkInterfaceTypeIPSec
, &kSCEntNetIPSec
, FALSE
, doNone
, NULL
, doDNS
|doIPv4
|doIPv6
|doProxies
|doSMB
},
283 { &kSCNetworkInterfaceTypeIrDA
, &kSCEntNetModem
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypePPPSerial
, doNone
},
284 { &kSCNetworkInterfaceTypeL2TP
, NULL
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypeL2TP
, doNone
},
285 { &kSCNetworkInterfaceTypeModem
, &kSCEntNetModem
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypePPPSerial
, doNone
},
286 { &kSCNetworkInterfaceTypePPP
, &kSCEntNetPPP
, FALSE
, doNone
, NULL
, doDNS
|doIPv4
|doIPv6
|doProxies
|doSMB
},
287 { &kSCNetworkInterfaceTypePPTP
, NULL
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypePPTP
, doNone
},
288 { &kSCNetworkInterfaceTypeSerial
, &kSCEntNetModem
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypePPPSerial
, doNone
},
289 { &kSCNetworkInterfaceTypeVLAN
, &kSCEntNetEthernet
, TRUE
, doNone
, NULL
, doDNS
|doIPv4
|doIPv6
|doProxies
|doSMB
},
290 { &kSCNetworkInterfaceTypeVPN
, &kSCEntNetVPN
, FALSE
, doNone
, NULL
, doDNS
|doIPv4
|doIPv6
|doProxies
|doSMB
},
291 { &kSCNetworkInterfaceTypeWWAN
, &kSCEntNetModem
, FALSE
, doPPP
, &kSCValNetInterfaceSubTypePPPSerial
, doNone
},
292 // ===================================== ================= ========== =============== ======================================= =========================================
293 { &kSCNetworkInterfaceTypeLoopback
, NULL
, TRUE
, doNone
, NULL
, doIPv4
|doIPv6
},
294 // ===================================== ================= ========== =============== ======================================= =========================================
295 { &kSCNetworkInterfaceTypeIPv4
, NULL
, FALSE
, doOverIP
, NULL
, doNone
}
299 #define NETWORKINTERFACE_LOCALIZATIONS CFSTR("NetworkInterface")
300 static CFBundleRef bundle
= NULL
;
303 static CFTypeID __kSCNetworkInterfaceTypeID
= _kCFRuntimeNotATypeID
;
306 static const CFRuntimeClass __SCNetworkInterfaceClass
= {
308 "SCNetworkInterface", // className
311 __SCNetworkInterfaceDeallocate
, // dealloc
312 __SCNetworkInterfaceEqual
, // equal
313 __SCNetworkInterfaceHash
, // hash
314 NULL
, // copyFormattingDesc
315 __SCNetworkInterfaceCopyDescription
// copyDebugDesc
319 static pthread_once_t initialized
= PTHREAD_ONCE_INIT
;
320 static pthread_once_t iokit_quiet
= PTHREAD_ONCE_INIT
;
323 static mach_port_t masterPort
= MACH_PORT_NULL
;
327 __SCNetworkInterfaceCopyDescription(CFTypeRef cf
)
329 CFAllocatorRef allocator
= CFGetAllocator(cf
);
330 CFMutableStringRef result
;
331 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)cf
;
333 result
= CFStringCreateMutable(allocator
, 0);
334 CFStringAppendFormat(result
, NULL
, CFSTR("<SCNetworkInterface %p [%p]> {"), cf
, allocator
);
335 CFStringAppendFormat(result
, NULL
, CFSTR("type = %@"), interfacePrivate
->interface_type
);
336 CFStringAppendFormat(result
, NULL
, CFSTR(", entity_device = %@"), interfacePrivate
->entity_device
);
337 if (interfacePrivate
->entity_device_unique
!= NULL
) {
338 CFStringAppendFormat(result
, NULL
, CFSTR("+%@"), interfacePrivate
->entity_device_unique
);
340 CFStringAppendFormat(result
, NULL
, CFSTR(", entity_type = %@"), interfacePrivate
->entity_type
);
341 if (interfacePrivate
->entity_subtype
!= NULL
) {
342 CFStringAppendFormat(result
, NULL
, CFSTR(" / %@"), interfacePrivate
->entity_subtype
);
344 if (interfacePrivate
->name
!= NULL
) {
345 CFStringAppendFormat(result
, NULL
, CFSTR(", name = %@"), interfacePrivate
->name
);
347 if (interfacePrivate
->localized_name
!= NULL
) {
348 CFStringAppendFormat(result
, NULL
, CFSTR(", name(l) = %@"), interfacePrivate
->localized_name
);
350 if (interfacePrivate
->localized_key
!= NULL
) {
351 CFStringAppendFormat(result
, NULL
, CFSTR(", name(k) = \"%@\""), interfacePrivate
->localized_key
);
352 if (interfacePrivate
->localized_arg1
!= NULL
) {
353 CFStringAppendFormat(result
, NULL
, CFSTR("+\"%@\""), interfacePrivate
->localized_arg1
);
355 if (interfacePrivate
->localized_arg2
!= NULL
) {
356 CFStringAppendFormat(result
, NULL
, CFSTR("+\"%@\""), interfacePrivate
->localized_arg2
);
360 if (interfacePrivate
->address
!= NULL
) {
365 CFStringAppendFormat(result
, NULL
, CFSTR(", address = 0x"));
367 data
= CFDataGetBytePtr(interfacePrivate
->address
);
368 dataLen
= CFDataGetLength(interfacePrivate
->address
);
369 for (i
= 0; i
< dataLen
; i
++) {
370 CFStringAppendFormat(result
, NULL
, CFSTR("%02x"), data
[i
]);
373 CFStringAppendFormat(result
, NULL
, CFSTR(", builtin = %s"), interfacePrivate
->builtin
? "TRUE" : "FALSE");
374 if (interfacePrivate
->hidden
) {
375 CFStringAppendFormat(result
, NULL
, CFSTR(", hidden = TRUE"));
377 if (interfacePrivate
->modemIsV92
) {
378 CFStringAppendFormat(result
, NULL
, CFSTR(", v.92"));
380 if (interfacePrivate
->location
!= NULL
) {
381 CFStringAppendFormat(result
, NULL
, CFSTR(", location = %@"), interfacePrivate
->location
);
383 if (interfacePrivate
->path
!= NULL
) {
384 CFStringAppendFormat(result
, NULL
, CFSTR(", path = %@"), interfacePrivate
->path
);
386 if (interfacePrivate
->entryID
!= 0) {
387 CFStringAppendFormat(result
, NULL
, CFSTR(", entryID = 0x%llx"), interfacePrivate
->entryID
);
389 if (interfacePrivate
->type
!= NULL
) {
390 CFStringAppendFormat(result
, NULL
, CFSTR(", type = %@"), interfacePrivate
->type
);
392 if (interfacePrivate
->unit
!= NULL
) {
393 CFStringAppendFormat(result
, NULL
, CFSTR(", unit = %@"), interfacePrivate
->unit
);
395 if ((interfacePrivate
->usb
.vid
!= NULL
) || (interfacePrivate
->usb
.pid
!= NULL
)) {
399 if (!isA_CFNumber(interfacePrivate
->usb
.pid
) ||
400 !CFNumberGetValue(interfacePrivate
->usb
.pid
, kCFNumberIntType
, &pid
)) {
403 if (!isA_CFNumber(interfacePrivate
->usb
.vid
) ||
404 !CFNumberGetValue(interfacePrivate
->usb
.vid
, kCFNumberIntType
, &vid
)) {
408 if (interfacePrivate
->usb
.name
!= NULL
) {
409 CFStringAppendFormat(result
, NULL
, CFSTR(", USB name = %@"),
410 interfacePrivate
->usb
.name
);
413 CFStringAppendFormat(result
, NULL
, CFSTR(", USB vid/pid = 0x%0x/0x%0x"),
417 if (interfacePrivate
->configurationAction
!= NULL
) {
418 CFStringAppendFormat(result
, NULL
, CFSTR(", action = %@"), interfacePrivate
->configurationAction
);
420 if (interfacePrivate
->overrides
!= NULL
) {
421 CFStringAppendFormat(result
, NULL
, CFSTR(", overrides = %p"), interfacePrivate
->overrides
);
423 CFStringAppendFormat(result
, NULL
, CFSTR(", order = %d"), interfacePrivate
->sort_order
);
424 if (interfacePrivate
->prefs
!= NULL
) {
425 CFStringAppendFormat(result
, NULL
, CFSTR(", prefs = %p"), interfacePrivate
->prefs
);
427 if (interfacePrivate
->serviceID
!= NULL
) {
428 CFStringAppendFormat(result
, NULL
, CFSTR(", service = %@"), interfacePrivate
->serviceID
);
430 if (interfacePrivate
->interface
!= NULL
) {
431 CFStringAppendFormat(result
, NULL
, CFSTR(", interface = %@"), interfacePrivate
->interface
);
433 if (interfacePrivate
->unsaved
!= NULL
) {
434 CFStringAppendFormat(result
, NULL
, CFSTR(", unsaved = %@"), interfacePrivate
->unsaved
);
437 if (interfacePrivate
->bond
.interfaces
!= NULL
) {
441 n
= CFArrayGetCount(interfacePrivate
->bond
.interfaces
);
442 for (i
= 0; i
< n
; i
++) {
443 SCNetworkInterfaceRef member
;
445 member
= CFArrayGetValueAtIndex(interfacePrivate
->bond
.interfaces
, i
);
446 CFStringAppendFormat(result
, NULL
,
448 (i
== 0) ? ", interfaces = " : ",",
449 SCNetworkInterfaceGetBSDName(member
));
452 if (interfacePrivate
->bond
.mode
!= NULL
) {
453 CFStringAppendFormat(result
, NULL
, CFSTR(", mode = %@"), interfacePrivate
->bond
.mode
);
455 if (interfacePrivate
->bond
.options
!= NULL
) {
456 CFStringAppendFormat(result
, NULL
, CFSTR(", options = %@"), interfacePrivate
->bond
.options
);
459 if (interfacePrivate
->bridge
.interfaces
!= NULL
) {
463 n
= CFArrayGetCount(interfacePrivate
->bridge
.interfaces
);
464 for (i
= 0; i
< n
; i
++) {
465 SCNetworkInterfaceRef member
;
467 member
= CFArrayGetValueAtIndex(interfacePrivate
->bridge
.interfaces
, i
);
468 CFStringAppendFormat(result
, NULL
,
470 (i
== 0) ? ", interfaces = " : ",",
471 SCNetworkInterfaceGetBSDName(member
));
474 if (interfacePrivate
->bridge
.options
!= NULL
) {
475 CFStringAppendFormat(result
, NULL
, CFSTR(", options = %@"), interfacePrivate
->bridge
.options
);
478 if (interfacePrivate
->vlan
.interface
!= NULL
) {
479 CFStringAppendFormat(result
, NULL
,
480 CFSTR(", interface = %@"),
481 SCNetworkInterfaceGetBSDName(interfacePrivate
->vlan
.interface
));
483 if (interfacePrivate
->vlan
.tag
!= NULL
) {
484 CFStringAppendFormat(result
, NULL
, CFSTR(", tag = %@"), interfacePrivate
->vlan
.tag
);
486 if (interfacePrivate
->vlan
.options
!= NULL
) {
487 CFStringAppendFormat(result
, NULL
, CFSTR(", options = %@"), interfacePrivate
->vlan
.options
);
490 CFStringAppendFormat(result
, NULL
, CFSTR("}"));
497 __SCNetworkInterfaceDeallocate(CFTypeRef cf
)
499 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)cf
;
501 /* release resources */
503 if (interfacePrivate
->name
!= NULL
)
504 CFRelease(interfacePrivate
->name
);
506 if (interfacePrivate
->localized_name
!= NULL
)
507 CFRelease(interfacePrivate
->localized_name
);
509 if (interfacePrivate
->localized_arg1
!= NULL
)
510 CFRelease(interfacePrivate
->localized_arg1
);
512 if (interfacePrivate
->localized_arg2
!= NULL
)
513 CFRelease(interfacePrivate
->localized_arg2
);
515 if (interfacePrivate
->interface
!= NULL
)
516 CFRelease(interfacePrivate
->interface
);
518 if (interfacePrivate
->prefs
!= NULL
)
519 CFRelease(interfacePrivate
->prefs
);
521 if (interfacePrivate
->store
!= NULL
)
522 CFRelease(interfacePrivate
->store
);
524 if (interfacePrivate
->serviceID
!= NULL
)
525 CFRelease(interfacePrivate
->serviceID
);
527 if (interfacePrivate
->unsaved
!= NULL
)
528 CFRelease(interfacePrivate
->unsaved
);
530 if (interfacePrivate
->entity_device
!= NULL
)
531 CFRelease(interfacePrivate
->entity_device
);
533 if (interfacePrivate
->entity_device_unique
!= NULL
)
534 CFRelease(interfacePrivate
->entity_device_unique
);
536 if (interfacePrivate
->supported_interface_types
!= NULL
)
537 CFRelease(interfacePrivate
->supported_interface_types
);
539 if (interfacePrivate
->supported_protocol_types
!= NULL
)
540 CFRelease(interfacePrivate
->supported_protocol_types
);
542 if (interfacePrivate
->address
!= NULL
)
543 CFRelease(interfacePrivate
->address
);
545 if (interfacePrivate
->addressString
!= NULL
)
546 CFRelease(interfacePrivate
->addressString
);
548 if (interfacePrivate
->configurationAction
!= NULL
)
549 CFRelease(interfacePrivate
->configurationAction
);
551 if (interfacePrivate
->location
!= NULL
)
552 CFRelease(interfacePrivate
->location
);
554 if (interfacePrivate
->path
!= NULL
)
555 CFRelease(interfacePrivate
->path
);
557 if (interfacePrivate
->overrides
!= NULL
)
558 CFRelease(interfacePrivate
->overrides
);
560 if (interfacePrivate
->prefix
!= NULL
)
561 CFRelease(interfacePrivate
->prefix
);
563 if (interfacePrivate
->type
!= NULL
)
564 CFRelease(interfacePrivate
->type
);
566 if (interfacePrivate
->unit
!= NULL
)
567 CFRelease(interfacePrivate
->unit
);
569 if (interfacePrivate
->usb
.name
!= NULL
)
570 CFRelease(interfacePrivate
->usb
.name
);
572 if (interfacePrivate
->usb
.pid
!= NULL
)
573 CFRelease(interfacePrivate
->usb
.pid
);
575 if (interfacePrivate
->usb
.vid
!= NULL
)
576 CFRelease(interfacePrivate
->usb
.vid
);
578 if (interfacePrivate
->bond
.interfaces
!= NULL
)
579 CFRelease(interfacePrivate
->bond
.interfaces
);
581 if (interfacePrivate
->bond
.mode
!= NULL
)
582 CFRelease(interfacePrivate
->bond
.mode
);
584 if (interfacePrivate
->bond
.options
!= NULL
)
585 CFRelease(interfacePrivate
->bond
.options
);
587 if (interfacePrivate
->bridge
.interfaces
!= NULL
)
588 CFRelease(interfacePrivate
->bridge
.interfaces
);
590 if (interfacePrivate
->bridge
.options
!= NULL
)
591 CFRelease(interfacePrivate
->bridge
.options
);
593 if (interfacePrivate
->vlan
.interface
!= NULL
)
594 CFRelease(interfacePrivate
->vlan
.interface
);
596 if (interfacePrivate
->vlan
.tag
!= NULL
)
597 CFRelease(interfacePrivate
->vlan
.tag
);
599 if (interfacePrivate
->vlan
.options
!= NULL
)
600 CFRelease(interfacePrivate
->vlan
.options
);
607 __SCNetworkInterfaceEqual(CFTypeRef cf1
, CFTypeRef cf2
)
609 SCNetworkInterfacePrivateRef if1
= (SCNetworkInterfacePrivateRef
)cf1
;
610 SCNetworkInterfacePrivateRef if2
= (SCNetworkInterfacePrivateRef
)cf2
;
615 if (!CFEqual(if1
->interface_type
, if2
->interface_type
)) {
616 return FALSE
; // if not the same interface type
619 if (!_SC_CFEqual(if1
->entity_device
, if2
->entity_device
)) {
620 return FALSE
; // if not the same device
623 if ((if1
->entity_device_unique
!= NULL
) && (if2
->entity_device_unique
!= NULL
)) {
624 if (!_SC_CFEqual(if1
->entity_device_unique
, if2
->entity_device_unique
)) {
625 return FALSE
; // if not the same device unique identifier
627 } else if ((if1
->entity_device_unique
!= NULL
) || (if2
->entity_device_unique
!= NULL
)) {
631 name1
= __SCNetworkInterfaceGetNonLocalizedDisplayName((SCNetworkInterfaceRef
)if1
);
632 name2
= __SCNetworkInterfaceGetNonLocalizedDisplayName((SCNetworkInterfaceRef
)if2
);
633 if ((name1
!= NULL
) && (name2
!= NULL
) && !_SC_CFEqual(name1
, name2
)) {
634 return FALSE
; // if same device but not the same display name
638 if (CFEqual(if1
->interface_type
, kSCNetworkInterfaceTypeBond
)) {
639 if (!_SC_CFEqual(if1
->bond
.interfaces
, if2
->bond
.interfaces
)) {
640 return FALSE
; // if not the same interfaces
642 if (!_SC_CFEqual(if1
->bond
.mode
, if2
->bond
.mode
)) {
643 return FALSE
; // if not the same mode
647 if (CFEqual(if1
->interface_type
, kSCNetworkInterfaceTypeBridge
)) {
648 if (!_SC_CFEqual(if1
->bridge
.interfaces
, if2
->bridge
.interfaces
)) {
649 return FALSE
; // if not the same interfaces
653 if (CFEqual(if1
->interface_type
, kSCNetworkInterfaceTypeVLAN
)) {
654 if (!_SC_CFEqual(if1
->vlan
.interface
, if2
->vlan
.interface
)) {
655 return FALSE
; // if not the same physical interface
657 if (!_SC_CFEqual(if1
->vlan
.tag
, if2
->vlan
.tag
)) {
658 return FALSE
; // if not the same tag
662 if (!_SC_CFEqual(if1
->interface
, if2
->interface
)) {
663 return FALSE
; // if not the same layering
671 __SCNetworkInterfaceHash(CFTypeRef cf
)
674 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)cf
;
676 if (interfacePrivate
->entity_device
!= NULL
) {
677 if (interfacePrivate
->entity_device_unique
== NULL
) {
678 hash
= CFHash(interfacePrivate
->entity_device
);
682 str
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@+%@"),
683 interfacePrivate
->entity_device
,
684 interfacePrivate
->entity_device_unique
);
695 __SCNetworkInterfaceInitialize(void)
700 __kSCNetworkInterfaceTypeID
= _CFRuntimeRegisterClass(&__SCNetworkInterfaceClass
);
702 // initialize __kSCNetworkInterfaceIPv4
703 _CFRuntimeInitStaticInstance(&__kSCNetworkInterfaceIPv4
, __kSCNetworkInterfaceTypeID
);
704 __kSCNetworkInterfaceIPv4
.interface_type
= kSCNetworkInterfaceTypeIPv4
;
705 __kSCNetworkInterfaceIPv4
.localized_key
= CFSTR("ipv4");
707 // initialize __kSCNetworkInterfaceLoopback
708 _CFRuntimeInitStaticInstance(&__kSCNetworkInterfaceLoopback
, __kSCNetworkInterfaceTypeID
);
709 __kSCNetworkInterfaceLoopback
.interface_type
= kSCNetworkInterfaceTypeLoopback
;
710 __kSCNetworkInterfaceLoopback
.localized_key
= CFSTR("loopback");
711 __kSCNetworkInterfaceLoopback
.entity_device
= CFRetain(CFSTR("lo0"));
712 __kSCNetworkInterfaceLoopback
.entity_type
= kSCValNetInterfaceTypeLoopback
;
714 // get CFBundleRef for SystemConfiguration.framework
715 bundle
= _SC_CFBundleGet();
717 // get mach port used to communication with IOKit
718 kr
= IOMasterPort(MACH_PORT_NULL
, &masterPort
);
719 if (kr
!= kIOReturnSuccess
) {
720 SCLog(TRUE
, LOG_DEBUG
,
721 CFSTR("__SCNetworkInterfaceInitialize(), could not get IOMasterPort, kr = 0x%x"),
730 SCNetworkInterfacePrivateRef
731 __SCNetworkInterfaceCreatePrivate(CFAllocatorRef allocator
,
732 SCNetworkInterfaceRef interface
,
733 SCPreferencesRef prefs
,
734 CFStringRef serviceID
)
736 SCNetworkInterfacePrivateRef interfacePrivate
;
739 /* initialize runtime */
740 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
742 /* allocate target */
743 size
= sizeof(SCNetworkInterfacePrivate
) - sizeof(CFRuntimeBase
);
744 interfacePrivate
= (SCNetworkInterfacePrivateRef
)_CFRuntimeCreateInstance(allocator
,
745 __kSCNetworkInterfaceTypeID
,
748 if (interfacePrivate
== NULL
) {
752 interfacePrivate
->interface_type
= NULL
;
753 interfacePrivate
->name
= NULL
;
754 interfacePrivate
->localized_name
= NULL
;
755 interfacePrivate
->localized_key
= NULL
;
756 interfacePrivate
->localized_arg1
= NULL
;
757 interfacePrivate
->localized_arg2
= NULL
;
758 interfacePrivate
->interface
= (interface
!= NULL
) ? CFRetain(interface
) : NULL
;
759 interfacePrivate
->prefs
= (prefs
!= NULL
) ? CFRetain(prefs
) : NULL
;
760 interfacePrivate
->store
= NULL
;
761 interfacePrivate
->serviceID
= (serviceID
!= NULL
) ? CFRetain(serviceID
) : NULL
;
762 interfacePrivate
->unsaved
= NULL
;
763 interfacePrivate
->entity_device
= NULL
;
764 interfacePrivate
->entity_device_unique
= NULL
;
765 interfacePrivate
->entity_type
= NULL
;
766 interfacePrivate
->entity_subtype
= NULL
;
767 interfacePrivate
->supported_interface_types
= NULL
;
768 interfacePrivate
->supported_protocol_types
= NULL
;
769 interfacePrivate
->address
= NULL
;
770 interfacePrivate
->addressString
= NULL
;
771 interfacePrivate
->builtin
= FALSE
;
772 interfacePrivate
->configurationAction
= NULL
;
773 interfacePrivate
->hidden
= FALSE
;
774 interfacePrivate
->location
= NULL
;
775 interfacePrivate
->path
= NULL
;
776 interfacePrivate
->entryID
= 0;
777 interfacePrivate
->overrides
= NULL
;
778 interfacePrivate
->modemIsV92
= FALSE
;
779 interfacePrivate
->prefix
= NULL
;
780 interfacePrivate
->type
= NULL
;
781 interfacePrivate
->unit
= NULL
;
782 interfacePrivate
->usb
.name
= NULL
;
783 interfacePrivate
->usb
.vid
= NULL
;
784 interfacePrivate
->usb
.pid
= NULL
;
785 interfacePrivate
->sort_order
= kSortUnknown
;
787 interfacePrivate
->supportsBond
= FALSE
;
788 interfacePrivate
->bond
.interfaces
= NULL
;
789 interfacePrivate
->bond
.mode
= NULL
;
790 interfacePrivate
->bond
.options
= NULL
;
792 interfacePrivate
->supportsBridge
= FALSE
;
793 interfacePrivate
->bridge
.interfaces
= NULL
;
794 interfacePrivate
->bridge
.options
= NULL
;
796 interfacePrivate
->supportsVLAN
= FALSE
;
797 interfacePrivate
->vlan
.interface
= NULL
;
798 interfacePrivate
->vlan
.tag
= NULL
;
799 interfacePrivate
->vlan
.options
= NULL
;
801 return interfacePrivate
;
807 __SCNetworkInterfaceSupportsVLAN(CFStringRef bsd_if
)
811 struct if_msghdr
* ifm
;
812 char * if_name
= NULL
;
813 unsigned int if_index
;
815 Boolean vlanOK
= FALSE
;
817 // get the interface index
818 if_name
= _SC_cfstring_to_cstring(bsd_if
, NULL
, 0, kCFStringEncodingASCII
);
819 if (if_name
== NULL
) {
820 return FALSE
; // if conversion error
822 if_index
= if_nametoindex(if_name
);
824 goto done
; // if unknown interface
827 // get information for the specified interface
832 mib
[4] = NET_RT_IFLIST
;
833 mib
[5] = if_index
; /* ask for exactly one interface */
835 if (sysctl(mib
, 6, NULL
, &buf_len
, NULL
, 0) == -1) {
836 SCLog(TRUE
, LOG_ERR
, CFSTR("sysctl() size failed: %s"), strerror(errno
));
839 buf
= CFAllocatorAllocate(NULL
, buf_len
, 0);
840 if (sysctl(mib
, 6, buf
, &buf_len
, NULL
, 0) == -1) {
841 SCLog(TRUE
, LOG_ERR
, CFSTR("sysctl() failed: %s"), strerror(errno
));
845 // check the link type and hwassist flags
846 // ALIGN: buf is aligned
847 ifm
= (struct if_msghdr
*)(void *)buf
;
848 switch (ifm
->ifm_type
) {
850 #if defined(IF_HWASSIST_VLAN_TAGGING) && defined(IF_HWASSIST_VLAN_MTU)
851 struct if_data
*if_data
= &ifm
->ifm_data
;
853 if (if_data
->ifi_hwassist
& (IF_HWASSIST_VLAN_TAGGING
| IF_HWASSIST_VLAN_MTU
)) {
863 if (if_name
!= NULL
) CFAllocatorDeallocate(NULL
, if_name
);
864 if (buf
!= NULL
) CFAllocatorDeallocate(NULL
, buf
);
871 SCNetworkInterfacePrivateRef
872 _SCBondInterfaceCreatePrivate(CFAllocatorRef allocator
,
875 SCNetworkInterfacePrivateRef interfacePrivate
;
877 interfacePrivate
= __SCNetworkInterfaceCreatePrivate(allocator
, NULL
, NULL
, NULL
);
878 if (interfacePrivate
== NULL
) {
882 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeBond
;
883 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeEthernet
;
884 interfacePrivate
->entity_device
= CFStringCreateCopy(allocator
, bond_if
);
885 interfacePrivate
->builtin
= TRUE
;
886 interfacePrivate
->supportsVLAN
= __SCNetworkInterfaceSupportsVLAN(bond_if
);
887 interfacePrivate
->sort_order
= kSortBond
;
889 interfacePrivate
->localized_key
= CFSTR("bond");
890 interfacePrivate
->localized_arg1
= CFRetain(interfacePrivate
->entity_device
);
892 interfacePrivate
->bond
.interfaces
= CFArrayCreate(NULL
, NULL
, 0, &kCFTypeArrayCallBacks
);
893 // interfacePrivate->bond.mode = NULL;
894 // interfacePrivate->bond.options = NULL;
896 return interfacePrivate
;
901 SCNetworkInterfacePrivateRef
902 _SCBridgeInterfaceCreatePrivate(CFAllocatorRef allocator
,
903 CFStringRef bridge_if
)
905 SCNetworkInterfacePrivateRef interfacePrivate
;
907 interfacePrivate
= __SCNetworkInterfaceCreatePrivate(allocator
, NULL
, NULL
, NULL
);
908 if (interfacePrivate
== NULL
) {
912 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeBridge
;
913 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeEthernet
;
914 interfacePrivate
->entity_device
= CFStringCreateCopy(allocator
, bridge_if
);
915 interfacePrivate
->builtin
= TRUE
;
916 interfacePrivate
->supportsVLAN
= __SCNetworkInterfaceSupportsVLAN(bridge_if
);
917 interfacePrivate
->sort_order
= kSortBridge
;
919 interfacePrivate
->localized_key
= CFSTR("bridge");
920 interfacePrivate
->localized_arg1
= CFRetain(interfacePrivate
->entity_device
);
922 interfacePrivate
->bridge
.interfaces
= CFArrayCreate(NULL
, NULL
, 0, &kCFTypeArrayCallBacks
);
923 // interfacePrivate->bridge.options = NULL;
925 return interfacePrivate
;
930 SCNetworkInterfacePrivateRef
931 _SCVLANInterfaceCreatePrivate(CFAllocatorRef allocator
,
934 SCNetworkInterfacePrivateRef interfacePrivate
;
936 interfacePrivate
= __SCNetworkInterfaceCreatePrivate(allocator
, NULL
, NULL
, NULL
);
937 if (interfacePrivate
== NULL
) {
941 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeVLAN
;
942 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeEthernet
;
943 interfacePrivate
->entity_device
= CFStringCreateCopy(allocator
, vlan_if
);
944 interfacePrivate
->builtin
= TRUE
;
945 interfacePrivate
->sort_order
= kSortVLAN
;
947 interfacePrivate
->localized_key
= CFSTR("vlan");
948 interfacePrivate
->localized_arg1
= CFRetain(interfacePrivate
->entity_device
);
950 // interfacePrivate->vlan.interface = NULL;
951 // interfacePrivate->vlan.tag = NULL;
952 // interfacePrivate->vlan.options = NULL;
954 return interfacePrivate
;
959 #pragma mark Interface ordering
962 static CF_RETURNS_RETAINED CFArrayRef
963 split_path(CFStringRef path
)
965 CFArrayRef components
;
966 CFMutableStringRef nPath
;
968 // turn '@'s into '/'s
969 nPath
= CFStringCreateMutableCopy(NULL
, 0, path
);
970 (void) CFStringFindAndReplace(nPath
,
973 CFRangeMake(0, CFStringGetLength(nPath
)),
976 // split path into components to be compared
977 components
= CFStringCreateArrayBySeparatingStrings(NULL
, nPath
, CFSTR("/"));
985 _SCNetworkInterfaceCompare(const void *val1
, const void *val2
, void *context
)
987 SCNetworkInterfacePrivateRef dev1
= (SCNetworkInterfacePrivateRef
)val1
;
988 SCNetworkInterfacePrivateRef dev2
= (SCNetworkInterfacePrivateRef
)val2
;
989 CFComparisonResult res
= kCFCompareEqualTo
;
991 /* sort by interface type */
992 if (dev1
->sort_order
!= dev2
->sort_order
) {
993 if (dev1
->sort_order
< dev2
->sort_order
) {
994 res
= kCFCompareLessThan
;
996 res
= kCFCompareGreaterThan
;
1001 /* built-in interfaces sort first */
1002 if (dev1
->builtin
!= dev2
->builtin
) {
1003 if (dev1
->builtin
) {
1004 res
= kCFCompareLessThan
;
1006 res
= kCFCompareGreaterThan
;
1011 /* ... and then, sort built-in interfaces by "location" */
1012 if (dev1
->builtin
) {
1013 if (dev1
->location
!= dev2
->location
) {
1014 if (isA_CFString(dev1
->location
)) {
1015 if (isA_CFString(dev2
->location
)) {
1016 res
= CFStringCompare(dev1
->location
, dev2
->location
, 0);
1018 res
= kCFCompareLessThan
;
1021 res
= kCFCompareGreaterThan
;
1024 if (res
!= kCFCompareEqualTo
) {
1030 /* ... and, then sort by IOPathMatch */
1031 if ((dev1
->path
!= NULL
) && (dev2
->path
!= NULL
)) {
1032 CFArrayRef elements1
;
1033 CFArrayRef elements2
;
1039 elements1
= split_path(dev1
->path
);
1040 n1
= CFArrayGetCount(elements1
);
1042 elements2
= split_path(dev2
->path
);
1043 n2
= CFArrayGetCount(elements2
);
1045 n
= (n1
<= n2
) ? n1
: n2
;
1046 for (i
= 0; i
< n
; i
++) {
1055 e1
= CFArrayGetValueAtIndex(elements1
, i
);
1056 e2
= CFArrayGetValueAtIndex(elements2
, i
);
1058 str
= _SC_cfstring_to_cstring(e1
, NULL
, 0, kCFStringEncodingUTF8
);
1060 q1
= strtoq(str
, &end
, 16);
1061 isNum
= ((*str
!= '\0') && (*end
== '\0') && (errno
== 0));
1062 CFAllocatorDeallocate(NULL
, str
);
1065 // if e1 is a valid numeric string
1066 str
= _SC_cfstring_to_cstring(e2
, NULL
, 0, kCFStringEncodingUTF8
);
1068 q2
= strtoq(str
, &end
, 16);
1069 isNum
= ((*str
!= '\0') && (*end
== '\0') && (errno
== 0));
1070 CFAllocatorDeallocate(NULL
, str
);
1073 // if e2 is also a valid numeric string
1076 res
= kCFCompareEqualTo
;
1078 } else if (q1
< q2
) {
1079 res
= kCFCompareLessThan
;
1081 res
= kCFCompareGreaterThan
;
1087 res
= CFStringCompare(e1
, e2
, 0);
1088 if (res
!= kCFCompareEqualTo
) {
1093 if (res
== kCFCompareEqualTo
) {
1095 res
= kCFCompareLessThan
;
1096 } else if (n1
< n2
) {
1097 res
= kCFCompareGreaterThan
;
1101 CFRelease(elements1
);
1102 CFRelease(elements2
);
1104 if (res
!= kCFCompareEqualTo
) {
1109 /* ... and, then sort by BSD interface name */
1110 if ((dev1
->entity_device
!= NULL
) && (dev2
->entity_device
!= NULL
)) {
1111 res
= CFStringCompare(dev1
->entity_device
, dev2
->entity_device
, 0);
1112 if (res
!= kCFCompareEqualTo
) {
1117 /* ... and lastly, sort by BSD interface unique identifier */
1118 if ((dev1
->entity_device_unique
!= NULL
) && (dev2
->entity_device_unique
!= NULL
)) {
1119 res
= CFStringCompare(dev1
->entity_device_unique
, dev2
->entity_device_unique
, 0);
1120 // if (res != kCFCompareEqualTo) {
1130 sort_interfaces(CFMutableArrayRef all_interfaces
)
1132 int n
= CFArrayGetCount(all_interfaces
);
1138 CFArraySortValues(all_interfaces
, CFRangeMake(0, n
), _SCNetworkInterfaceCompare
, NULL
);
1145 __SCNetworkInterfaceOrder(SCNetworkInterfaceRef interface
)
1147 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
1149 return interfacePrivate
->sort_order
;
1154 #pragma mark Interface details
1158 IOCopyCFStringValue(CFTypeRef ioVal
)
1160 if (isA_CFString(ioVal
)) {
1161 return CFStringCreateCopy(NULL
, ioVal
);
1164 if (isA_CFData(ioVal
)) {
1165 return CFStringCreateWithCString(NULL
,
1166 (const char *)CFDataGetBytePtr(ioVal
),
1167 kCFStringEncodingUTF8
);
1175 IODictionaryCopyBSDName(CFDictionaryRef io_dict
)
1177 CFStringRef if_bsdName
;
1178 CFStringRef if_prefix
;
1179 CFNumberRef if_unit
;
1181 if_bsdName
= CFDictionaryGetValue(io_dict
, CFSTR(kIOBSDNameKey
));
1182 if (if_bsdName
!= NULL
) {
1183 return IOCopyCFStringValue(if_bsdName
);
1186 // no BSD name, get interface prefix and unit
1187 if_prefix
= CFDictionaryGetValue(io_dict
, CFSTR(kIOInterfaceNamePrefix
));
1188 if_unit
= CFDictionaryGetValue(io_dict
, CFSTR(kIOInterfaceUnit
));
1189 if (isA_CFString(if_prefix
) && isA_CFNumber(if_unit
)) {
1190 // if both prefix and unit available, construct BSD name
1191 if_bsdName
= CFStringCreateWithFormat(NULL
,
1203 IODictionaryCopyCFStringValue(CFDictionaryRef io_dict
, CFStringRef io_key
)
1207 ioVal
= CFDictionaryGetValue(io_dict
, io_key
);
1208 return IOCopyCFStringValue(ioVal
);
1213 IOStringValueHasPrefix(CFTypeRef ioVal
, CFStringRef prefix
)
1215 Boolean match
= FALSE
;
1216 CFIndex prefixLen
= CFStringGetLength(prefix
);
1217 CFStringRef str
= NULL
;
1219 if (!isA_CFString(ioVal
)) {
1220 if (isA_CFData(ioVal
)) {
1221 str
= CFStringCreateWithCStringNoCopy(NULL
,
1222 (const char *)CFDataGetBytePtr(ioVal
),
1223 kCFStringEncodingUTF8
,
1231 if ((ioVal
!= NULL
) &&
1232 (CFStringGetLength(ioVal
) >= prefixLen
) &&
1233 (CFStringCompareWithOptions(ioVal
,
1235 CFRangeMake(0, prefixLen
),
1236 kCFCompareCaseInsensitive
) == kCFCompareEqualTo
)) {
1240 if (str
!= NULL
) CFRelease(str
);
1245 static const struct {
1246 const CFStringRef name
;
1247 const CFStringRef slot
;
1248 } slot_mappings
[] = {
1250 { CFSTR("A1") , CFSTR("1") },
1251 { CFSTR("B1") , CFSTR("2") },
1252 { CFSTR("C1") , CFSTR("3") },
1254 // Blue&White G3, Yikes G4
1255 { CFSTR("J12"), CFSTR("1") },
1256 { CFSTR("J11"), CFSTR("2") },
1257 { CFSTR("J10"), CFSTR("3") },
1258 { CFSTR("J9"), CFSTR("4") },
1261 { CFSTR("A") , CFSTR("1") },
1262 { CFSTR("B") , CFSTR("2") },
1263 { CFSTR("C") , CFSTR("3") },
1264 { CFSTR("D") , CFSTR("4") },
1266 // Digital Audio G4 (and later models)
1267 { CFSTR("1") , CFSTR("1") },
1268 { CFSTR("2") , CFSTR("2") },
1269 { CFSTR("3") , CFSTR("3") },
1270 { CFSTR("4") , CFSTR("4") },
1271 { CFSTR("5") , CFSTR("5") }
1275 static const CFStringRef slot_prefixes
[] = {
1276 CFSTR("thunderbolt slot "),
1282 static CF_RETURNS_RETAINED CFStringRef
1283 pci_slot(io_registry_entry_t interface
, CFTypeRef
*pci_slot_name
)
1286 io_registry_entry_t parent
;
1287 CFMutableStringRef slot
;
1288 CFTypeRef slot_name
;
1291 if (pci_slot_name
!= NULL
) *pci_slot_name
= NULL
;
1293 slot_name
= IORegistryEntryCreateCFProperty(interface
, CFSTR("AAPL,slot-name"), NULL
, 0);
1294 if (slot_name
!= NULL
) {
1297 slot
= CFStringCreateMutable(NULL
, 0);
1298 if (isA_CFString(slot_name
)) {
1299 if (pci_slot_name
!= NULL
) *pci_slot_name
= CFStringCreateCopy(NULL
, slot_name
);
1300 CFStringAppend(slot
, slot_name
);
1301 } else if (isA_CFData(slot_name
)) {
1302 if (pci_slot_name
!= NULL
) *pci_slot_name
= CFDataCreateCopy(NULL
, slot_name
);
1303 CFStringAppendCString(slot
,
1304 (const char *)CFDataGetBytePtr(slot_name
),
1305 kCFStringEncodingUTF8
);
1308 for (i
= 0; i
< sizeof(slot_prefixes
)/sizeof(slot_prefixes
[0]); i
++) {
1311 len
= CFStringGetLength(slot_prefixes
[i
]);
1312 if (CFStringGetLength(slot
) > len
) {
1313 (void) CFStringFindAndReplace(slot
,
1316 CFRangeMake(0, len
),
1317 kCFCompareCaseInsensitive
|kCFCompareAnchored
);
1321 for (i
= 0; i
< sizeof(slot_mappings
)/sizeof(slot_mappings
[0]); i
++) {
1322 if (CFStringCompare(slot
,
1323 slot_mappings
[i
].name
,
1324 kCFCompareCaseInsensitive
) == kCFCompareEqualTo
) {
1326 slot
= (CFMutableStringRef
)CFRetain(slot_mappings
[i
].slot
);
1331 CFRelease(slot_name
);
1334 kr
= IORegistryEntryGetParentEntry(interface
, kIOServicePlane
, &parent
);
1336 case kIOReturnSuccess
: {
1337 CFTypeRef parent_pci_slot_name
= NULL
;
1338 CFStringRef parent_slot
;
1340 parent_slot
= pci_slot(parent
, &parent_pci_slot_name
);
1341 if (parent_slot
!= NULL
) {
1342 if (slot
!= NULL
) CFRelease(slot
);
1343 slot
= (CFMutableStringRef
)parent_slot
;
1345 if (pci_slot_name
!= NULL
) {
1346 if (*pci_slot_name
!= NULL
) CFRelease(*pci_slot_name
);
1347 *pci_slot_name
= parent_pci_slot_name
;
1349 CFRelease(parent_pci_slot_name
);
1353 IOObjectRelease(parent
);
1356 case kIOReturnNoDevice
:
1357 // if we have hit the root node
1360 SCLog(TRUE
, LOG_DEBUG
, CFSTR("pci_slot IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr
);
1368 static CFComparisonResult
1369 compare_bsdNames(const void *val1
, const void *val2
, void *context
)
1371 CFStringRef bsd1
= (CFStringRef
)val1
;
1372 CFStringRef bsd2
= (CFStringRef
)val2
;
1374 return CFStringCompare(bsd1
, bsd2
, 0);
1378 static CF_RETURNS_RETAINED CFStringRef
1379 pci_port(CFTypeRef slot_name
, int ift
, CFStringRef bsdName
)
1382 CFStringRef port_name
= NULL
;
1383 CFMutableArrayRef port_names
;
1386 CFStringRef match_keys
[2];
1387 CFTypeRef match_vals
[2];
1388 CFDictionaryRef match_dict
;
1389 CFDictionaryRef matching
;
1390 io_registry_entry_t slot
;
1391 io_iterator_t slot_iterator
= MACH_PORT_NULL
;
1393 match_keys
[0] = CFSTR("AAPL,slot-name");
1394 match_vals
[0] = slot_name
;
1396 match_dict
= CFDictionaryCreate(NULL
,
1397 (const void **)match_keys
,
1398 (const void **)match_vals
,
1400 &kCFTypeDictionaryKeyCallBacks
,
1401 &kCFTypeDictionaryValueCallBacks
);
1403 match_keys
[0] = CFSTR(kIOProviderClassKey
);
1404 match_vals
[0] = CFSTR("IOPCIDevice");
1406 match_keys
[1] = CFSTR(kIOPropertyMatchKey
);
1407 match_vals
[1] = match_dict
;
1409 // note: the "matching" dictionary will be consumed by the following
1410 matching
= CFDictionaryCreate(NULL
,
1411 (const void **)match_keys
,
1412 (const void **)match_vals
,
1413 sizeof(match_keys
)/sizeof(match_keys
[0]),
1414 &kCFTypeDictionaryKeyCallBacks
,
1415 &kCFTypeDictionaryValueCallBacks
);
1416 CFRelease(match_dict
);
1418 kr
= IOServiceGetMatchingServices(masterPort
, matching
, &slot_iterator
);
1419 if (kr
!= kIOReturnSuccess
) {
1420 SCLog(TRUE
, LOG_DEBUG
, CFSTR("pci_port IOServiceGetMatchingServices() failed, kr = 0x%x"), kr
);
1421 return MACH_PORT_NULL
;
1424 port_names
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1426 while ((slot
= IOIteratorNext(slot_iterator
)) != MACH_PORT_NULL
) {
1427 io_registry_entry_t child
;
1428 io_iterator_t child_iterator
= MACH_PORT_NULL
;
1430 kr
= IORegistryEntryCreateIterator(slot
,
1432 kIORegistryIterateRecursively
,
1434 if (kr
!= kIOReturnSuccess
) {
1435 SCLog(TRUE
, LOG_DEBUG
, CFSTR("pci_port IORegistryEntryCreateIterator() failed, kr = 0x%x"), kr
);
1436 CFRelease(port_names
);
1437 return MACH_PORT_NULL
;
1440 while ((child
= IOIteratorNext(child_iterator
)) != MACH_PORT_NULL
) {
1441 if (IOObjectConformsTo(child
, kIONetworkInterfaceClass
)) {
1442 CFMutableDictionaryRef interface_dict
= NULL
;
1444 (void) IORegistryEntryCreateCFProperties(child
, &interface_dict
, NULL
, kNilOptions
);
1445 if (interface_dict
!= NULL
) {
1446 CFNumberRef child_if_type
;
1447 int child_ift
= ift
;
1449 child_if_type
= CFDictionaryGetValue(interface_dict
, CFSTR(kIOInterfaceType
));
1450 if (child_if_type
!= NULL
) {
1451 if (!isA_CFNumber(child_if_type
) ||
1452 !CFNumberGetValue(child_if_type
, kCFNumberIntType
, &child_ift
)) {
1453 // assume that it's a match
1458 if (ift
== child_ift
) {
1459 CFStringRef if_bsdName
;
1461 if_bsdName
= IODictionaryCopyBSDName(interface_dict
);
1462 if (if_bsdName
!= NULL
) {
1463 CFArrayAppendValue(port_names
, if_bsdName
);
1464 CFRelease(if_bsdName
);
1468 CFRelease(interface_dict
);
1471 IOObjectRelease(child
);
1473 IOObjectRelease(child_iterator
);
1474 IOObjectRelease(slot
);
1476 IOObjectRelease(slot_iterator
);
1478 n
= CFArrayGetCount(port_names
);
1480 CFArraySortValues(port_names
, CFRangeMake(0, n
), compare_bsdNames
, NULL
);
1481 n
= CFArrayGetFirstIndexOfValue(port_names
, CFRangeMake(0, n
), bsdName
);
1482 if (n
!= kCFNotFound
) {
1483 port_name
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%ld"), n
+ 1);
1487 CFRelease(port_names
);
1493 pci_slot_info(io_registry_entry_t interface
, int ift
, CFStringRef
*slot_name
, CFStringRef
*port_name
)
1495 CFStringRef bsd_name
= NULL
;
1496 CFMutableDictionaryRef interface_dict
= NULL
;
1498 CFTypeRef pci_slot_name
;
1503 (void) IORegistryEntryCreateCFProperties(interface
, &interface_dict
, NULL
, kNilOptions
);
1504 if (interface_dict
!= NULL
) {
1505 bsd_name
= IODictionaryCopyBSDName(interface_dict
);
1506 CFRelease(interface_dict
);
1509 if (bsd_name
== NULL
) {
1513 *slot_name
= pci_slot(interface
, &pci_slot_name
);
1514 if (*slot_name
!= NULL
) {
1515 if (pci_slot_name
!= NULL
) {
1516 *port_name
= pci_port(pci_slot_name
, ift
, bsd_name
);
1517 CFRelease(pci_slot_name
);
1522 CFRelease(bsd_name
);
1528 isBuiltin(io_registry_entry_t interface
)
1532 slot
= pci_slot(interface
, NULL
);
1534 // interfaces which have a "slot" are not built-in
1544 isBluetoothBuiltin(Boolean
*haveController
)
1546 Boolean builtin
= FALSE
;
1547 io_object_t hciController
;
1548 io_iterator_t iter
= MACH_PORT_NULL
;
1551 kr
= IOServiceGetMatchingServices(masterPort
,
1552 IOServiceMatching("IOBluetoothHCIController"),
1554 if ((kr
!= kIOReturnSuccess
) || (iter
== MACH_PORT_NULL
)) {
1555 if (kr
!= kIOReturnSuccess
) {
1556 SCLog(TRUE
, LOG_DEBUG
, CFSTR("isBluetoothBuiltin IOServiceGetMatchingServices() failed, kr = 0x%x"), kr
);
1558 *haveController
= FALSE
;
1561 *haveController
= TRUE
;
1563 hciController
= IOIteratorNext(iter
);
1564 IOObjectRelease(iter
);
1565 if(hciController
!= MACH_PORT_NULL
) {
1566 #if !TARGET_IPHONE_SIMULATOR
1567 CFNumberRef idVendor
;
1569 idVendor
= IORegistryEntryCreateCFProperty(hciController
, CFSTR(kUSBVendorID
), NULL
, 0);
1570 if (idVendor
!= NULL
) {
1573 if (isA_CFNumber(idVendor
) &&
1574 CFNumberGetValue(idVendor
, kCFNumberIntType
, &idVendorVal
) &&
1575 (idVendorVal
== kIOUSBVendorIDAppleComputer
)) {
1579 CFRelease(idVendor
);
1581 #endif // !TARGET_IPHONE_SIMULATOR
1583 IOObjectRelease(hciController
);
1591 isThunderbolt(io_registry_entry_t interface
)
1595 val
= IORegistryEntrySearchCFProperty(interface
,
1597 CFSTR(kPCIThunderboltString
),
1599 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1610 processUSBInterface(SCNetworkInterfacePrivateRef interfacePrivate
,
1611 io_registry_entry_t interface
,
1612 CFDictionaryRef interface_dict
,
1613 io_registry_entry_t controller
,
1614 CFDictionaryRef controller_dict
,
1615 io_registry_entry_t bus
,
1616 CFDictionaryRef bus_dict
)
1618 #if !TARGET_IPHONE_SIMULATOR
1620 interfacePrivate
->usb
.name
= IORegistryEntrySearchCFProperty(interface
,
1622 CFSTR(kUSBProductString
),
1624 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1625 interfacePrivate
->usb
.vid
= IORegistryEntrySearchCFProperty(interface
,
1627 CFSTR(kUSBVendorID
),
1629 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1630 interfacePrivate
->usb
.pid
= IORegistryEntrySearchCFProperty(interface
,
1632 CFSTR(kUSBProductID
),
1634 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1635 #endif // !TARGET_IPHONE_SIMULATOR
1642 update_interface_name(SCNetworkInterfacePrivateRef interfacePrivate
,
1643 io_registry_entry_t interface
,
1646 Boolean updated
= FALSE
;
1649 // check if a "Product Name" has been provided
1650 val
= IORegistryEntrySearchCFProperty(interface
,
1652 CFSTR(kIOPropertyProductNameKey
),
1654 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1655 if ((val
== NULL
) && useUSBInfo
&& (interfacePrivate
->usb
.name
!= NULL
)) {
1656 // else, use "USB Product Name" if available
1657 val
= CFRetain(interfacePrivate
->usb
.name
);
1660 CFStringRef productName
;
1662 productName
= IOCopyCFStringValue(val
);
1665 if (productName
!= NULL
) {
1666 if (CFStringGetLength(productName
) > 0) {
1667 // if we have a [somewhat reasonable?] product name
1668 if (interfacePrivate
->name
!= NULL
) {
1669 CFRelease(interfacePrivate
->name
);
1671 interfacePrivate
->name
= CFRetain(productName
);
1672 if (interfacePrivate
->localized_name
!= NULL
) {
1673 CFRelease(interfacePrivate
->localized_name
);
1675 interfacePrivate
->localized_name
= copy_interface_string(bundle
, productName
, TRUE
);
1680 CFRelease(productName
);
1689 #pragma mark Interface enumeration
1692 typedef Boolean (*processInterface
)(SCNetworkInterfacePrivateRef interfacePrivate
,
1693 io_registry_entry_t interface
,
1694 CFDictionaryRef interface_dict
,
1695 io_registry_entry_t controller
,
1696 CFDictionaryRef controller_dict
,
1697 io_registry_entry_t bus
,
1698 CFDictionaryRef bus_dict
);
1702 merge_override(SCNetworkInterfacePrivateRef interfacePrivate
,
1703 io_registry_entry_t interface
,
1704 CFStringRef override
)
1709 key
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("Device%@Overrides"), override
);
1710 val
= IORegistryEntrySearchCFProperty(interface
,
1714 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1717 if (isA_CFDictionary(val
)) {
1718 if (interfacePrivate
->overrides
== NULL
) {
1719 interfacePrivate
->overrides
= CFDictionaryCreateMutable(NULL
,
1721 &kCFTypeDictionaryKeyCallBacks
,
1722 &kCFTypeDictionaryValueCallBacks
);
1724 CFDictionarySetValue(interfacePrivate
->overrides
, override
, val
);
1733 #define BT_PAN_NAME "Bluetooth PAN"
1736 processNetworkInterface(SCNetworkInterfacePrivateRef interfacePrivate
,
1737 io_registry_entry_t interface
,
1738 CFDictionaryRef interface_dict
,
1739 io_registry_entry_t controller
,
1740 CFDictionaryRef controller_dict
,
1741 io_registry_entry_t bus
,
1742 CFDictionaryRef bus_dict
)
1752 num
= CFDictionaryGetValue(interface_dict
, CFSTR(kIOInterfaceType
));
1753 if (isA_CFNumber(num
) &&
1754 CFNumberGetValue(num
, kCFNumberIntType
, &ift
)) {
1755 interfacePrivate
->type
= CFRetain(num
);
1757 SCLog(TRUE
, LOG_DEBUG
, CFSTR("processNetworkInterface() failed, no interface type"));
1765 if (IOObjectConformsTo(controller
, "IO80211Controller") ||
1766 IOObjectConformsTo(controller
, "AirPortPCI" ) ||
1767 IOObjectConformsTo(controller
, "AirPortDriver" )) {
1768 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeIEEE80211
;
1769 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeEthernet
;
1770 interfacePrivate
->sort_order
= kSortAirPort
;
1771 } else if (IOObjectConformsTo(controller
, "AppleThunderboltIPPort")) {
1772 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
;
1773 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeEthernet
;
1774 interfacePrivate
->sort_order
= kSortThunderbolt
;
1775 } else if (IOObjectConformsTo(controller
, "IOBluetoothBNEPDriver")) {
1776 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
;
1777 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeEthernet
;
1778 interfacePrivate
->sort_order
= kSortBluetoothPAN_GN
;
1779 } else if (IOObjectConformsTo(controller
, "AppleUSBEthernetHost")) {
1780 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
;
1781 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeEthernet
;
1782 interfacePrivate
->sort_order
= kSortTethered
;
1783 } else if (IOObjectConformsTo(controller
, "AppleUSBCDCECMData")) {
1784 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
;
1785 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeEthernet
;
1786 interfacePrivate
->sort_order
= kSortWWANEthernet
;
1789 if (interfacePrivate
->interface_type
== NULL
) {
1790 val
= IORegistryEntrySearchCFProperty(interface
,
1792 CFSTR(kIOUserEthernetInterfaceRoleKey
),
1794 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1796 if (isA_CFString(val
)) {
1797 if (CFEqual(val
, CFSTR(BT_PAN_NAME
))) {
1798 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
;
1799 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeEthernet
;
1800 interfacePrivate
->sort_order
= kSortBluetoothPAN_GN
;
1801 } else if (CFEqual(val
, CFSTR("Bluetooth PAN-NAP"))) {
1802 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
;
1803 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeEthernet
;
1804 interfacePrivate
->sort_order
= kSortBluetoothPAN_NAP
;
1805 } else if (CFEqual(val
, CFSTR("Bluetooth P2P"))) {
1806 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
;
1807 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeEthernet
;
1808 interfacePrivate
->sort_order
= kSortBluetoothPAN_U
;
1816 if (interfacePrivate
->interface_type
== NULL
) {
1817 str
= IODictionaryCopyCFStringValue(bus_dict
, CFSTR("name"));
1819 if (CFEqual(str
, CFSTR("radio"))) {
1820 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
; // ??
1821 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeEthernet
;
1822 interfacePrivate
->sort_order
= kSortOtherWireless
;
1829 if (interfacePrivate
->interface_type
== NULL
) {
1830 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
;
1831 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeEthernet
;
1832 interfacePrivate
->sort_order
= kSortEthernet
;
1834 // BOND support only enabled for ethernet devices
1835 interfacePrivate
->supportsBond
= TRUE
;
1838 // enable Bridge support
1839 interfacePrivate
->supportsBridge
= TRUE
;
1842 val
= isA_CFBoolean(CFDictionaryGetValue(interface_dict
, CFSTR(kIOBuiltin
)));
1844 val
= isA_CFBoolean(CFDictionaryGetValue(interface_dict
, CFSTR(kIOPrimaryInterface
)));
1847 interfacePrivate
->builtin
= CFBooleanGetValue(val
);
1849 interfacePrivate
->builtin
= isBuiltin(interface
);
1852 if (!interfacePrivate
->builtin
&&
1853 CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeIEEE80211
)) {
1854 // always treat AirPort interfaces as built-in
1855 interfacePrivate
->builtin
= TRUE
;
1859 interfacePrivate
->location
= IODictionaryCopyCFStringValue(interface_dict
, CFSTR(kIOLocation
));
1860 if ((interfacePrivate
->location
!= NULL
) &&
1861 (CFStringGetLength(interfacePrivate
->location
) == 0)) {
1862 CFRelease(interfacePrivate
->location
);
1863 interfacePrivate
->location
= NULL
;
1867 num
= CFDictionaryGetValue(controller_dict
, CFSTR(kIOFeatures
));
1868 if (isA_CFNumber(num
) &&
1869 CFNumberGetValue(num
, kCFNumberIntType
, & iVal
)) {
1870 if (iVal
& (kIONetworkFeatureHardwareVlan
| kIONetworkFeatureSoftwareVlan
)) {
1871 interfacePrivate
->supportsVLAN
= TRUE
;
1876 if (CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeIEEE80211
)) {
1877 interfacePrivate
->localized_key
= CFSTR("airport");
1878 } else if (interfacePrivate
->sort_order
== kSortThunderbolt
) {
1879 if ((interfacePrivate
->location
== NULL
) ||
1880 (CFStringGetLength(interfacePrivate
->location
) == 0)) {
1881 interfacePrivate
->localized_key
= CFSTR("thunderbolt");
1883 interfacePrivate
->localized_key
= CFSTR("multithunderbolt");
1884 interfacePrivate
->localized_arg1
= CFRetain(interfacePrivate
->location
);
1886 } else if (interfacePrivate
->sort_order
== kSortBluetoothPAN_GN
) {
1887 interfacePrivate
->localized_key
= CFSTR("bluetooth-pan-gn");
1888 } else if (interfacePrivate
->sort_order
== kSortBluetoothPAN_NAP
) {
1889 interfacePrivate
->localized_key
= CFSTR("bluetooth-pan-nap");
1890 } else if (interfacePrivate
->sort_order
== kSortBluetoothPAN_U
) {
1891 interfacePrivate
->localized_key
= CFSTR("bluetooth-pan-u");
1892 } else if (interfacePrivate
->sort_order
== kSortOtherWireless
) {
1893 interfacePrivate
->localized_key
= CFSTR("wireless");
1894 interfacePrivate
->localized_arg1
= CFRetain(CFSTR("")); // ??
1895 } else if (interfacePrivate
->builtin
) {
1896 if ((interfacePrivate
->location
== NULL
) ||
1897 (CFStringGetLength(interfacePrivate
->location
) == 0)) {
1898 interfacePrivate
->localized_key
= CFSTR("ether");
1900 interfacePrivate
->localized_key
= CFSTR("multiether");
1901 interfacePrivate
->localized_arg1
= CFRetain(interfacePrivate
->location
);
1904 CFStringRef provider
;
1906 // check provider class
1907 provider
= IORegistryEntrySearchCFProperty(interface
,
1909 CFSTR(kIOProviderClassKey
),
1911 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
1912 if (provider
!= NULL
) {
1913 if (CFEqual(provider
, CFSTR("IOPCIDevice"))) {
1914 CFStringRef port_name
;
1915 CFStringRef slot_name
;
1917 // set interface "name"
1918 if (!update_interface_name(interfacePrivate
, interface
, FALSE
) &&
1919 pci_slot_info(interface
, ift
, &slot_name
, &port_name
)) {
1920 if (isThunderbolt(interface
)) {
1921 if (port_name
== NULL
) {
1922 interfacePrivate
->localized_key
= CFSTR("thunderbolt-ether");
1923 interfacePrivate
->localized_arg1
= slot_name
;
1925 interfacePrivate
->localized_key
= CFSTR("thunderbolt-multiether");
1926 interfacePrivate
->localized_arg1
= slot_name
;
1927 interfacePrivate
->localized_arg2
= port_name
;
1931 if (port_name
== NULL
) {
1932 interfacePrivate
->localized_key
= CFSTR("pci-ether");
1933 interfacePrivate
->localized_arg1
= slot_name
;
1935 interfacePrivate
->localized_key
= CFSTR("pci-multiether");
1936 interfacePrivate
->localized_arg1
= slot_name
;
1937 interfacePrivate
->localized_arg2
= port_name
;
1941 } else if (CFEqual(provider
, CFSTR("IOUSBDevice")) ||
1942 CFEqual(provider
, CFSTR("IOUSBInterface"))) {
1943 // get USB info (if available)
1944 processUSBInterface(interfacePrivate
,
1952 // set interface "name"
1953 if (!update_interface_name(interfacePrivate
, interface
, TRUE
)) {
1954 interfacePrivate
->localized_key
= CFSTR("usb-ether");
1955 interfacePrivate
->localized_arg1
= IODictionaryCopyBSDName(interface_dict
);
1958 CFRelease(provider
);
1961 if (interfacePrivate
->localized_key
== NULL
) {
1962 // if no provider, not a PCI device, or no slot information
1963 interfacePrivate
->localized_key
= CFSTR("generic-ether");
1964 interfacePrivate
->localized_arg1
= IODictionaryCopyBSDName(interface_dict
);
1971 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeFireWire
;
1974 interfacePrivate
->entity_type
= kSCValNetInterfaceTypeFireWire
;
1977 interfacePrivate
->builtin
= isBuiltin(interface
);
1980 interfacePrivate
->sort_order
= kSortFireWire
;
1983 if (interfacePrivate
->builtin
) {
1984 interfacePrivate
->localized_key
= CFSTR("firewire");
1986 CFStringRef port_name
;
1987 CFStringRef slot_name
;
1989 // set interface "name"
1990 if (!update_interface_name(interfacePrivate
, interface
, FALSE
) &&
1991 pci_slot_info(interface
, ift
, &slot_name
, &port_name
)) {
1992 if (isThunderbolt(interface
)) {
1993 if (port_name
== NULL
) {
1994 interfacePrivate
->localized_key
= CFSTR("thunderbolt-firewire");
1995 interfacePrivate
->localized_arg1
= slot_name
;
1997 interfacePrivate
->localized_key
= CFSTR("thunderbolt-multifirewire");
1998 interfacePrivate
->localized_arg1
= slot_name
;
1999 interfacePrivate
->localized_arg2
= port_name
;
2002 if (port_name
== NULL
) {
2003 interfacePrivate
->localized_key
= CFSTR("pci-firewire");
2004 interfacePrivate
->localized_arg1
= slot_name
;
2006 interfacePrivate
->localized_key
= CFSTR("pci-multifirewire");
2007 interfacePrivate
->localized_arg1
= slot_name
;
2008 interfacePrivate
->localized_arg2
= port_name
;
2016 SCLog(TRUE
, LOG_DEBUG
, CFSTR("processNetworkInterface() failed, unknown interface type = %d"), ift
);
2021 interfacePrivate
->entity_device
= IODictionaryCopyBSDName(interface_dict
);
2023 // Hardware (MAC) address
2024 data
= CFDictionaryGetValue(controller_dict
, CFSTR(kIOMACAddress
));
2025 if (isA_CFData(data
)) {
2026 interfacePrivate
->address
= CFRetain(data
);
2030 str
= CFDictionaryGetValue(interface_dict
, CFSTR(kIOInterfaceNamePrefix
));
2031 if (isA_CFString(str
)) {
2032 interfacePrivate
->prefix
= CFRetain(str
);
2036 num
= CFDictionaryGetValue(interface_dict
, CFSTR(kIOInterfaceUnit
));
2037 if (isA_CFNumber(num
) &&
2038 CFNumberGetValue(num
, kCFNumberIntType
, & iVal
)) {
2039 interfacePrivate
->unit
= CFRetain(num
);
2042 // configuration [PPP] template override (now deprecated, use NetworkConfigurationOverrides)
2043 merge_override(interfacePrivate
, interface
, kSCNetworkInterfaceTypePPP
);
2050 set_connection_script(SCNetworkInterfacePrivateRef interfacePrivate
, CFStringRef script
)
2052 CFDictionaryRef dict
;
2053 CFMutableDictionaryRef newDict
;
2055 if (interfacePrivate
->overrides
== NULL
) {
2056 interfacePrivate
->overrides
= CFDictionaryCreateMutable(NULL
,
2058 &kCFTypeDictionaryKeyCallBacks
,
2059 &kCFTypeDictionaryValueCallBacks
);
2062 dict
= CFDictionaryGetValue(interfacePrivate
->overrides
, kSCNetworkInterfaceTypeModem
);
2064 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
2066 newDict
= CFDictionaryCreateMutable(NULL
,
2068 &kCFTypeDictionaryKeyCallBacks
,
2069 &kCFTypeDictionaryValueCallBacks
);
2071 if (script
!= NULL
) {
2072 CFDictionarySetValue(newDict
, kSCPropNetModemConnectionScript
, script
);
2074 CFDictionaryRemoveValue(newDict
, kSCPropNetModemConnectionScript
);
2076 if (CFDictionaryGetCount(newDict
) > 0) {
2077 CFDictionarySetValue(interfacePrivate
->overrides
, kSCNetworkInterfaceTypeModem
, newDict
);
2079 CFDictionaryRemoveValue(interfacePrivate
->overrides
, kSCNetworkInterfaceTypeModem
);
2083 if (CFDictionaryGetCount(interfacePrivate
->overrides
) == 0) {
2084 CFRelease(interfacePrivate
->overrides
);
2085 interfacePrivate
->overrides
= NULL
;
2092 is_valid_connection_script(CFStringRef script
)
2094 char ccl
[MAXPATHLEN
];
2095 char path
[MAXPATHLEN
];
2096 NSSearchPathEnumerationState state
;
2098 (void) _SC_cfstring_to_cstring(script
,
2101 kCFStringEncodingUTF8
);
2103 state
= NSStartSearchPathEnumeration(NSLibraryDirectory
,
2104 NSLocalDomainMask
|NSSystemDomainMask
);
2105 while ((state
= NSGetNextSearchPathEnumeration(state
, path
))) {
2107 struct stat statBuf
;
2109 if (ccl
[0] == '/') {
2110 path
[0] = '\0'; // if modemCCL is a full path
2112 strlcat(path
, "/Modem Scripts/", sizeof(path
));
2114 strlcat(path
, ccl
, sizeof(path
));
2116 if (stat(path
, &statBuf
) != 0) {
2117 if (errno
== ENOENT
) {
2121 SCLog(TRUE
, LOG_DEBUG
,
2122 CFSTR("processSerialInterface stat() failed: %s"),
2126 if (S_ISREG(statBuf
.st_mode
)) {
2127 // if we have a valid CCL script
2131 #define BUNDLE_EXT ".ccl"
2132 #define BUNDLE_EXT_LEN sizeof(BUNDLE_EXT) - 1
2137 if ((n
<= BUNDLE_EXT_LEN
) ||
2138 (strstr(&path
[n
- BUNDLE_EXT_LEN
], BUNDLE_EXT
) == NULL
)) {
2139 strlcat(path
, BUNDLE_EXT
, sizeof(path
));
2140 if (stat(path
, &statBuf
) != 0) {
2141 if (errno
== ENOENT
) {
2145 SCLog(TRUE
, LOG_DEBUG
,
2146 CFSTR("processSerialInterface stat() failed: %s"),
2151 if (S_ISDIR(statBuf
.st_mode
)) {
2152 // if we have a valid CCL bundle
2162 processSerialInterface(SCNetworkInterfacePrivateRef interfacePrivate
,
2163 io_registry_entry_t interface
,
2164 CFDictionaryRef interface_dict
,
2165 io_registry_entry_t controller
,
2166 CFDictionaryRef controller_dict
,
2167 io_registry_entry_t bus
,
2168 CFDictionaryRef bus_dict
)
2170 CFStringRef base
= NULL
;
2172 Boolean isModem
= FALSE
;
2173 Boolean isWWAN
= FALSE
;
2174 CFStringRef modemCCL
= NULL
;
2179 val
= IORegistryEntrySearchCFProperty(interface
,
2181 kSCNetworkInterfaceHiddenPortKey
,
2183 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
2186 return FALSE
; // if this interface should not be exposed
2189 // check if initializing
2190 val
= IORegistryEntrySearchCFProperty(interface
,
2192 kSCNetworkInterfaceInitializingKey
,
2194 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
2196 Boolean initializing
;
2198 initializing
= isA_CFBoolean(val
) && CFBooleanGetValue(val
);
2201 return FALSE
; // if this interface is still initializing
2206 val
= IORegistryEntrySearchCFProperty(interface
,
2210 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
2212 isWWAN
= isA_CFBoolean(val
) && CFBooleanGetValue(val
);
2217 interfacePrivate
->entity_device
= IODictionaryCopyCFStringValue(interface_dict
, CFSTR(kIOTTYDeviceKey
));
2218 if (interfacePrivate
->entity_device
== NULL
) {
2222 base
= IODictionaryCopyCFStringValue(interface_dict
, CFSTR(kIOTTYBaseNameKey
));
2224 base
= CFRetain(interfacePrivate
->entity_device
);
2230 * Exclude ports named "irda" because otherwise the IrDA ports on the
2231 * original iMac (rev's A through D) show up as serial ports. Given
2232 * that only the rev A actually had an IrDA port, and Mac OS X doesn't
2233 * even support it, these ports definitely shouldn't be listed.
2235 if (CFStringCompare(base
,
2237 kCFCompareCaseInsensitive
) == kCFCompareEqualTo
) {
2241 if (IOStringValueHasPrefix(base
, CFSTR("bluetooth"))) {
2242 Boolean haveController
= FALSE
;
2245 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeBluetooth
;
2246 interfacePrivate
->sort_order
= kSortBluetooth
;
2247 interfacePrivate
->builtin
= isBluetoothBuiltin(&haveController
);
2248 if (!haveController
) {
2249 // if device with no controller present
2252 } else if (IOStringValueHasPrefix(base
, CFSTR("irda-ircomm"))) {
2254 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeIrDA
;
2255 interfacePrivate
->sort_order
= kSortIrDA
;
2256 } else if (isWWAN
) {
2258 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeWWAN
;
2259 interfacePrivate
->sort_order
= kSortWWAN
;
2262 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeModem
;
2263 interfacePrivate
->sort_order
= kSortModem
;
2266 val
= IORegistryEntrySearchCFProperty(interface
,
2268 CFSTR(kIODeviceSupportsHoldKey
),
2270 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
2274 if (isA_CFNumber(val
) &&
2275 CFNumberGetValue(val
, kCFNumberSInt32Type
, &v92
)) {
2276 interfacePrivate
->modemIsV92
= (v92
== 1);
2283 interfacePrivate
->entity_type
= kSCEntNetModem
;
2285 // Entity (Hardware)
2286 ift
= CFDictionaryGetValue(interface_dict
, CFSTR(kIOSerialBSDTypeKey
));
2287 if (!isA_CFString(ift
)) {
2291 if (CFEqual(ift
, CFSTR(kIOSerialBSDModemType
))) {
2295 if (CFEqual(base
, CFSTR("modem"))) {
2296 interfacePrivate
->builtin
= TRUE
;
2297 interfacePrivate
->sort_order
= kSortInternalModem
;
2298 } else if (CFEqual(base
, CFSTR("usbmodem"))) {
2299 interfacePrivate
->sort_order
= kSortUSBModem
;
2301 } else if (CFEqual(ift
, CFSTR(kIOSerialBSDRS232Type
))) {
2303 interfacePrivate
->sort_order
= kSortSerialPort
;
2308 // configuration [PPP] template override (now deprecated, use NetworkConfigurationOverrides)
2309 merge_override(interfacePrivate
, interface
, kSCNetworkInterfaceTypePPP
);
2311 // configuration [Modem] template override (now deprecated, use NetworkConfigurationOverrides)
2312 merge_override(interfacePrivate
, interface
, kSCNetworkInterfaceTypeModem
);
2314 // look for modem CCL, unique identifier
2315 if (interfacePrivate
->overrides
!= NULL
) {
2316 val
= CFDictionaryGetValue(interfacePrivate
->overrides
, kSCNetworkInterfaceTypeModem
);
2318 CFStringRef uniqueID
;
2320 modemCCL
= CFDictionaryGetValue(val
, kSCPropNetModemConnectionScript
);
2321 modemCCL
= isA_CFString(modemCCL
);
2323 uniqueID
= CFDictionaryGetValue(val
, CFSTR("UniqueIdentifier"));
2324 uniqueID
= isA_CFString(uniqueID
);
2325 if (uniqueID
!= NULL
) {
2326 // retain the device's base name and the unique id
2327 CFRelease(interfacePrivate
->entity_device
);
2328 interfacePrivate
->entity_device
= CFRetain(base
);
2329 interfacePrivate
->entity_device_unique
= CFStringCreateCopy(NULL
, uniqueID
);
2334 // if not part of the NetworkConfigurationOverrides/DeviceModemOverrides, look
2335 // a bit harder for the modem CCL
2336 if (modemCCL
== NULL
) {
2337 val
= IORegistryEntrySearchCFProperty(interface
,
2341 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
2343 modemCCL
= IOCopyCFStringValue(val
);
2344 if (modemCCL
!= NULL
) {
2345 set_connection_script(interfacePrivate
, modemCCL
);
2346 CFRelease(modemCCL
);
2354 if (CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeIrDA
)) {
2355 interfacePrivate
->localized_key
= CFSTR("irda");
2356 } else if (CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeBluetooth
)) {
2357 interfacePrivate
->localized_key
= CFSTR("bluetooth");
2359 CFStringRef localized
= NULL
;
2360 CFStringRef name
= NULL
;
2361 CFMutableStringRef port
;
2363 port
= CFStringCreateMutableCopy(NULL
, 0, base
);
2364 CFStringLowercase(port
, NULL
);
2367 CFStringAppend(port
, CFSTR("-port"));
2370 // set non-localized name
2371 if (bundle
!= NULL
) {
2372 name
= copy_interface_string(bundle
, port
, FALSE
);
2375 if (!CFEqual(port
, name
)) {
2376 // if [English] localization available
2377 interfacePrivate
->name
= name
;
2379 // if no [English] localization available, use TTY base name
2381 interfacePrivate
->name
= CFStringCreateCopy(NULL
, base
);
2384 interfacePrivate
->name
= CFStringCreateCopy(NULL
, base
);
2387 // set localized name
2388 if (bundle
!= NULL
) {
2389 localized
= copy_interface_string(bundle
, port
, TRUE
);
2391 if (localized
!= NULL
) {
2392 if (!CFEqual(port
, localized
)) {
2393 // if localization available
2394 interfacePrivate
->localized_name
= localized
;
2396 // if no localization available, use TTY base name
2397 CFRelease(localized
);
2398 interfacePrivate
->localized_name
= CFStringCreateCopy(NULL
, base
);
2401 interfacePrivate
->localized_name
= CFStringCreateCopy(NULL
, base
);
2404 if (!isModem
|| !CFEqual(base
, CFSTR("modem"))) {
2405 // get USB info (if available)
2406 processUSBInterface(interfacePrivate
,
2414 // set interface "name"
2415 if (update_interface_name(interfacePrivate
, interface
, TRUE
)) {
2416 // if "ModemCCL" not provided, also check if the product/interface
2417 // name matches a CCL script
2418 if ((modemCCL
== NULL
) &&
2419 is_valid_connection_script(interfacePrivate
->name
)) {
2420 set_connection_script(interfacePrivate
, interfacePrivate
->name
);
2432 if (!ok
&& (interfacePrivate
->entity_device
!= NULL
)) {
2433 CFRelease(interfacePrivate
->entity_device
);
2434 interfacePrivate
->entity_device
= NULL
;
2436 if (base
!= NULL
) CFRelease(base
);
2443 __SC_IORegistryEntryCopyPath(io_registry_entry_t entry
, const io_name_t plane
)
2446 * Create a path for a registry entry.
2450 CFStringRef str
= NULL
;
2452 status
= IORegistryEntryGetPath(entry
, plane
, path
);
2453 if (status
== kIOReturnSuccess
) {
2454 str
= CFStringCreateWithCString(NULL
, path
, kCFStringEncodingUTF8
);
2455 } else if (status
== kIOReturnBadArgument
) {
2456 io_registry_entry_t parent
;
2458 status
= IORegistryEntryGetParentEntry(entry
, plane
, &parent
);
2459 if (status
== kIOReturnSuccess
) {
2460 CFStringRef str_parent
;
2462 str_parent
= __SC_IORegistryEntryCopyPath(parent
, plane
);
2463 if (str_parent
!= NULL
) {
2466 status
= IORegistryEntryGetNameInPlane(entry
, plane
, name
);
2467 if (status
== kIOReturnSuccess
) {
2470 status
= IORegistryEntryGetLocationInPlane(entry
, plane
, location
);
2471 if (status
== kIOReturnSuccess
) {
2472 str
= CFStringCreateWithFormat(NULL
,
2479 str
= CFStringCreateWithFormat(NULL
,
2487 CFRelease(str_parent
);
2490 IOObjectRelease(parent
);
2498 static SCNetworkInterfaceRef
2499 createInterface(io_registry_entry_t interface
, processInterface func
)
2501 io_registry_entry_t bus
= MACH_PORT_NULL
;
2502 CFMutableDictionaryRef bus_dict
= NULL
;
2503 io_registry_entry_t controller
= MACH_PORT_NULL
;
2504 CFMutableDictionaryRef controller_dict
= NULL
;
2505 uint64_t entryID
= 0;
2506 SCNetworkInterfacePrivateRef interfacePrivate
= NULL
;
2507 CFMutableDictionaryRef interface_dict
= NULL
;
2511 kr
= IORegistryEntryCreateCFProperties(interface
, &interface_dict
, NULL
, kNilOptions
);
2512 if (kr
!= kIOReturnSuccess
) {
2513 SCLog(TRUE
, LOG_DEBUG
, CFSTR("createInterface IORegistryEntryCreateCFProperties() failed, kr = 0x%x"), kr
);
2517 /* get the controller node */
2518 kr
= IORegistryEntryGetParentEntry(interface
, kIOServicePlane
, &controller
);
2519 if (kr
!= kIOReturnSuccess
) {
2520 SCLog(TRUE
, LOG_DEBUG
, CFSTR("createInterface IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr
);
2524 /* get the dictionary associated with the node */
2525 kr
= IORegistryEntryCreateCFProperties(controller
, &controller_dict
, NULL
, kNilOptions
);
2526 if (kr
!= kIOReturnSuccess
) {
2527 SCLog(TRUE
, LOG_DEBUG
, CFSTR("createInterface IORegistryEntryCreateCFProperties() failed, kr = 0x%x"), kr
);
2531 /* get the bus node */
2532 kr
= IORegistryEntryGetParentEntry(controller
, kIOServicePlane
, &bus
);
2533 if (kr
!= kIOReturnSuccess
) {
2534 SCLog(TRUE
, LOG_DEBUG
, CFSTR("createInterface IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr
);
2538 /* get the dictionary associated with the node */
2539 kr
= IORegistryEntryCreateCFProperties(bus
, &bus_dict
, NULL
, kNilOptions
);
2540 if (kr
!= kIOReturnSuccess
) {
2541 SCLog(TRUE
, LOG_DEBUG
, CFSTR("createInterface IORegistryEntryCreateCFProperties() failed, kr = 0x%x"), kr
);
2545 /* get the registry entry ID */
2546 kr
= IORegistryEntryGetRegistryEntryID(interface
, &entryID
);
2547 if (kr
!= kIOReturnSuccess
) {
2548 SCLog(TRUE
, LOG_DEBUG
, CFSTR("createInterface IORegistryEntryGetRegistryEntryID() failed, kr = 0x%x"), kr
);
2552 interfacePrivate
= __SCNetworkInterfaceCreatePrivate(NULL
, NULL
, NULL
, NULL
);
2553 assert(interfacePrivate
!= NULL
);
2554 interfacePrivate
->path
= __SC_IORegistryEntryCopyPath(interface
, kIOServicePlane
);
2555 interfacePrivate
->entryID
= entryID
;
2557 // configuration [PPP, Modem, DNS, IPv4, IPv6, Proxies, SMB] template overrides
2558 val
= IORegistryEntrySearchCFProperty(interface
,
2560 kSCNetworkInterfaceNetworkConfigurationOverridesKey
,
2562 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
2564 if (isA_CFDictionary(val
)) {
2565 interfacePrivate
->overrides
= CFDictionaryCreateMutableCopy(NULL
, 0, val
);
2570 if ((*func
)(interfacePrivate
, interface
, interface_dict
, controller
, controller_dict
, bus
, bus_dict
)) {
2571 /* get user-notification / auto-configuration preference */
2572 val
= IORegistryEntrySearchCFProperty(interface
,
2574 kSCNetworkInterfaceConfigurationActionKey
,
2576 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
2578 if (isA_CFString(val
)) {
2579 interfacePrivate
->configurationAction
= CFRetain(val
);
2584 /* get HiddenConfiguration preference */
2585 val
= IORegistryEntrySearchCFProperty(interface
,
2587 kSCNetworkInterfaceHiddenConfigurationKey
,
2589 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
2591 interfacePrivate
->hidden
= TRUE
;
2595 CFRelease(interfacePrivate
);
2596 interfacePrivate
= NULL
;
2601 if (interface_dict
!= NULL
) CFRelease(interface_dict
);
2603 if (controller
!= MACH_PORT_NULL
) IOObjectRelease(controller
);
2604 if (controller_dict
!= NULL
) CFRelease(controller_dict
);
2606 if (bus
!= MACH_PORT_NULL
) IOObjectRelease(bus
);
2607 if (bus_dict
!= NULL
) CFRelease(bus_dict
);
2609 return (SCNetworkInterfaceRef
)interfacePrivate
;
2613 static CF_RETURNS_RETAINED CFArrayRef
2614 findMatchingInterfaces(CFDictionaryRef matching
, processInterface func
)
2616 CFMutableArrayRef interfaces
;
2617 io_registry_entry_t interface
;
2619 io_iterator_t iterator
= MACH_PORT_NULL
;
2622 * A reference to the "matching" dictionary will be consumed by the
2623 * the call to IOServiceGetMatchingServices so we bump up the retain
2628 kr
= IOServiceGetMatchingServices(masterPort
, matching
, &iterator
);
2629 if (kr
!= kIOReturnSuccess
) {
2630 SCLog(TRUE
, LOG_DEBUG
, CFSTR("findMatchingInterfaces IOServiceGetMatchingServices() failed, kr = 0x%x"), kr
);
2634 interfaces
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
2636 while ((interface
= IOIteratorNext(iterator
)) != MACH_PORT_NULL
) {
2637 SCNetworkInterfaceRef match
;
2639 match
= createInterface(interface
, func
);
2640 if (match
!= NULL
) {
2641 CFArrayAppendValue(interfaces
, match
);
2645 IOObjectRelease(interface
);
2648 IOObjectRelease(iterator
);
2655 #pragma mark helper functions
2659 findConfiguration(CFStringRef interface_type
)
2663 for (i
= 0; i
< sizeof(configurations
)/sizeof(configurations
[0]); i
++) {
2664 if (CFEqual(interface_type
, *configurations
[i
].interface_type
)) {
2675 __SCNetworkInterfaceGetDefaultConfigurationType(SCNetworkInterfaceRef interface
)
2677 CFIndex interfaceIndex
;
2678 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2680 if (interfacePrivate
->serviceID
== NULL
) {
2681 // if not associated with a service (yet)
2682 _SCErrorSet(kSCStatusInvalidArgument
);
2686 interfaceIndex
= findConfiguration(interfacePrivate
->interface_type
);
2687 if (interfaceIndex
== kCFNotFound
) {
2688 // unknown interface type, use per-service configuration preferences
2689 return interfacePrivate
->interface_type
; // entity
2692 if (configurations
[interfaceIndex
].entity_hardware
!= NULL
) {
2693 // if configuration information can be associated with this interface type
2694 return *configurations
[interfaceIndex
].entity_hardware
;
2697 _SCErrorSet(kSCStatusInvalidArgument
);
2704 __SCNetworkInterfaceIsValidExtendedConfigurationType(SCNetworkInterfaceRef interface
,
2705 CFStringRef extendedType
,
2706 Boolean requirePerInterface
)
2708 CFStringRef defaultType
;
2709 CFIndex extendedIndex
;
2710 CFIndex interfaceIndex
;
2711 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2712 Boolean isL2TP
= FALSE
;
2715 defaultType
= __SCNetworkInterfaceGetDefaultConfigurationType(interface
);
2716 if (defaultType
== NULL
) {
2720 if (CFEqual(extendedType
, defaultType
)) {
2721 // extended and default configuration types cannot conflict
2725 interfaceIndex
= findConfiguration(interfacePrivate
->interface_type
);
2726 if (interfaceIndex
== kCFNotFound
) {
2727 // configuration information for unknown interface type's
2728 // are stored along with the service and we don't allow
2729 // per-service extended configurations
2733 if (CFEqual(extendedType
, kSCEntNetIPSec
)) {
2734 CFStringRef interfaceType
;
2736 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
2737 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
)) {
2738 SCNetworkInterfaceRef child
;
2740 child
= SCNetworkInterfaceGetInterface(interface
);
2741 if (child
!= NULL
) {
2742 interfaceType
= SCNetworkInterfaceGetInterfaceType(child
);
2743 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeL2TP
)) {
2750 if (requirePerInterface
&&
2751 !configurations
[interfaceIndex
].per_interface_config
&&
2753 // we don't allow per-service extended configurations (except
2754 // that we do allow IPSec as an extended type for PPP->L2TP)
2758 extendedIndex
= findConfiguration(extendedType
);
2759 if ((extendedIndex
!= kCFNotFound
) && !isL2TP
) {
2760 // extended type cannot match a known interface type (except
2761 // that we do allow IPSec as an extended type for PPP->L2TP)
2767 * Do we match specific/known extended configuration types (e.g. EAPOL)
2768 * and ensure that any non-standard extended configuration types be of
2769 * the form com.myCompany.myType?
2778 _SCErrorSet(kSCStatusInvalidArgument
);
2785 CFStringRef defaultType
;
2786 CFMutableArrayRef types
;
2787 } extendedConfiguration
, *extendedConfigurationRef
;
2791 __addExtendedConfigurationType(const void *key
, const void *value
, void *context
)
2793 CFStringRef extendedType
= (CFStringRef
)key
;
2794 extendedConfigurationRef myContextRef
= (extendedConfigurationRef
)context
;
2796 if (CFEqual(extendedType
, myContextRef
->defaultType
)) {
2797 // do not include the default configuration type
2801 if (CFArrayContainsValue(myContextRef
->types
,
2802 CFRangeMake(0, CFArrayGetCount(myContextRef
->types
)),
2804 // if extendedType already has already been added
2808 CFArrayAppendValue(myContextRef
->types
, extendedType
);
2814 static CF_RETURNS_RETAINED CFArrayRef
2815 extendedConfigurationTypes(SCNetworkInterfaceRef interface
)
2818 CFIndex interfaceIndex
;
2819 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2820 extendedConfiguration myContext
;
2821 SCNetworkServiceRef service
;
2825 myContext
.defaultType
= __SCNetworkInterfaceGetDefaultConfigurationType(interface
);
2826 if (myContext
.defaultType
== NULL
) {
2827 myContext
.types
= NULL
;
2831 myContext
.types
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
2833 if (interfacePrivate
->serviceID
== NULL
) {
2834 // if not associated with a service (yet)
2838 interfaceIndex
= findConfiguration(interfacePrivate
->interface_type
);
2839 if (interfaceIndex
== kCFNotFound
) {
2840 // we don't allow per-service extended configurations
2844 if (!configurations
[interfaceIndex
].per_interface_config
) {
2845 // known interface type but we still don't allow
2846 // per-service extended configurations
2850 service
= (SCNetworkServiceRef
)__SCNetworkServiceCreatePrivate(NULL
,
2851 interfacePrivate
->prefs
,
2852 interfacePrivate
->serviceID
,
2855 sets
= SCNetworkSetCopyAll(interfacePrivate
->prefs
);
2856 n
= (sets
!= NULL
) ? CFArrayGetCount(sets
) : 0;
2858 for (i
= 0; i
< n
; i
++) {
2859 CFDictionaryRef configs
;
2862 CFArrayRef services
;
2863 SCNetworkSetRef set
;
2865 set
= CFArrayGetValueAtIndex(sets
, i
);
2866 services
= SCNetworkSetCopyServices(set
);
2867 found
= CFArrayContainsValue(services
,
2868 CFRangeMake(0, CFArrayGetCount(services
)),
2870 CFRelease(services
);
2876 // add stored extended configuration types
2877 path
= SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL
, // allocator
2878 SCNetworkSetGetSetID(set
), // set
2879 interfacePrivate
->entity_device
, // service
2881 configs
= __getPrefsConfiguration(interfacePrivate
->prefs
, path
);
2883 if (isA_CFDictionary(configs
)) {
2884 CFDictionaryApplyFunction(configs
,
2885 __addExtendedConfigurationType
,
2889 // add not-yet-stored extended configuration types
2890 if (interfacePrivate
->unsaved
!= NULL
) {
2891 CFDictionaryApplyFunction(interfacePrivate
->unsaved
,
2892 __addExtendedConfigurationType
,
2900 if (sets
!= NULL
) CFRelease(sets
);
2904 return myContext
.types
;
2909 copyConfigurationPaths(SCNetworkInterfacePrivateRef interfacePrivate
,
2910 CFStringRef extendedType
)
2912 CFMutableArrayRef array
;
2914 CFIndex interfaceIndex
;
2917 SCNetworkServiceRef service
;
2920 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
2922 interfaceIndex
= findConfiguration(interfacePrivate
->interface_type
);
2923 if (interfaceIndex
== kCFNotFound
) {
2924 // unknown interface type, use per-service configuration preferences
2925 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
2926 interfacePrivate
->serviceID
, // service
2927 extendedType
); // entity
2928 CFArrayAppendValue(array
, path
);
2933 if (!configurations
[interfaceIndex
].per_interface_config
) {
2934 // known interface type, per-service configuration preferences
2935 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
2936 interfacePrivate
->serviceID
, // service
2937 extendedType
); // entity
2938 CFArrayAppendValue(array
, path
);
2943 // known interface type, per-interface configuration preferences
2945 // 1. look for all sets which contain the associated service
2946 // 2. add a per-set path for the interface configuration for
2949 service
= (SCNetworkServiceRef
)__SCNetworkServiceCreatePrivate(NULL
,
2950 interfacePrivate
->prefs
,
2951 interfacePrivate
->serviceID
,
2952 (SCNetworkInterfaceRef
)interfacePrivate
);
2954 sets
= SCNetworkSetCopyAll(interfacePrivate
->prefs
);
2955 n
= (sets
!= NULL
) ? CFArrayGetCount(sets
) : 0;
2957 for (i
= 0; i
< n
; i
++) {
2958 CFArrayRef services
;
2959 SCNetworkSetRef set
;
2961 set
= CFArrayGetValueAtIndex(sets
, i
);
2962 services
= SCNetworkSetCopyServices(set
);
2963 if (CFArrayContainsValue(services
,
2964 CFRangeMake(0, CFArrayGetCount(services
)),
2966 path
= SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL
, // allocator
2967 SCNetworkSetGetSetID(set
), // set
2968 interfacePrivate
->entity_device
, // service
2969 extendedType
); // entity
2970 CFArrayAppendValue(array
, path
);
2973 CFRelease(services
);
2976 if (CFArrayGetCount(array
) == 0) {
2982 if (sets
!= NULL
) CFRelease(sets
);
2988 #pragma mark SCNetworkInterface <--> preferences entity
2993 __SCNetworkInterfaceCopyInterfaceEntity(SCNetworkInterfaceRef interface
)
2995 CFMutableDictionaryRef entity
;
2996 CFIndex interfaceIndex
;
2997 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
2999 entity
= CFDictionaryCreateMutable(NULL
,
3001 &kCFTypeDictionaryKeyCallBacks
,
3002 &kCFTypeDictionaryValueCallBacks
);
3003 if (interfacePrivate
->entity_type
!= NULL
) {
3004 CFDictionarySetValue(entity
,
3005 kSCPropNetInterfaceType
,
3006 interfacePrivate
->entity_type
);
3008 if (interfacePrivate
->entity_subtype
!= NULL
) {
3009 CFDictionarySetValue(entity
,
3010 kSCPropNetInterfaceSubType
,
3011 interfacePrivate
->entity_subtype
);
3013 if (interfacePrivate
->entity_device
!= NULL
) {
3014 CFDictionarySetValue(entity
,
3015 kSCPropNetInterfaceDeviceName
,
3016 interfacePrivate
->entity_device
);
3018 if (interfacePrivate
->entity_device_unique
!= NULL
) {
3019 CFDictionarySetValue(entity
,
3020 CFSTR("DeviceUniqueIdentifier"),
3021 interfacePrivate
->entity_device_unique
);
3023 if (interfacePrivate
->hidden
) {
3024 CFDictionarySetValue(entity
,
3025 kSCNetworkInterfaceHiddenConfigurationKey
,
3029 // match the "hardware" with the lowest layer
3031 SCNetworkInterfaceRef nextInterface
;
3033 nextInterface
= SCNetworkInterfaceGetInterface(interface
);
3034 if (nextInterface
== NULL
) {
3038 interface
= nextInterface
;
3040 interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
3042 if (CFEqual(interface
, kSCNetworkInterfaceIPv4
)) {
3046 interfaceIndex
= findConfiguration(interfacePrivate
->interface_type
);
3047 if (interfaceIndex
!= kCFNotFound
) {
3048 if (configurations
[interfaceIndex
].entity_hardware
!= NULL
) {
3049 CFDictionarySetValue(entity
,
3050 kSCPropNetInterfaceHardware
,
3051 *configurations
[interfaceIndex
].entity_hardware
);
3054 CFDictionarySetValue(entity
,
3055 kSCPropNetInterfaceHardware
,
3056 interfacePrivate
->interface_type
);
3059 // add the localized display name (which will only be used when/if the
3060 // interface is removed from the system)
3061 CFDictionarySetValue(entity
,
3062 kSCPropUserDefinedName
,
3063 SCNetworkInterfaceGetLocalizedDisplayName(interface
));
3065 // note that this is a V.92 capable modem
3066 if (CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeModem
) &&
3067 interfacePrivate
->modemIsV92
) {
3071 num
= CFNumberCreate(NULL
, kCFNumberIntType
, &one
);
3072 CFDictionarySetValue(entity
,
3073 kSCPropNetInterfaceSupportsModemOnHold
,
3082 static SCNetworkInterfaceRef
3083 findInterface(CFArrayRef interfaces
, CFStringRef match_if
)
3088 n
= CFArrayGetCount(interfaces
);
3089 for (i
= 0; i
< n
; i
++) {
3090 SCNetworkInterfaceRef interface
= CFArrayGetValueAtIndex(interfaces
, i
);
3091 CFStringRef interfaceName
;
3093 interfaceName
= SCNetworkInterfaceGetBSDName(interface
);
3094 if ((interfaceName
!= NULL
) && CFEqual(interfaceName
, match_if
)) {
3095 CFRetain(interface
);
3103 #if !TARGET_OS_IPHONE
3104 static SCNetworkInterfaceRef
3105 findBondInterface(SCPreferencesRef prefs
, CFStringRef ifDevice
)
3108 SCNetworkInterfaceRef interface
= NULL
;
3110 if (prefs
== NULL
) {
3114 // check if the interface is an Ethernet Bond
3115 bonds
= SCBondInterfaceCopyAll(prefs
);
3116 if (bonds
!= NULL
) {
3117 interface
= findInterface(bonds
, ifDevice
);
3122 #endif // !TARGET_OS_IPHONE
3124 static SCNetworkInterfaceRef
3125 findBridgeInterface(SCPreferencesRef prefs
, CFStringRef ifDevice
)
3128 SCNetworkInterfaceRef interface
= NULL
;
3130 if (prefs
== NULL
) {
3134 // check if the interface is an bridge
3135 bridges
= SCBridgeInterfaceCopyAll(prefs
);
3136 if (bridges
!= NULL
) {
3137 interface
= findInterface(bridges
, ifDevice
);
3143 static SCNetworkInterfaceRef
3144 findVLANInterface(SCPreferencesRef prefs
, CFStringRef ifDevice
)
3146 SCNetworkInterfaceRef interface
= NULL
;
3149 if (prefs
== NULL
) {
3153 // check if the interface is a VLAN
3154 vlans
= SCVLANInterfaceCopyAll(prefs
);
3155 if (vlans
!= NULL
) {
3156 interface
= findInterface(vlans
, ifDevice
);
3163 SCNetworkInterfaceRef
3164 _SCNetworkInterfaceCreateWithBSDName(CFAllocatorRef allocator
,
3165 CFStringRef bsdName
,
3168 CFMutableDictionaryRef entity
;
3169 SCNetworkInterfaceRef interface
;
3171 entity
= CFDictionaryCreateMutable(NULL
,
3173 &kCFTypeDictionaryKeyCallBacks
,
3174 &kCFTypeDictionaryValueCallBacks
);
3175 CFDictionarySetValue(entity
, kSCPropNetInterfaceDeviceName
, bsdName
);
3177 #if !TARGET_OS_IPHONE
3178 if ((flags
& kIncludeBondInterfaces
) == 0) {
3179 CFDictionarySetValue(entity
, CFSTR("_NO_BOND_INTERFACES_"), kCFBooleanTrue
);
3181 #endif // !TARGET_OS_IPHONE
3183 if ((flags
& kIncludeBridgeInterfaces
) == 0) {
3184 CFDictionarySetValue(entity
, CFSTR("_NO_BRIDGE_INTERFACES_"), kCFBooleanTrue
);
3187 if ((flags
& kIncludeVLANInterfaces
) == 0) {
3188 CFDictionarySetValue(entity
, CFSTR("_NO_VLAN_INTERFACES_"), kCFBooleanTrue
);
3191 interface
= _SCNetworkInterfaceCreateWithEntity(NULL
, entity
, NULL
);
3199 __SCNetworkInterfaceSetService(SCNetworkInterfaceRef interface
,
3200 SCNetworkServiceRef service
)
3202 SCNetworkInterfacePrivateRef interfacePrivate
;
3203 SCNetworkServicePrivateRef servicePrivate
;
3205 interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
3206 if (interfacePrivate
->prefs
!= NULL
) {
3207 CFRelease(interfacePrivate
->prefs
);
3208 interfacePrivate
->prefs
= NULL
;
3210 if (interfacePrivate
->serviceID
!= NULL
) {
3211 CFRelease(interfacePrivate
->serviceID
);
3212 interfacePrivate
->serviceID
= NULL
;
3215 servicePrivate
= (SCNetworkServicePrivateRef
)service
;
3216 if (servicePrivate
->prefs
!= NULL
) {
3217 interfacePrivate
->prefs
= CFRetain(servicePrivate
->prefs
);
3219 if (servicePrivate
->serviceID
!= NULL
) {
3220 interfacePrivate
->serviceID
= CFRetain(servicePrivate
->serviceID
);
3228 _SCNetworkInterfaceMatchesName(CFStringRef name
, CFStringRef key
)
3233 if (bundle
== NULL
) {
3238 if (!isA_CFString(name
)) {
3239 // if no interface "name"
3243 // check non-localized name for a match
3244 str
= copy_interface_string(bundle
, key
, FALSE
);
3246 match
= CFEqual(name
, str
);
3253 // check localized name for a match
3254 str
= copy_interface_string(bundle
, key
, TRUE
);
3256 match
= CFEqual(name
, str
);
3267 SCNetworkInterfaceRef
3268 _SCNetworkInterfaceCreateWithEntity(CFAllocatorRef allocator
,
3269 CFDictionaryRef interface_entity
,
3270 SCNetworkServiceRef service
)
3272 SCNetworkInterfacePrivateRef interfacePrivate
= NULL
;
3273 CFStringRef ifDevice
;
3274 CFStringRef ifName
= NULL
;
3275 CFStringRef ifSubType
;
3277 CFStringRef ifUnique
;
3278 CFArrayRef matching_interfaces
= NULL
;
3280 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
3281 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
3283 ifType
= CFDictionaryGetValue(interface_entity
, kSCPropNetInterfaceType
);
3284 if (ifType
== NULL
) {
3286 * The interface "Type" was not specified. We'll make an
3287 * assumption that this is an "Ethernet" interface. If a
3288 * real interface exists with the provided interface name
3289 * then the actual type will be set accordingly. If not, we'll
3290 * end up crafting an "Ethernet" SCNetworkInterface which
3291 * will keep the rest of the configuration APIs happy.
3293 ifType
= kSCValNetInterfaceTypeEthernet
;
3296 if (!isA_CFString(ifType
)) {
3300 ifSubType
= CFDictionaryGetValue(interface_entity
, kSCPropNetInterfaceSubType
);
3301 if (CFEqual(ifType
, kSCValNetInterfaceTypePPP
) ||
3302 CFEqual(ifType
, kSCValNetInterfaceTypeVPN
)) {
3303 if (!isA_CFString(ifSubType
)) {
3308 ifDevice
= CFDictionaryGetValue(interface_entity
, kSCPropNetInterfaceDeviceName
);
3309 ifUnique
= CFDictionaryGetValue(interface_entity
, CFSTR("DeviceUniqueIdentifier"));
3311 if (CFEqual(ifType
, kSCValNetInterfaceTypeEthernet
) ||
3312 CFEqual(ifType
, kSCValNetInterfaceTypeFireWire
) ||
3313 (CFEqual(ifType
, kSCValNetInterfaceTypePPP
) && CFEqual(ifSubType
, kSCValNetInterfaceSubTypePPPoE
))) {
3314 char bsdName
[IFNAMSIZ
];
3315 CFMutableDictionaryRef matching
;
3317 if (!isA_CFString(ifDevice
)) {
3321 if (CFEqual(ifDevice
, CFSTR("lo0"))) { // for _SCNetworkInterfaceCreateWithBSDName
3322 interfacePrivate
= __SCNetworkInterfaceCreateCopy(NULL
, kSCNetworkInterfaceLoopback
, NULL
, NULL
);
3326 if (_SC_cfstring_to_cstring(ifDevice
, bsdName
, sizeof(bsdName
), kCFStringEncodingASCII
) == NULL
) {
3330 matching
= IOBSDNameMatching(masterPort
, 0, bsdName
);
3331 if (matching
== NULL
) {
3334 matching_interfaces
= findMatchingInterfaces(matching
, processNetworkInterface
);
3335 CFRelease(matching
);
3336 } else if (CFEqual(ifType
, kSCValNetInterfaceTypePPP
)) {
3337 if (CFEqual(ifSubType
, kSCValNetInterfaceSubTypePPPSerial
)) {
3338 CFDictionaryRef matching
;
3339 CFStringRef match_keys
[2];
3340 CFStringRef match_vals
[2];
3342 if (!isA_CFString(ifDevice
)) {
3346 match_keys
[0] = CFSTR(kIOProviderClassKey
);
3347 match_vals
[0] = CFSTR(kIOSerialBSDServiceValue
);
3349 match_keys
[1] = CFSTR(kIOTTYBaseNameKey
);
3350 match_vals
[1] = ifDevice
;
3352 matching
= CFDictionaryCreate(NULL
,
3353 (const void **)match_keys
,
3354 (const void **)match_vals
,
3355 sizeof(match_keys
)/sizeof(match_keys
[0]),
3356 &kCFTypeDictionaryKeyCallBacks
,
3357 &kCFTypeDictionaryValueCallBacks
);
3358 matching_interfaces
= findMatchingInterfaces(matching
, processSerialInterface
);
3359 CFRelease(matching
);
3361 if (ifUnique
== NULL
) {
3363 Boolean useDeviceName
= TRUE
;
3365 n
= (matching_interfaces
!= NULL
) ? CFArrayGetCount(matching_interfaces
) : 0;
3369 for (i
= 0; i
< n
; i
++) {
3370 SCNetworkInterfacePrivateRef scanPrivate
;
3372 scanPrivate
= (SCNetworkInterfacePrivateRef
)CFArrayGetValueAtIndex(matching_interfaces
, i
);
3373 if (scanPrivate
->entity_device_unique
!= NULL
) {
3374 useDeviceName
= FALSE
;
3380 if (useDeviceName
) {
3381 if (matching_interfaces
!= NULL
) {
3382 CFRelease(matching_interfaces
);
3385 match_keys
[1] = CFSTR(kIOTTYDeviceKey
);
3386 matching
= CFDictionaryCreate(NULL
,
3387 (const void **)match_keys
,
3388 (const void **)match_vals
,
3389 sizeof(match_keys
)/sizeof(match_keys
[0]),
3390 &kCFTypeDictionaryKeyCallBacks
,
3391 &kCFTypeDictionaryValueCallBacks
);
3392 matching_interfaces
= findMatchingInterfaces(matching
, processSerialInterface
);
3393 CFRelease(matching
);
3396 } else if (CFEqual(ifSubType
, kSCValNetInterfaceSubTypeL2TP
)) {
3397 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
3398 kSCNetworkInterfaceTypeL2TP
);
3399 } else if (CFEqual(ifSubType
, kSCValNetInterfaceSubTypePPTP
)) {
3400 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
3401 kSCNetworkInterfaceTypePPTP
);
3403 // XXX do we allow non-Apple variants of PPP??? XXX
3404 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
3407 } else if (CFEqual(ifType
, kSCValNetInterfaceType6to4
)) {
3408 if (!isA_CFString(ifDevice
)) {
3412 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
3413 kSCNetworkInterfaceType6to4
);
3414 } else if (CFEqual(ifType
, kSCValNetInterfaceTypeIPSec
)) {
3415 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
3416 kSCNetworkInterfaceTypeIPSec
);
3417 } else if (CFEqual(ifType
, kSCValNetInterfaceTypeLoopback
)) {
3418 interfacePrivate
= __SCNetworkInterfaceCreateCopy(NULL
, kSCNetworkInterfaceLoopback
, NULL
, NULL
);
3419 } else if (CFEqual(ifType
, kSCValNetInterfaceTypeVPN
)) {
3420 if (CFStringFind(ifSubType
, CFSTR("."), 0).location
!= kCFNotFound
) {
3421 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
3424 } else if ((CFStringFind(ifType
, CFSTR("."), 0).location
!= kCFNotFound
) && (ifDevice
== NULL
)) {
3425 interfacePrivate
= (SCNetworkInterfacePrivateRef
)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
,
3429 if (matching_interfaces
!= NULL
) {
3431 SCPreferencesRef prefs
;
3432 Boolean temp_preferences
= FALSE
;
3434 n
= CFArrayGetCount(matching_interfaces
);
3437 interfacePrivate
= (SCNetworkInterfacePrivateRef
)CFArrayGetValueAtIndex(matching_interfaces
, 0);
3438 if (_SC_CFEqual(ifUnique
, interfacePrivate
->entity_device_unique
)) {
3439 // if the unique ID's match
3440 CFRetain(interfacePrivate
);
3444 interfacePrivate
= NULL
;
3447 if (!CFEqual(ifType
, kSCValNetInterfaceTypeEthernet
)) {
3451 if (CFDictionaryGetValueIfPresent(interface_entity
,
3452 kSCPropUserDefinedName
,
3453 (const void **)&ifName
) &&
3454 CFEqual(ifName
, CFSTR(BT_PAN_NAME
))) {
3458 prefs
= (service
!= NULL
) ? ((SCNetworkServicePrivateRef
)service
)->prefs
: NULL
;
3459 if (prefs
== NULL
) {
3460 prefs
= SCPreferencesCreate(NULL
, CFSTR("SCNetworkInterface"), NULL
);
3461 if (prefs
!= NULL
) {
3462 temp_preferences
= TRUE
;
3465 if (prefs
== NULL
) {
3468 #if !TARGET_OS_IPHONE
3469 if (!CFDictionaryContainsKey(interface_entity
, CFSTR("_NO_BOND_INTERFACES_"))) {
3470 interfacePrivate
= (SCNetworkInterfacePrivateRef
)findBondInterface(prefs
, ifDevice
);
3472 #endif // !TARGET_OS_IPHONE
3473 if ((interfacePrivate
== NULL
)
3474 && !CFDictionaryContainsKey(interface_entity
, CFSTR("_NO_BRIDGE_INTERFACES_"))) {
3475 interfacePrivate
= (SCNetworkInterfacePrivateRef
)findBridgeInterface(prefs
, ifDevice
);
3478 if ((interfacePrivate
== NULL
)
3479 && !CFDictionaryContainsKey(interface_entity
, CFSTR("_NO_VLAN_INTERFACES_"))) {
3480 interfacePrivate
= (SCNetworkInterfacePrivateRef
)findVLANInterface(prefs
, ifDevice
);
3482 if (temp_preferences
) CFRelease(prefs
);
3485 if (ifUnique
!= NULL
) {
3488 // we are looking for an interface with a unique ID
3489 // so let's try to focus our choices
3490 for (i
= 0; i
< n
; i
++) {
3491 SCNetworkInterfacePrivateRef scanPrivate
;
3493 scanPrivate
= (SCNetworkInterfacePrivateRef
)CFArrayGetValueAtIndex(matching_interfaces
, i
);
3494 if (_SC_CFEqual(ifUnique
, scanPrivate
->entity_device_unique
)) {
3495 if (interfacePrivate
!= NULL
) {
3496 // if we've matched more than one interface
3497 interfacePrivate
= NULL
;
3500 interfacePrivate
= scanPrivate
;
3503 } else if (CFDictionaryGetValueIfPresent(interface_entity
,
3504 kSCPropUserDefinedName
,
3505 (const void **)&ifName
)) {
3508 // we don't have a unique ID but do have an interface
3509 // name. If the matching interfaces do have IDs than
3510 // we can try to focus our choices using the name
3511 for (i
= 0; i
< n
; i
++) {
3512 SCNetworkInterfacePrivateRef scanPrivate
;
3514 scanPrivate
= (SCNetworkInterfacePrivateRef
)CFArrayGetValueAtIndex(matching_interfaces
, i
);
3515 if (scanPrivate
->entity_device_unique
!= NULL
) {
3516 SCNetworkInterfaceRef scan
= (SCNetworkInterfaceRef
)scanPrivate
;
3517 CFStringRef scanName
;
3519 scanName
= __SCNetworkInterfaceGetNonLocalizedDisplayName(scan
);
3520 if ((scanName
!= NULL
) && !_SC_CFEqual(ifName
, scanName
)) {
3521 continue; // if not the same display name
3525 if (interfacePrivate
!= NULL
) {
3526 // if we've matched more than one interface
3527 interfacePrivate
= NULL
;
3530 interfacePrivate
= scanPrivate
;
3533 if (interfacePrivate
== NULL
) {
3534 SCLog(TRUE
, LOG_ERR
, CFSTR("_SCNetworkInterfaceCreateWithEntity() failed, more than one interface matches %@"), ifDevice
);
3535 interfacePrivate
= (SCNetworkInterfacePrivateRef
)CFArrayGetValueAtIndex(matching_interfaces
, 0);
3537 CFRetain(interfacePrivate
);
3540 CFRelease(matching_interfaces
);
3545 if (interfacePrivate
== NULL
) {
3547 * if device not present on this system
3549 interfacePrivate
= __SCNetworkInterfaceCreatePrivate(NULL
, NULL
, NULL
, NULL
);
3550 interfacePrivate
->entity_type
= ifType
;
3551 interfacePrivate
->entity_subtype
= ifSubType
;
3552 interfacePrivate
->entity_device
= (ifDevice
!= NULL
) ? CFStringCreateCopy(NULL
, ifDevice
) : NULL
;
3553 interfacePrivate
->entity_device_unique
= (ifUnique
!= NULL
) ? CFStringCreateCopy(NULL
, ifUnique
) : NULL
;
3555 if (CFEqual(ifType
, kSCValNetInterfaceTypeEthernet
)) {
3556 CFStringRef entity_hardware
;
3558 entity_hardware
= CFDictionaryGetValue(interface_entity
, kSCPropNetInterfaceHardware
);
3559 if (isA_CFString((entity_hardware
)) &&
3560 CFEqual(entity_hardware
, kSCEntNetAirPort
)) {
3561 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeIEEE80211
;
3562 interfacePrivate
->localized_key
= CFSTR("airport");
3563 interfacePrivate
->sort_order
= kSortAirPort
;
3567 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
;
3569 name
= CFDictionaryGetValue(interface_entity
, kSCPropUserDefinedName
);
3570 if (_SCNetworkInterfaceMatchesName(name
, CFSTR("iPhone"))) {
3571 interfacePrivate
->localized_key
= CFSTR("iPhone");
3572 interfacePrivate
->sort_order
= kSortTethered
;
3573 } else if (_SCNetworkInterfaceMatchesName(name
, CFSTR("iPad"))) {
3574 interfacePrivate
->localized_key
= CFSTR("iPad");
3575 interfacePrivate
->sort_order
= kSortTethered
;
3576 } else if (_SCNetworkInterfaceMatchesName(name
, CFSTR("thunderbolt"))) {
3577 interfacePrivate
->localized_key
= CFSTR("thunderbolt");
3578 interfacePrivate
->sort_order
= kSortThunderbolt
;
3579 } else if (_SCNetworkInterfaceMatchesName(name
, CFSTR("bluetooth-pan-gn"))) {
3580 interfacePrivate
->localized_key
= CFSTR("bluetooth-pan-gn");
3581 interfacePrivate
->sort_order
= kSortBluetoothPAN_GN
;
3582 } else if (_SCNetworkInterfaceMatchesName(name
, CFSTR("bluetooth-pan-nap"))) {
3583 interfacePrivate
->localized_key
= CFSTR("bluetooth-pan-nap");
3584 interfacePrivate
->sort_order
= kSortBluetoothPAN_NAP
;
3585 } else if (_SCNetworkInterfaceMatchesName(name
, CFSTR("bluetooth-pan-u"))) {
3586 interfacePrivate
->localized_key
= CFSTR("bluetooth-pan-u");
3587 interfacePrivate
->sort_order
= kSortBluetoothPAN_U
;
3589 interfacePrivate
->sort_order
= kSortEthernet
;
3592 } else if (CFEqual(ifType
, kSCValNetInterfaceTypeFireWire
)) {
3593 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeFireWire
;
3594 interfacePrivate
->sort_order
= kSortFireWire
;
3595 } else if (CFEqual(ifType
, kSCValNetInterfaceTypePPP
)) {
3596 if (CFEqual(ifSubType
, kSCValNetInterfaceSubTypePPPoE
)) {
3597 CFStringRef entity_hardware
;
3599 entity_hardware
= CFDictionaryGetValue(interface_entity
, kSCPropNetInterfaceHardware
);
3600 if (isA_CFString((entity_hardware
)) &&
3601 CFEqual(entity_hardware
, kSCEntNetAirPort
)) {
3602 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeIEEE80211
;
3603 interfacePrivate
->sort_order
= kSortAirPort
;
3605 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeEthernet
;
3606 interfacePrivate
->sort_order
= kSortEthernet
;
3608 } else if (CFEqual(ifSubType
, kSCValNetInterfaceSubTypePPPSerial
)) {
3609 if (CFStringHasPrefix(ifDevice
, CFSTR("Bluetooth"))) {
3610 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeBluetooth
;
3611 interfacePrivate
->sort_order
= kSortBluetooth
;
3612 } else if (CFStringHasPrefix(ifDevice
, CFSTR("irda"))) {
3613 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeIrDA
;
3614 interfacePrivate
->sort_order
= kSortIrDA
;
3615 } else if (CFStringHasPrefix(ifDevice
, CFSTR("wwan"))) {
3616 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeWWAN
;
3617 interfacePrivate
->sort_order
= kSortWWAN
;
3619 interfacePrivate
->interface_type
= kSCNetworkInterfaceTypeModem
;
3620 interfacePrivate
->sort_order
= kSortModem
;
3623 SCNetworkInterfaceRef child
;
3626 CFRelease(interfacePrivate
);
3627 child
= SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
, ifSubType
);
3628 interfacePrivate
= (SCNetworkInterfacePrivateRef
)child
;
3629 if (interfacePrivate
== NULL
) {
3633 } else if (CFEqual(ifType
, kSCValNetInterfaceTypeVPN
)) {
3634 SCNetworkInterfaceRef child
;
3636 CFRelease(interfacePrivate
);
3637 child
= SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4
, ifSubType
);
3638 interfacePrivate
= (SCNetworkInterfacePrivateRef
)child
;
3639 if (interfacePrivate
== NULL
) {
3642 } else if (CFStringFind(ifType
, CFSTR("."), 0).location
!= kCFNotFound
) {
3643 // if vendor interface
3644 if (vendor_interface_types
== NULL
) {
3645 vendor_interface_types
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
3647 CFSetAddValue(vendor_interface_types
, ifType
);
3649 interfacePrivate
->interface_type
= CFSetGetValue(vendor_interface_types
, ifType
);
3651 // if unknown interface
3652 CFRelease(interfacePrivate
);
3653 interfacePrivate
= NULL
;
3657 if (CFDictionaryContainsKey(interface_entity
, kSCNetworkInterfaceHiddenConfigurationKey
)) {
3658 interfacePrivate
->hidden
= TRUE
;
3662 if (service
!= NULL
) {
3663 __SCNetworkInterfaceSetService((SCNetworkInterfaceRef
)interfacePrivate
,
3666 #if !TARGET_OS_IPHONE
3667 // set prefs & serviceID to Bond member interfaces
3668 if (CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeBond
)) {
3673 members
= SCBondInterfaceGetMemberInterfaces((SCNetworkInterfaceRef
)interfacePrivate
);
3674 n
= (members
!= NULL
) ? CFArrayGetCount(members
) : 0;
3675 for (i
= 0; i
< n
; i
++) {
3676 SCNetworkInterfaceRef member
;
3678 member
= CFArrayGetValueAtIndex(members
, i
);
3679 __SCNetworkInterfaceSetService(member
, service
);
3682 #endif // !TARGET_OS_IPHONE
3684 // set prefs & serviceID to Bridge member interfaces
3685 if (CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeBridge
)) {
3690 members
= SCBridgeInterfaceGetMemberInterfaces((SCNetworkInterfaceRef
)interfacePrivate
);
3691 n
= (members
!= NULL
) ? CFArrayGetCount(members
) : 0;
3692 for (i
= 0; i
< n
; i
++) {
3693 SCNetworkInterfaceRef member
;
3695 member
= CFArrayGetValueAtIndex(members
, i
);
3696 __SCNetworkInterfaceSetService(member
, service
);
3700 // set prefs & serviceID to VLAN pyhsical interface
3701 if (CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeVLAN
)) {
3702 SCNetworkInterfaceRef vlan_physical
;
3704 vlan_physical
= SCVLANInterfaceGetPhysicalInterface((SCNetworkInterfaceRef
)interfacePrivate
);
3705 if (vlan_physical
!= NULL
) {
3706 __SCNetworkInterfaceSetService(vlan_physical
, service
);
3711 if (CFEqual(ifType
, kSCValNetInterfaceTypePPP
)) {
3712 SCNetworkInterfaceRef parent
;
3715 parent
= SCNetworkInterfaceCreateWithInterface((SCNetworkInterfaceRef
)interfacePrivate
,
3716 kSCNetworkInterfaceTypePPP
);
3717 CFRelease(interfacePrivate
);
3718 interfacePrivate
= (SCNetworkInterfacePrivateRef
)parent
;
3719 } else if (CFEqual(ifType
, kSCValNetInterfaceTypeVPN
)) {
3720 SCNetworkInterfaceRef parent
;
3723 parent
= SCNetworkInterfaceCreateWithInterface((SCNetworkInterfaceRef
)interfacePrivate
,
3724 kSCNetworkInterfaceTypeVPN
);
3725 CFRelease(interfacePrivate
);
3726 interfacePrivate
= (SCNetworkInterfacePrivateRef
)parent
;
3729 return (SCNetworkInterfaceRef
)interfacePrivate
;
3734 #pragma mark SCNetworkInterface APIs
3739 __SCNetworkInterfaceCopyAll_IONetworkInterface(void)
3741 CFDictionaryRef matching
;
3742 CFArrayRef new_interfaces
;
3744 // get Ethernet, Firewire, Thunderbolt, and AirPort interfaces
3746 matching
= IOServiceMatching(kIONetworkInterfaceClass
);
3747 new_interfaces
= findMatchingInterfaces(matching
, processNetworkInterface
);
3748 CFRelease(matching
);
3750 return new_interfaces
;
3756 __SCNetworkInterfaceCopyAll_Modem()
3758 CFDictionaryRef matching
;
3759 CFStringRef match_keys
[2];
3760 CFStringRef match_vals
[2];
3761 CFArrayRef new_interfaces
;
3763 match_keys
[0] = CFSTR(kIOProviderClassKey
);
3764 match_vals
[0] = CFSTR(kIOSerialBSDServiceValue
);
3766 match_keys
[1] = CFSTR(kIOSerialBSDTypeKey
);
3767 match_vals
[1] = CFSTR(kIOSerialBSDModemType
);
3769 matching
= CFDictionaryCreate(NULL
,
3770 (const void **)match_keys
,
3771 (const void **)match_vals
,
3772 sizeof(match_keys
)/sizeof(match_keys
[0]),
3773 &kCFTypeDictionaryKeyCallBacks
,
3774 &kCFTypeDictionaryValueCallBacks
);
3775 new_interfaces
= findMatchingInterfaces(matching
, processSerialInterface
);
3776 CFRelease(matching
);
3778 return new_interfaces
;
3784 __SCNetworkInterfaceCopyAll_RS232()
3786 CFDictionaryRef matching
;
3787 CFStringRef match_keys
[2];
3788 CFStringRef match_vals
[2];
3789 CFArrayRef new_interfaces
;
3791 match_keys
[0] = CFSTR(kIOProviderClassKey
);
3792 match_vals
[0] = CFSTR(kIOSerialBSDServiceValue
);
3794 match_keys
[1] = CFSTR(kIOSerialBSDTypeKey
);
3795 match_vals
[1] = CFSTR(kIOSerialBSDRS232Type
);
3797 matching
= CFDictionaryCreate(NULL
,
3798 (const void **)match_keys
,
3799 (const void **)match_vals
,
3800 sizeof(match_keys
)/sizeof(match_keys
[0]),
3801 &kCFTypeDictionaryKeyCallBacks
,
3802 &kCFTypeDictionaryValueCallBacks
);
3803 new_interfaces
= findMatchingInterfaces(matching
, processSerialInterface
);
3804 CFRelease(matching
);
3806 return new_interfaces
;
3810 #if !TARGET_OS_IPHONE
3812 addBTPANInterface(SCPreferencesRef prefs
, CFMutableArrayRef all_interfaces
)
3815 SCNetworkInterfaceRef interface
;
3818 n
= CFArrayGetCount(all_interfaces
);
3819 for (i
= 0; i
< n
; i
++) {
3820 SCNetworkInterfaceRef interface
;
3822 interface
= CFArrayGetValueAtIndex(all_interfaces
, i
);
3823 if (_SCNetworkInterfaceIsBluetoothPAN(interface
)) {
3824 // if we already have a BT-PAN interface
3829 interface
= _SCNetworkInterfaceCopyBTPANInterface();
3830 if (interface
!= NULL
) {
3831 // include BT-PAN interface
3832 CFArrayAppendValue(all_interfaces
, interface
);
3833 CFRelease(interface
);
3838 #endif // !TARGET_OS_IPHONE
3842 add_interfaces(CFMutableArrayRef all_interfaces
, CFArrayRef new_interfaces
)
3847 n
= CFArrayGetCount(new_interfaces
);
3848 for (i
= 0; i
< n
; i
++) {
3849 CFStringRef bsdName
;
3850 SCNetworkInterfaceRef interface
;
3852 interface
= CFArrayGetValueAtIndex(new_interfaces
, i
);
3853 bsdName
= SCNetworkInterfaceGetBSDName(interface
);
3854 if (bsdName
!= NULL
) {
3855 CFArrayAppendValue(all_interfaces
, interface
);
3864 __waitForInterfaces()
3869 SCDynamicStoreRef store
;
3871 store
= SCDynamicStoreCreate(NULL
, CFSTR("SCNetworkInterfaceCopyAll"), NULL
, NULL
);
3872 if (store
== NULL
) {
3876 key
= SCDynamicStoreKeyCreate(NULL
, CFSTR("%@" "InterfaceNamer"), kSCDynamicStoreDomainPlugin
);
3877 keys
= CFArrayCreate(NULL
, (const void **)&key
, 1, &kCFTypeArrayCallBacks
);
3878 ok
= SCDynamicStoreSetNotificationKeys(store
, keys
, NULL
);
3881 SCLog(TRUE
, LOG_ERR
,
3882 CFSTR("SCDynamicStoreSetNotificationKeys() failed: %s"), SCErrorString(SCError()));
3887 CFArrayRef changedKeys
;
3888 CFDictionaryRef dict
;
3889 Boolean quiet
= FALSE
;
3892 dict
= SCDynamicStoreCopyValue(store
, key
);
3894 if (isA_CFDictionary(dict
) &&
3895 (CFDictionaryContainsKey(dict
, CFSTR("*QUIET*")) ||
3896 CFDictionaryContainsKey(dict
, CFSTR("*TIMEOUT*")))) {
3905 ok
= SCDynamicStoreNotifyWait(store
);
3907 SCLog(TRUE
, LOG_ERR
,
3908 CFSTR("SCDynamicStoreNotifyWait() failed: %s"), SCErrorString(SCError()));
3912 changedKeys
= SCDynamicStoreCopyNotifiedKeys(store
);
3913 if (changedKeys
!= NULL
) {
3914 CFRelease(changedKeys
);
3926 CFArrayRef
/* of SCNetworkInterfaceRef's */
3927 _SCNetworkInterfaceCopyAllWithPreferences(SCPreferencesRef prefs
)
3929 CFMutableArrayRef all_interfaces
;
3930 CFArrayRef new_interfaces
;
3931 Boolean temp_preferences
= FALSE
;
3933 /* initialize runtime */
3934 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
3936 /* wait for IOKit to quiesce */
3937 pthread_once(&iokit_quiet
, __waitForInterfaces
);
3939 all_interfaces
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
3941 // get Ethernet, Firewire, Thunderbolt, and AirPort interfaces
3942 new_interfaces
= __SCNetworkInterfaceCopyAll_IONetworkInterface();
3943 if (new_interfaces
!= NULL
) {
3944 add_interfaces(all_interfaces
, new_interfaces
);
3945 CFRelease(new_interfaces
);
3948 // get Modem interfaces
3949 new_interfaces
= __SCNetworkInterfaceCopyAll_Modem();
3950 if (new_interfaces
!= NULL
) {
3951 add_interfaces(all_interfaces
, new_interfaces
);
3952 CFRelease(new_interfaces
);
3955 // get serial (RS232) interfaces
3956 new_interfaces
= __SCNetworkInterfaceCopyAll_RS232();
3957 if (new_interfaces
!= NULL
) {
3958 add_interfaces(all_interfaces
, new_interfaces
);
3959 CFRelease(new_interfaces
);
3962 // get virtual network interfaces (Bond, Bridge, VLAN)
3963 if (prefs
== NULL
) {
3964 prefs
= SCPreferencesCreate(NULL
, CFSTR("SCNetworkInterfaceCopyAll"), NULL
);
3965 if (prefs
!= NULL
) {
3966 temp_preferences
= TRUE
;
3969 if (prefs
!= NULL
) {
3970 #if !TARGET_OS_IPHONE
3971 new_interfaces
= SCBondInterfaceCopyAll(prefs
);
3972 if (new_interfaces
!= NULL
) {
3973 add_interfaces(all_interfaces
, new_interfaces
);
3974 CFRelease(new_interfaces
);
3976 #endif // !TARGET_OS_IPHONE
3978 new_interfaces
= SCBridgeInterfaceCopyAll(prefs
);
3979 if (new_interfaces
!= NULL
) {
3980 add_interfaces(all_interfaces
, new_interfaces
);
3981 CFRelease(new_interfaces
);
3984 new_interfaces
= SCVLANInterfaceCopyAll(prefs
);
3985 if (new_interfaces
!= NULL
) {
3986 add_interfaces(all_interfaces
, new_interfaces
);
3987 CFRelease(new_interfaces
);
3990 #if !TARGET_OS_IPHONE
3991 // add BT-PAN interface
3992 addBTPANInterface(prefs
, all_interfaces
);
3993 #endif // !TARGET_OS_IPHONE
3995 if (temp_preferences
) CFRelease(prefs
);
3998 // all interfaces have been identified, order and return
3999 sort_interfaces(all_interfaces
);
4001 return all_interfaces
;
4005 CFArrayRef
/* of SCNetworkInterfaceRef's */
4006 SCNetworkInterfaceCopyAll()
4008 CFArrayRef all_interfaces
;
4010 all_interfaces
= _SCNetworkInterfaceCopyAllWithPreferences(NULL
);
4011 return all_interfaces
;
4015 CFArrayRef
/* of kSCNetworkInterfaceTypeXXX CFStringRef's */
4016 SCNetworkInterfaceGetSupportedInterfaceTypes(SCNetworkInterfaceRef interface
)
4019 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
4021 if (!isA_SCNetworkInterface(interface
)) {
4022 _SCErrorSet(kSCStatusInvalidArgument
);
4026 if (interfacePrivate
->supported_interface_types
!= NULL
) {
4030 i
= findConfiguration(interfacePrivate
->interface_type
);
4031 if (i
!= kCFNotFound
) {
4032 if (configurations
[i
].supported_interfaces
!= doNone
) {
4033 interfacePrivate
->supported_interface_types
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
4034 if (configurations
[i
].supported_interfaces
& do6to4
) {
4035 CFArrayAppendValue(interfacePrivate
->supported_interface_types
, kSCNetworkInterfaceType6to4
);
4037 if (configurations
[i
].supported_interfaces
& doL2TP
) {
4038 CFArrayAppendValue(interfacePrivate
->supported_interface_types
, kSCNetworkInterfaceTypeL2TP
);
4040 if (configurations
[i
].supported_interfaces
& doPPP
) {
4041 CFArrayAppendValue(interfacePrivate
->supported_interface_types
, kSCNetworkInterfaceTypePPP
);
4043 if (configurations
[i
].supported_interfaces
& doPPTP
) {
4044 CFArrayAppendValue(interfacePrivate
->supported_interface_types
, kSCNetworkInterfaceTypePPTP
);
4046 if (configurations
[i
].supported_interfaces
& doIPSec
) {
4047 CFArrayAppendValue(interfacePrivate
->supported_interface_types
, kSCNetworkInterfaceTypeIPSec
);
4051 SCNetworkInterfaceRef child
;
4053 child
= SCNetworkInterfaceGetInterface(interface
);
4054 if ((child
!= NULL
) && CFEqual(child
, kSCNetworkInterfaceIPv4
)) {
4055 interfacePrivate
->supported_interface_types
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
4056 CFArrayAppendValue(interfacePrivate
->supported_interface_types
, kSCNetworkInterfaceTypeVPN
);
4062 return interfacePrivate
->supported_interface_types
;
4066 CFArrayRef
/* of kSCNetworkProtocolTypeXXX CFStringRef's */
4067 SCNetworkInterfaceGetSupportedProtocolTypes(SCNetworkInterfaceRef interface
)
4070 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
4072 if (!isA_SCNetworkInterface(interface
)) {
4073 _SCErrorSet(kSCStatusInvalidArgument
);
4077 if (interfacePrivate
->supported_protocol_types
!= NULL
) {
4081 i
= findConfiguration(interfacePrivate
->interface_type
);
4082 if (i
!= kCFNotFound
) {
4083 if (configurations
[i
].supported_protocols
!= doNone
) {
4084 interfacePrivate
->supported_protocol_types
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
4085 if (configurations
[i
].supported_protocols
& doDNS
) {
4086 CFArrayAppendValue(interfacePrivate
->supported_protocol_types
, kSCNetworkProtocolTypeDNS
);
4088 if (configurations
[i
].supported_protocols
& doIPv4
) {
4089 CFArrayAppendValue(interfacePrivate
->supported_protocol_types
, kSCNetworkProtocolTypeIPv4
);
4091 if (configurations
[i
].supported_protocols
& doIPv6
) {
4092 CFArrayAppendValue(interfacePrivate
->supported_protocol_types
, kSCNetworkProtocolTypeIPv6
);
4094 if (configurations
[i
].supported_protocols
& doProxies
) {
4095 CFArrayAppendValue(interfacePrivate
->supported_protocol_types
, kSCNetworkProtocolTypeProxies
);
4097 #if !TARGET_OS_IPHONE
4098 if (configurations
[i
].supported_protocols
& doSMB
) {
4099 CFArrayAppendValue(interfacePrivate
->supported_protocol_types
, kSCNetworkProtocolTypeSMB
);
4101 #endif // !TARGET_OS_IPHONE
4107 return interfacePrivate
->supported_protocol_types
;
4111 SCNetworkInterfaceRef
4112 SCNetworkInterfaceCreateWithInterface(SCNetworkInterfaceRef child
, CFStringRef interfaceType
)
4114 SCNetworkInterfacePrivateRef childPrivate
= (SCNetworkInterfacePrivateRef
)child
;
4116 SCNetworkInterfacePrivateRef parentPrivate
;
4118 if (!isA_SCNetworkInterface(child
)) {
4119 _SCErrorSet(kSCStatusInvalidArgument
);
4123 if (!isA_CFString(interfaceType
)) {
4124 _SCErrorSet(kSCStatusInvalidArgument
);
4128 if (CFEqual(child
, kSCNetworkInterfaceLoopback
)) {
4129 // can't layer on top of loopback
4130 _SCErrorSet(kSCStatusInvalidArgument
);
4134 childIndex
= findConfiguration(childPrivate
->interface_type
);
4136 parentPrivate
= __SCNetworkInterfaceCreatePrivate(NULL
,
4138 childPrivate
->prefs
,
4139 childPrivate
->serviceID
);
4140 if (parentPrivate
== NULL
) {
4141 _SCErrorSet(kSCStatusFailed
);
4145 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
)) {
4146 parentPrivate
->interface_type
= kSCNetworkInterfaceTypePPP
;
4147 parentPrivate
->entity_type
= kSCValNetInterfaceTypePPP
;
4150 if (childIndex
!= kCFNotFound
) {
4151 if (configurations
[childIndex
].ppp_subtype
!= NULL
) {
4152 parentPrivate
->entity_subtype
= *configurations
[childIndex
].ppp_subtype
;
4154 // sorry, the child interface does not support PPP
4158 // if the child's interface type not known, use the child entities "Type"
4159 parentPrivate
->entity_subtype
= childPrivate
->entity_type
;
4162 if (childPrivate
->entity_device
!= NULL
) {
4163 parentPrivate
->entity_device
= CFStringCreateCopy(NULL
, childPrivate
->entity_device
);
4166 if (childPrivate
->entity_device_unique
!= NULL
) {
4167 parentPrivate
->entity_device_unique
= CFStringCreateCopy(NULL
, childPrivate
->entity_device_unique
);
4169 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeL2TP
)) {
4170 if ((childIndex
== kCFNotFound
) ||
4171 ((configurations
[childIndex
].supported_interfaces
& doL2TP
) != doL2TP
)) {
4172 // if the child interface does not support L2TP
4175 parentPrivate
->interface_type
= kSCNetworkInterfaceTypeL2TP
;
4176 parentPrivate
->localized_key
= CFSTR("l2tp");
4177 parentPrivate
->entity_type
= kSCEntNetL2TP
; // interface config goes into "L2TP"
4178 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPTP
)) {
4179 if ((childIndex
== kCFNotFound
) ||
4180 ((configurations
[childIndex
].supported_interfaces
& doPPTP
) != doPPTP
)) {
4181 // if the child interface does not support PPTP
4184 parentPrivate
->interface_type
= kSCNetworkInterfaceTypePPTP
;
4185 parentPrivate
->localized_key
= CFSTR("pptp");
4186 parentPrivate
->entity_type
= kSCEntNetPPTP
; // interface config goes into "PPTP"
4187 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceType6to4
)) {
4188 if ((childIndex
== kCFNotFound
) ||
4189 ((configurations
[childIndex
].supported_interfaces
& do6to4
) != do6to4
)) {
4190 // if the child interface does not support 6to4
4194 parentPrivate
->interface_type
= kSCNetworkInterfaceType6to4
;
4195 parentPrivate
->localized_key
= CFSTR("6to4");
4196 parentPrivate
->entity_type
= kSCValNetInterfaceType6to4
;
4197 parentPrivate
->entity_device
= CFRetain(CFSTR("stf0"));
4198 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeIPSec
)) {
4199 if ((childIndex
== kCFNotFound
) ||
4200 ((configurations
[childIndex
].supported_interfaces
& doIPSec
) != doIPSec
)) {
4201 // if the child interface does not support IPSec
4204 parentPrivate
->interface_type
= kSCNetworkInterfaceTypeIPSec
;
4205 parentPrivate
->localized_key
= CFSTR("ipsec");
4206 parentPrivate
->entity_type
= kSCValNetInterfaceTypeIPSec
;
4207 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeVPN
)) {
4208 if (childIndex
!= kCFNotFound
) {
4209 // if not a "vendor" child interface
4213 parentPrivate
->interface_type
= kSCNetworkInterfaceTypeVPN
;
4214 parentPrivate
->localized_key
= CFSTR("vpn");
4215 parentPrivate
->localized_arg1
= CFRetain(childPrivate
->entity_type
);
4216 parentPrivate
->entity_type
= kSCValNetInterfaceTypeVPN
;
4217 parentPrivate
->entity_subtype
= childPrivate
->entity_type
;
4218 if (childPrivate
->entity_device
!= NULL
) {
4219 parentPrivate
->entity_device
= CFStringCreateCopy(NULL
, childPrivate
->entity_device
);
4221 if (parentPrivate
->entity_subtype
!= NULL
) {
4222 CFArrayRef components
;
4224 CFStringRef vpnType
;
4227 // the "default" interface name is derived from the VPN type
4230 // com.apple.Apple-VPN.vpnplugin --> "Apple VPN"
4233 vpnType
= parentPrivate
->entity_subtype
;
4234 components
= CFStringCreateArrayBySeparatingStrings(NULL
, vpnType
, CFSTR("."));
4235 n
= CFArrayGetCount(components
);
4237 CFEqual(CFArrayGetValueAtIndex(components
, n
- 1), CFSTR("vpnplugin"))) {
4238 CFMutableStringRef str
;
4240 str
= CFStringCreateMutableCopy(NULL
,
4242 CFArrayGetValueAtIndex(components
, n
- 2));
4243 (void) CFStringFindAndReplace(str
,
4246 CFRangeMake(0, CFStringGetLength(str
)),
4248 parentPrivate
->localized_name
= str
;
4250 CFRelease(components
);
4252 } else if (CFStringFind(interfaceType
, CFSTR("."), 0).location
!= kCFNotFound
) {
4253 // if custom interface type
4254 if (vendor_interface_types
== NULL
) {
4255 vendor_interface_types
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
4257 CFSetAddValue(vendor_interface_types
, interfaceType
);
4259 parentPrivate
->interface_type
= CFSetGetValue(vendor_interface_types
, interfaceType
);
4260 parentPrivate
->entity_type
= parentPrivate
->interface_type
; // interface config goes into a
4261 // a dictionary with the same
4262 // name as the interfaceType
4264 // unknown interface type
4268 parentPrivate
->hidden
= childPrivate
->hidden
;
4270 if (childPrivate
->overrides
!= NULL
) {
4271 parentPrivate
->overrides
= CFDictionaryCreateMutableCopy(NULL
, 0, childPrivate
->overrides
);
4274 // The following change handles the case where a user has both an Ethernet and
4275 // PPPoE network service. Because a PPPoE service is typically associated with
4276 // an ISP we want it to be sorted higher in the service order.
4277 if ((parentPrivate
->entity_subtype
!= NULL
) &&
4278 (CFEqual(parentPrivate
->entity_subtype
, kSCValNetInterfaceSubTypePPPoE
))) {
4279 if ((childPrivate
->interface_type
!= NULL
) &&
4280 (CFEqual(childPrivate
->interface_type
, kSCNetworkInterfaceTypeIEEE80211
))) {
4281 parentPrivate
->sort_order
= kSortAirportPPP
;
4283 parentPrivate
->sort_order
= kSortEthernetPPP
;
4286 // set sort order of the parent to match the child interface
4287 parentPrivate
->sort_order
= childPrivate
->sort_order
;
4290 return (SCNetworkInterfaceRef
)parentPrivate
;
4294 CFRelease(parentPrivate
);
4295 _SCErrorSet(kSCStatusInvalidArgument
);
4302 __SCNetworkInterfaceGetDefaultConfiguration(SCNetworkSetRef set
, SCNetworkInterfaceRef interface
)
4304 CFDictionaryRef config
= NULL
;
4305 CFStringRef defaultType
;
4306 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
4308 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
4309 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
4311 defaultType
= __SCNetworkInterfaceGetDefaultConfigurationType(interface
);
4312 if (defaultType
!= NULL
) {
4316 path
= SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL
, // allocator
4317 SCNetworkSetGetSetID(set
), // set
4318 interfacePrivate
->entity_device
, // interface
4319 defaultType
); // entity
4321 config
= __getPrefsConfiguration(interfacePrivate
->prefs
, path
);
4324 if (config
== NULL
) {
4325 // if the "set" does not have a saved configuration, use
4326 // the [template] "interface" configuration
4327 if (interfacePrivate
->unsaved
!= NULL
) {
4328 config
= CFDictionaryGetValue(interfacePrivate
->unsaved
, defaultType
);
4329 if (config
== (CFDictionaryRef
)kCFNull
) {
4334 if (isA_CFDictionary(config
) && (CFDictionaryGetCount(config
) == 0)) {
4345 static CFDictionaryRef
4346 __SCNetworkInterfaceGetConfiguration(SCNetworkInterfaceRef interface
,
4347 CFStringRef extendedType
)
4349 CFDictionaryRef config
= NULL
;
4350 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
4353 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
4354 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
4356 paths
= copyConfigurationPaths(interfacePrivate
, extendedType
);
4357 if (paths
!= NULL
) {
4360 path
= CFArrayGetValueAtIndex(paths
, 0);
4361 config
= __getPrefsConfiguration(interfacePrivate
->prefs
, path
);
4365 if (interfacePrivate
->unsaved
!= NULL
) {
4366 config
= CFDictionaryGetValue(interfacePrivate
->unsaved
, extendedType
);
4367 if (config
== (CFDictionaryRef
)kCFNull
) {
4373 if (isA_CFDictionary(config
) && (CFDictionaryGetCount(config
) == 0)) {
4382 SCNetworkInterfaceGetConfiguration(SCNetworkInterfaceRef interface
)
4384 CFDictionaryRef config
;
4385 CFStringRef defaultType
;
4387 if (!isA_SCNetworkInterface(interface
)) {
4388 _SCErrorSet(kSCStatusInvalidArgument
);
4392 defaultType
= __SCNetworkInterfaceGetDefaultConfigurationType(interface
);
4393 if (defaultType
== NULL
) {
4397 config
= __SCNetworkInterfaceGetConfiguration(interface
, defaultType
);
4398 if (config
== NULL
) {
4399 if (CFEqual(defaultType
, kSCEntNetAirPort
)) {
4400 SCNetworkInterfacePrivateRef interfacePrivate
;
4403 // if AirPort interface, check for a per-service config
4404 interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
4405 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
4406 interfacePrivate
->serviceID
, // service
4407 kSCEntNetAirPort
); // entity
4408 config
= __getPrefsConfiguration(interfacePrivate
->prefs
, path
);
4412 if (config
== NULL
) {
4413 _SCErrorSet(kSCStatusOK
);
4421 SCNetworkInterfaceGetExtendedConfiguration(SCNetworkInterfaceRef interface
,
4422 CFStringRef extendedType
)
4424 CFDictionaryRef config
;
4426 if (!isA_SCNetworkInterface(interface
)) {
4427 _SCErrorSet(kSCStatusInvalidArgument
);
4431 if (!__SCNetworkInterfaceIsValidExtendedConfigurationType(interface
, extendedType
, TRUE
)) {
4432 _SCErrorSet(kSCStatusInvalidArgument
);
4436 config
= __SCNetworkInterfaceGetConfiguration(interface
, extendedType
);
4437 if (config
== NULL
) {
4438 _SCErrorSet(kSCStatusOK
);
4446 SCNetworkInterfaceGetBSDName(SCNetworkInterfaceRef interface
)
4448 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
4450 if (!isA_SCNetworkInterface(interface
)) {
4451 _SCErrorSet(kSCStatusInvalidArgument
);
4455 if ((interfacePrivate
->interface
!= NULL
) &&
4456 (interfacePrivate
->interface
!= kSCNetworkInterfaceIPv4
)) {
4457 _SCErrorSet(kSCStatusOK
);
4461 return interfacePrivate
->entity_device
;
4466 SCNetworkInterfaceGetHardwareAddressString(SCNetworkInterfaceRef interface
)
4468 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
4470 if (!isA_SCNetworkInterface(interface
)) {
4471 _SCErrorSet(kSCStatusInvalidArgument
);
4475 if ((interfacePrivate
->address
!= NULL
) &&
4476 (interfacePrivate
->addressString
== NULL
)) {
4480 char mac
[sizeof("xx:xx:xx:xx:xx:xx:xx:xx")];
4483 bp
= (uint8_t *)CFDataGetBytePtr(interfacePrivate
->address
);
4484 n
= CFDataGetLength(interfacePrivate
->address
) * 3;
4486 if (n
> sizeof(mac
)) {
4487 mac_p
= CFAllocatorAllocate(NULL
, 0, n
);
4490 for (cp
= mac_p
; n
> 0; n
-= 3) {
4491 cp
+= snprintf(cp
, n
, "%2.2x:", *bp
++);
4494 interfacePrivate
->addressString
= CFStringCreateWithCString(NULL
, mac_p
, kCFStringEncodingUTF8
);
4495 if (mac_p
!= mac
) CFAllocatorDeallocate(NULL
, mac_p
);
4498 return interfacePrivate
->addressString
;
4502 SCNetworkInterfaceRef
4503 SCNetworkInterfaceGetInterface(SCNetworkInterfaceRef interface
)
4505 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
4507 if (!isA_SCNetworkInterface(interface
)) {
4508 _SCErrorSet(kSCStatusInvalidArgument
);
4512 return interfacePrivate
->interface
;
4517 SCNetworkInterfaceGetInterfaceType(SCNetworkInterfaceRef interface
)
4519 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
4521 if (!isA_SCNetworkInterface(interface
)) {
4522 _SCErrorSet(kSCStatusInvalidArgument
);
4526 return interfacePrivate
->interface_type
;
4531 copy_interface_string(CFBundleRef bundle
, CFStringRef key
, Boolean localized
)
4533 CFStringRef str
= NULL
;
4536 str
= CFBundleCopyLocalizedString(bundle
,
4539 NETWORKINTERFACE_LOCALIZATIONS
);
4541 str
= _SC_CFBundleCopyNonLocalizedString(bundle
,
4544 NETWORKINTERFACE_LOCALIZATIONS
);
4552 copy_display_name(SCNetworkInterfaceRef interface
, Boolean localized
, Boolean oldLocalization
)
4554 CFMutableStringRef local
;
4557 local
= CFStringCreateMutable(NULL
, 0);
4559 while (interface
!= NULL
) {
4560 Boolean added
= FALSE
;
4561 SCNetworkInterfaceRef child
= NULL
;
4562 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
4564 if ((interfacePrivate
->interface
!= NULL
) &&
4565 (interfacePrivate
->interface
!= kSCNetworkInterfaceIPv4
) &&
4566 !CFEqual(interfacePrivate
->interface_type
, kSCNetworkInterfaceTypeVPN
)) {
4567 child
= interfacePrivate
->interface
;
4570 if ((bundle
!= NULL
) && (interfacePrivate
->localized_key
!= NULL
)) {
4572 CFStringRef key
= interfacePrivate
->localized_key
;
4574 if (oldLocalization
) {
4575 key
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("X-%@"),
4576 interfacePrivate
->localized_key
);
4578 fmt
= copy_interface_string(bundle
, key
, localized
);
4580 CFStringAppendFormat(local
,
4583 interfacePrivate
->localized_arg1
,
4584 interfacePrivate
->localized_arg2
);
4588 if (oldLocalization
) {
4594 (interfacePrivate
->prefs
!= NULL
) &&
4595 (interfacePrivate
->serviceID
!= NULL
) &&
4597 CFDictionaryRef entity
;
4600 // check for (and use) the name of the interface when it
4601 // was last available
4602 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
,
4603 interfacePrivate
->serviceID
,
4604 kSCEntNetInterface
);
4605 entity
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
4607 if (isA_CFDictionary(entity
)) {
4610 name
= CFDictionaryGetValue(entity
, kSCPropUserDefinedName
);
4611 if (isA_CFString(name
)) {
4612 CFStringAppend(local
, name
);
4619 // create (non-)localized name based on the interface type
4620 CFStringAppend(local
, interfacePrivate
->interface_type
);
4622 // ... and, if this is a leaf node, the interface device
4623 if ((interfacePrivate
->entity_device
!= NULL
) && (child
== NULL
)) {
4624 CFStringAppendFormat(local
, NULL
, CFSTR(" (%@)"), interfacePrivate
->entity_device
);
4628 if (child
!= NULL
) {
4629 // if this interface is layered over another
4630 CFStringAppend(local
, CFSTR(" --> "));
4636 name
= CFStringCreateCopy(NULL
, local
);
4643 #if !TARGET_OS_IPHONE
4646 __SCNetworkInterfaceCopyXLocalizedDisplayName(SCNetworkInterfaceRef interface
)
4650 if (!isA_SCNetworkInterface(interface
)) {
4651 _SCErrorSet(kSCStatusInvalidArgument
);
4655 name
= copy_display_name(interface
, TRUE
, TRUE
);
4662 __SCNetworkInterfaceCopyXNonLocalizedDisplayName(SCNetworkInterfaceRef interface
)
4664 CFStringRef localized_name
;
4666 if (!isA_SCNetworkInterface(interface
)) {
4667 _SCErrorSet(kSCStatusInvalidArgument
);
4671 localized_name
= copy_display_name(interface
, FALSE
, TRUE
);
4672 return localized_name
;
4674 #endif // !TARGET_OS_IPHONE
4679 __SCNetworkInterfaceGetNonLocalizedDisplayName(SCNetworkInterfaceRef interface
)
4681 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
4683 if (!isA_SCNetworkInterface(interface
)) {
4684 _SCErrorSet(kSCStatusInvalidArgument
);
4688 if (interfacePrivate
->name
== NULL
) {
4689 interfacePrivate
->name
= copy_display_name(interface
, FALSE
, FALSE
);
4692 return interfacePrivate
->name
;
4697 SCNetworkInterfaceGetLocalizedDisplayName(SCNetworkInterfaceRef interface
)
4699 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
4701 if (!isA_SCNetworkInterface(interface
)) {
4702 _SCErrorSet(kSCStatusInvalidArgument
);
4706 if (interfacePrivate
->localized_name
== NULL
) {
4707 interfacePrivate
->localized_name
= copy_display_name(interface
, TRUE
, FALSE
);
4710 return interfacePrivate
->localized_name
;
4716 __SCNetworkInterfaceGetTemplateOverrides(SCNetworkInterfaceRef interface
, CFStringRef overrideType
)
4718 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
4719 CFDictionaryRef overrides
= NULL
;
4721 if (interfacePrivate
->overrides
!= NULL
) {
4722 overrides
= CFDictionaryGetValue(interfacePrivate
->overrides
, overrideType
);
4730 SCNetworkInterfaceGetTypeID(void)
4732 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
); /* initialize runtime */
4733 return __kSCNetworkInterfaceTypeID
;
4739 __SCNetworkInterfaceSetDefaultConfiguration(SCNetworkSetRef set
,
4740 SCNetworkInterfaceRef interface
,
4741 CFStringRef defaultType
,
4742 CFDictionaryRef config
,
4745 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
4748 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
4749 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
4751 if (defaultType
== NULL
) {
4752 defaultType
= __SCNetworkInterfaceGetDefaultConfigurationType(interface
);
4753 if (defaultType
== NULL
) {
4758 if (isA_CFDictionary(config
) && (CFDictionaryGetCount(config
) == 0)) {
4765 path
= SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL
, // allocator
4766 SCNetworkSetGetSetID(set
), // set
4767 interfacePrivate
->entity_device
, // interface
4768 defaultType
); // entity
4770 ok
= __setPrefsConfiguration(interfacePrivate
->prefs
, path
, config
, FALSE
);
4773 // if configuration has been saved
4774 if (interfacePrivate
->unsaved
!= NULL
) {
4775 CFDictionaryRemoveValue(interfacePrivate
->unsaved
, defaultType
);
4776 if (CFDictionaryGetCount(interfacePrivate
->unsaved
) == 0) {
4777 CFRelease(interfacePrivate
->unsaved
);
4778 interfacePrivate
->unsaved
= NULL
;
4784 if (config
== NULL
) {
4785 // remember that we are clearing the configuration
4786 config
= (CFDictionaryRef
)kCFNull
;
4789 if (interfacePrivate
->unsaved
== NULL
) {
4790 interfacePrivate
->unsaved
= CFDictionaryCreateMutable(NULL
,
4792 &kCFTypeDictionaryKeyCallBacks
,
4793 &kCFTypeDictionaryValueCallBacks
);
4795 CFDictionarySetValue(interfacePrivate
->unsaved
, defaultType
, config
);
4798 _SCErrorSet(kSCStatusNoKey
);
4809 __SCNetworkInterfaceSetConfiguration(SCNetworkInterfaceRef interface
,
4810 CFStringRef extendedType
,
4811 CFDictionaryRef config
,
4814 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
4818 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
4819 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
4821 if (extendedType
== NULL
) {
4822 extendedType
= __SCNetworkInterfaceGetDefaultConfigurationType(interface
);
4823 if (extendedType
== NULL
) {
4828 if (isA_CFDictionary(config
) && (CFDictionaryGetCount(config
) == 0)) {
4832 paths
= copyConfigurationPaths(interfacePrivate
, extendedType
);
4833 if (paths
!= NULL
) {
4837 n
= CFArrayGetCount(paths
);
4838 for (i
= 0; i
< n
; i
++) {
4841 path
= CFArrayGetValueAtIndex(paths
, i
);
4842 ok
= __setPrefsConfiguration(interfacePrivate
->prefs
, path
, config
, FALSE
);
4849 // if configuration has been saved
4850 if (interfacePrivate
->unsaved
!= NULL
) {
4851 CFDictionaryRemoveValue(interfacePrivate
->unsaved
, extendedType
);
4852 if (CFDictionaryGetCount(interfacePrivate
->unsaved
) == 0) {
4853 CFRelease(interfacePrivate
->unsaved
);
4854 interfacePrivate
->unsaved
= NULL
;
4862 if (config
== NULL
) {
4863 // remember that we are clearing the configuration
4864 config
= (CFDictionaryRef
)kCFNull
;
4867 if (interfacePrivate
->unsaved
== NULL
) {
4868 interfacePrivate
->unsaved
= CFDictionaryCreateMutable(NULL
,
4870 &kCFTypeDictionaryKeyCallBacks
,
4871 &kCFTypeDictionaryValueCallBacks
);
4873 CFDictionarySetValue(interfacePrivate
->unsaved
, extendedType
, config
);
4876 _SCErrorSet(kSCStatusNoKey
);
4885 SCNetworkInterfaceSetConfiguration(SCNetworkInterfaceRef interface
, CFDictionaryRef config
)
4887 CFStringRef defaultType
;
4889 if (!isA_SCNetworkInterface(interface
)) {
4890 _SCErrorSet(kSCStatusInvalidArgument
);
4894 defaultType
= __SCNetworkInterfaceGetDefaultConfigurationType(interface
);
4895 if (defaultType
== NULL
) {
4899 return __SCNetworkInterfaceSetConfiguration(interface
, defaultType
, config
, FALSE
);
4904 SCNetworkInterfaceSetExtendedConfiguration(SCNetworkInterfaceRef interface
,
4905 CFStringRef extendedType
,
4906 CFDictionaryRef config
)
4908 if (!isA_SCNetworkInterface(interface
)) {
4909 _SCErrorSet(kSCStatusInvalidArgument
);
4913 if (!__SCNetworkInterfaceIsValidExtendedConfigurationType(interface
, extendedType
, TRUE
)) {
4917 return __SCNetworkInterfaceSetConfiguration(interface
, extendedType
, config
, FALSE
);
4922 #pragma mark SCNetworkInterface [Refresh Configuration] API
4925 #ifndef kSCEntNetRefreshConfiguration
4926 #define kSCEntNetRefreshConfiguration CFSTR("RefreshConfiguration")
4927 #endif // kSCEntNetRefreshConfiguration
4930 _SCNetworkInterfaceForceConfigurationRefresh(CFStringRef ifName
)
4935 if (!isA_CFString(ifName
)) {
4936 _SCErrorSet(kSCStatusInvalidArgument
);
4940 key
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
,
4941 kSCDynamicStoreDomainState
,
4943 kSCEntNetRefreshConfiguration
);
4944 ok
= SCDynamicStoreNotifyValue(NULL
, key
);
4951 __SCNetworkInterfaceForceConfigurationRefresh_helper(SCPreferencesRef prefs
, CFStringRef ifName
)
4953 CFDataRef data
= NULL
;
4955 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
4956 uint32_t status
= kSCStatusOK
;
4957 CFDataRef reply
= NULL
;
4959 if (prefsPrivate
->helper_port
== MACH_PORT_NULL
) {
4960 ok
= __SCPreferencesCreate_helper(prefs
);
4966 // serialize the interface name
4967 ok
= _SCSerializeString(ifName
, &data
, NULL
, NULL
);
4972 // have the helper "refresh" the configuration
4973 status
= kSCStatusOK
;
4975 ok
= _SCHelperExec(prefsPrivate
->helper_port
,
4976 SCHELPER_MSG_INTERFACE_REFRESH
,
4980 if (data
!= NULL
) CFRelease(data
);
4985 if (status
!= kSCStatusOK
) {
4994 if (prefsPrivate
->helper_port
!= MACH_PORT_NULL
) {
4995 _SCHelperClose(&prefsPrivate
->helper_port
);
4998 status
= kSCStatusAccessError
;
5003 _SCErrorSet(status
);
5009 SCNetworkInterfaceForceConfigurationRefresh(SCNetworkInterfaceRef interface
)
5012 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
5014 if (!isA_SCNetworkInterface(interface
)) {
5015 _SCErrorSet(kSCStatusInvalidArgument
);
5019 ifName
= SCNetworkInterfaceGetBSDName(interface
);
5020 if (ifName
== NULL
) {
5021 _SCErrorSet(kSCStatusInvalidArgument
);
5025 if (interfacePrivate
->prefs
!= NULL
) {
5026 SCPreferencesRef prefs
= interfacePrivate
->prefs
;
5027 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
5029 if (prefsPrivate
->authorizationData
!= NULL
) {
5030 return __SCNetworkInterfaceForceConfigurationRefresh_helper(prefs
, ifName
);
5034 return _SCNetworkInterfaceForceConfigurationRefresh(ifName
);
5039 SCNetworkInterfaceRefreshConfiguration(CFStringRef ifName
)
5041 return _SCNetworkInterfaceForceConfigurationRefresh(ifName
);
5046 #pragma mark SCNetworkInterface Password APIs
5050 getPasswordID(CFDictionaryRef config
, CFStringRef serviceID
)
5052 CFStringRef unique_id
= NULL
;
5054 if (config
!= NULL
) {
5055 CFStringRef encryption
;
5057 encryption
= CFDictionaryGetValue(config
, kSCPropNetPPPAuthPasswordEncryption
);
5058 if (isA_CFString(encryption
) &&
5059 CFEqual(encryption
, kSCValNetPPPAuthPasswordEncryptionKeychain
)) {
5060 unique_id
= CFDictionaryGetValue(config
, kSCPropNetPPPAuthPassword
);
5063 if (unique_id
== NULL
) {
5064 unique_id
= serviceID
;
5072 copySharedSecretID(CFDictionaryRef config
, CFStringRef serviceID
)
5074 CFMutableStringRef shared_id
= NULL
;
5076 if (config
!= NULL
) {
5077 CFStringRef encryption
;
5079 encryption
= CFDictionaryGetValue(config
, kSCPropNetIPSecSharedSecretEncryption
);
5080 if (isA_CFString(encryption
) &&
5081 CFEqual(encryption
, kSCValNetIPSecSharedSecretEncryptionKeychain
)) {
5082 shared_id
= (CFMutableStringRef
)CFDictionaryGetValue(config
, kSCPropNetIPSecSharedSecret
);
5083 if (shared_id
!= NULL
) {
5084 CFRetain(shared_id
);
5089 if (shared_id
== NULL
) {
5090 CFStringRef unique_id
;
5092 unique_id
= getPasswordID(config
, serviceID
);
5093 shared_id
= CFStringCreateMutableCopy(NULL
, 0, unique_id
);
5094 CFStringAppend(shared_id
, CFSTR(".SS"));
5102 copyXAuthID(CFDictionaryRef config
, CFStringRef serviceID
)
5104 CFMutableStringRef xauth_id
= NULL
;
5106 if (config
!= NULL
) {
5107 CFStringRef encryption
;
5109 encryption
= CFDictionaryGetValue(config
, kSCPropNetIPSecXAuthPasswordEncryption
);
5110 if (isA_CFString(encryption
) &&
5111 CFEqual(encryption
, kSCValNetIPSecXAuthPasswordEncryptionKeychain
)) {
5112 xauth_id
= (CFMutableStringRef
)CFDictionaryGetValue(config
, kSCPropNetIPSecXAuthPassword
);
5113 if (xauth_id
!= NULL
) {
5119 if (xauth_id
== NULL
) {
5120 CFStringRef unique_id
;
5122 unique_id
= getPasswordID(config
, serviceID
);
5123 xauth_id
= CFStringCreateMutableCopy(NULL
, 0, unique_id
);
5124 CFStringAppend(xauth_id
, CFSTR(".XAUTH"));
5132 checkInterfacePassword(SCNetworkInterfaceRef interface
,
5133 SCNetworkInterfacePasswordType passwordType
,
5134 SCPreferencesRef
*prefs
,
5135 CFStringRef
*serviceID
)
5137 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
5139 if (!isA_SCNetworkInterface(interface
)) {
5143 *serviceID
= interfacePrivate
->serviceID
;
5144 if (*serviceID
== NULL
) {
5148 *prefs
= interfacePrivate
->prefs
;
5149 if (*prefs
== NULL
) {
5153 switch (passwordType
) {
5154 case kSCNetworkInterfacePasswordTypePPP
: {
5155 CFStringRef interfaceType
;
5157 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
5158 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
)) {
5166 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret
: {
5167 CFStringRef interfaceType
;
5169 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
5170 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
)) {
5171 interface
= SCNetworkInterfaceGetInterface(interface
);
5172 if (interface
!= NULL
) {
5173 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
5174 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeL2TP
)) {
5175 // if PPP->L2TP interface
5179 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeIPSec
)) {
5180 // if IPSec interface
5187 case kSCNetworkInterfacePasswordTypeEAPOL
: {
5191 case kSCNetworkInterfacePasswordTypeIPSecXAuth
: {
5192 CFStringRef interfaceType
;
5194 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
5195 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeIPSec
)) {
5196 // if IPSec interface
5203 case kSCNetworkInterfacePasswordTypeVPN
: {
5204 CFStringRef interfaceType
;
5206 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
5207 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeVPN
)) {
5223 _SCErrorSet(kSCStatusInvalidArgument
);
5229 SCNetworkInterfaceCheckPassword(SCNetworkInterfaceRef interface
,
5230 SCNetworkInterfacePasswordType passwordType
)
5232 Boolean exists
= FALSE
;
5233 SCPreferencesRef prefs
= NULL
;
5234 CFStringRef serviceID
= NULL
;
5236 if (!checkInterfacePassword(interface
, passwordType
, &prefs
, &serviceID
)) {
5240 switch (passwordType
) {
5241 case kSCNetworkInterfacePasswordTypePPP
: {
5242 CFDictionaryRef config
;
5243 CFStringRef unique_id
;
5245 // get configuration
5246 config
= SCNetworkInterfaceGetConfiguration(interface
);
5249 unique_id
= getPasswordID(config
, serviceID
);
5252 exists
= __extract_password(prefs
,
5254 kSCPropNetPPPAuthPassword
,
5255 kSCPropNetPPPAuthPasswordEncryption
,
5256 kSCValNetPPPAuthPasswordEncryptionKeychain
,
5262 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret
: {
5263 CFDictionaryRef config
;
5265 CFStringRef shared_id
;
5267 // get configuration
5268 extended
= CFEqual(SCNetworkInterfaceGetInterfaceType(interface
), kSCNetworkInterfaceTypePPP
);
5270 config
= SCNetworkInterfaceGetExtendedConfiguration(interface
, kSCEntNetIPSec
);
5272 config
= SCNetworkInterfaceGetConfiguration(interface
);
5275 // get sharedSecret ID
5276 shared_id
= copySharedSecretID(config
, serviceID
);
5279 exists
= __extract_password(prefs
,
5281 kSCPropNetIPSecSharedSecret
,
5282 kSCPropNetIPSecSharedSecretEncryption
,
5283 kSCValNetIPSecSharedSecretEncryptionKeychain
,
5286 CFRelease(shared_id
);
5290 case kSCNetworkInterfacePasswordTypeEAPOL
: {
5291 CFDictionaryRef config
;
5292 CFStringRef unique_id
= NULL
;
5294 // get configuration
5295 config
= SCNetworkInterfaceGetExtendedConfiguration(interface
, kSCEntNetEAPOL
);
5297 // get 802.1X identifier
5298 if (config
!= NULL
) {
5299 unique_id
= CFDictionaryGetValue(config
, kEAPClientPropUserPasswordKeychainItemID
);
5301 if (!isA_CFString(unique_id
)) {
5306 exists
= _SCPreferencesSystemKeychainPasswordItemExists(prefs
, unique_id
);
5310 case kSCNetworkInterfacePasswordTypeIPSecXAuth
: {
5311 CFDictionaryRef config
;
5312 CFStringRef xauth_id
;
5314 // get configuration
5315 config
= SCNetworkInterfaceGetConfiguration(interface
);
5318 xauth_id
= copyXAuthID(config
, serviceID
);
5321 exists
= __extract_password(prefs
,
5323 kSCPropNetIPSecXAuthPassword
,
5324 kSCPropNetIPSecXAuthPasswordEncryption
,
5325 kSCValNetIPSecXAuthPasswordEncryptionKeychain
,
5328 CFRelease(xauth_id
);
5332 case kSCNetworkInterfacePasswordTypeVPN
: {
5333 CFDictionaryRef config
;
5336 // get configuration
5337 config
= SCNetworkInterfaceGetConfiguration(interface
);
5340 vpn_id
= getPasswordID(config
, serviceID
);
5343 exists
= __extract_password(prefs
,
5345 kSCPropNetVPNAuthPassword
,
5346 kSCPropNetVPNAuthPasswordEncryption
,
5347 kSCValNetVPNAuthPasswordEncryptionKeychain
,
5354 _SCErrorSet(kSCStatusInvalidArgument
);
5363 SCNetworkInterfaceCopyPassword(SCNetworkInterfaceRef interface
,
5364 SCNetworkInterfacePasswordType passwordType
)
5366 CFDataRef password
= NULL
;
5367 SCPreferencesRef prefs
= NULL
;
5368 CFStringRef serviceID
= NULL
;
5370 if (!checkInterfacePassword(interface
, passwordType
, &prefs
, &serviceID
)) {
5374 switch (passwordType
) {
5375 case kSCNetworkInterfacePasswordTypePPP
: {
5376 CFDictionaryRef config
;
5377 CFStringRef unique_id
;
5379 // get configuration
5380 config
= SCNetworkInterfaceGetConfiguration(interface
);
5383 unique_id
= getPasswordID(config
, serviceID
);
5386 (void) __extract_password(prefs
,
5388 kSCPropNetPPPAuthPassword
,
5389 kSCPropNetPPPAuthPasswordEncryption
,
5390 kSCValNetPPPAuthPasswordEncryptionKeychain
,
5396 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret
: {
5397 CFDictionaryRef config
;
5399 CFStringRef shared_id
;
5401 // get configuration
5402 extended
= CFEqual(SCNetworkInterfaceGetInterfaceType(interface
), kSCNetworkInterfaceTypePPP
);
5404 config
= SCNetworkInterfaceGetExtendedConfiguration(interface
, kSCEntNetIPSec
);
5406 config
= SCNetworkInterfaceGetConfiguration(interface
);
5409 // get sharedSecret ID
5410 shared_id
= copySharedSecretID(config
, serviceID
);
5413 (void) __extract_password(prefs
,
5415 kSCPropNetIPSecSharedSecret
,
5416 kSCPropNetIPSecSharedSecretEncryption
,
5417 kSCValNetIPSecSharedSecretEncryptionKeychain
,
5421 CFRelease(shared_id
);
5425 case kSCNetworkInterfacePasswordTypeEAPOL
: {
5426 CFDictionaryRef config
;
5427 CFStringRef unique_id
= NULL
;
5429 // get configuration
5430 config
= SCNetworkInterfaceGetExtendedConfiguration(interface
, kSCEntNetEAPOL
);
5432 // get 802.1X identifier
5433 if (config
!= NULL
) {
5434 unique_id
= CFDictionaryGetValue(config
, kEAPClientPropUserPasswordKeychainItemID
);
5436 if (!isA_CFString(unique_id
)) {
5437 _SCErrorSet(kSCStatusFailed
);
5442 password
= _SCPreferencesSystemKeychainPasswordItemCopy(prefs
, unique_id
);
5446 case kSCNetworkInterfacePasswordTypeIPSecXAuth
: {
5447 CFDictionaryRef config
;
5448 CFStringRef xauth_id
;
5450 // get configuration
5451 config
= SCNetworkInterfaceGetConfiguration(interface
);
5454 xauth_id
= copyXAuthID(config
, serviceID
);
5457 (void) __extract_password(prefs
,
5459 kSCPropNetIPSecXAuthPassword
,
5460 kSCPropNetIPSecXAuthPasswordEncryption
,
5461 kSCValNetIPSecXAuthPasswordEncryptionKeychain
,
5464 CFRelease(xauth_id
);
5468 case kSCNetworkInterfacePasswordTypeVPN
: {
5469 CFDictionaryRef config
;
5472 // get configuration
5473 config
= SCNetworkInterfaceGetConfiguration(interface
);
5476 vpn_id
= getPasswordID(config
, serviceID
);
5479 (void) __extract_password(prefs
,
5481 kSCPropNetVPNAuthPassword
,
5482 kSCPropNetVPNAuthPasswordEncryption
,
5483 kSCValNetVPNAuthPasswordEncryptionKeychain
,
5490 _SCErrorSet(kSCStatusInvalidArgument
);
5499 SCNetworkInterfaceRemovePassword(SCNetworkInterfaceRef interface
,
5500 SCNetworkInterfacePasswordType passwordType
)
5503 SCPreferencesRef prefs
= NULL
;
5504 CFStringRef serviceID
= NULL
;
5506 if (!checkInterfacePassword(interface
, passwordType
, &prefs
, &serviceID
)) {
5510 switch (passwordType
) {
5511 case kSCNetworkInterfacePasswordTypePPP
: {
5512 CFDictionaryRef config
;
5513 CFDictionaryRef newConfig
= NULL
;
5514 CFStringRef unique_id
;
5516 // get configuration
5517 config
= SCNetworkInterfaceGetConfiguration(interface
);
5520 unique_id
= getPasswordID(config
, serviceID
);
5523 ok
= __remove_password(prefs
,
5525 kSCPropNetPPPAuthPassword
,
5526 kSCPropNetPPPAuthPasswordEncryption
,
5527 kSCValNetPPPAuthPasswordEncryptionKeychain
,
5531 ok
= SCNetworkInterfaceSetConfiguration(interface
, newConfig
);
5532 if (newConfig
!= NULL
) CFRelease(newConfig
);
5538 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret
: {
5539 CFDictionaryRef config
;
5541 CFDictionaryRef newConfig
= NULL
;
5542 CFStringRef shared_id
;
5544 // get configuration
5545 extended
= CFEqual(SCNetworkInterfaceGetInterfaceType(interface
), kSCNetworkInterfaceTypePPP
);
5547 config
= SCNetworkInterfaceGetExtendedConfiguration(interface
, kSCEntNetIPSec
);
5549 config
= SCNetworkInterfaceGetConfiguration(interface
);
5552 // get sharedSecret ID
5553 shared_id
= copySharedSecretID(config
, serviceID
);
5556 ok
= __remove_password(prefs
,
5558 kSCPropNetIPSecSharedSecret
,
5559 kSCPropNetIPSecSharedSecretEncryption
,
5560 kSCValNetIPSecSharedSecretEncryptionKeychain
,
5565 ok
= SCNetworkInterfaceSetExtendedConfiguration(interface
,
5569 ok
= SCNetworkInterfaceSetConfiguration(interface
,
5572 if (newConfig
!= NULL
) CFRelease(newConfig
);
5575 CFRelease(shared_id
);
5579 case kSCNetworkInterfacePasswordTypeEAPOL
: {
5580 CFDictionaryRef config
;
5581 CFStringRef unique_id
= NULL
;
5583 // get configuration
5584 config
= SCNetworkInterfaceGetExtendedConfiguration(interface
, kSCEntNetEAPOL
);
5586 // get 802.1X identifier
5587 if (config
!= NULL
) {
5588 unique_id
= CFDictionaryGetValue(config
, kEAPClientPropUserPasswordKeychainItemID
);
5590 if (!isA_CFString(unique_id
)) {
5591 _SCErrorSet(kSCStatusFailed
);
5596 ok
= _SCPreferencesSystemKeychainPasswordItemRemove(prefs
, unique_id
);
5600 case kSCNetworkInterfacePasswordTypeIPSecXAuth
: {
5601 CFDictionaryRef config
;
5602 CFDictionaryRef newConfig
= NULL
;
5603 CFStringRef xauth_id
;
5605 // get configuration
5606 config
= SCNetworkInterfaceGetConfiguration(interface
);
5609 xauth_id
= copyXAuthID(config
, serviceID
);
5612 ok
= __remove_password(prefs
,
5614 kSCPropNetIPSecXAuthPassword
,
5615 kSCPropNetIPSecXAuthPasswordEncryption
,
5616 kSCValNetIPSecXAuthPasswordEncryptionKeychain
,
5620 ok
= SCNetworkInterfaceSetConfiguration(interface
, newConfig
);
5621 if (newConfig
!= NULL
) CFRelease(newConfig
);
5624 CFRelease(xauth_id
);
5628 case kSCNetworkInterfacePasswordTypeVPN
: {
5629 CFDictionaryRef config
;
5630 CFDictionaryRef newConfig
= NULL
;
5633 // get configuration
5634 config
= SCNetworkInterfaceGetConfiguration(interface
);
5637 vpn_id
= getPasswordID(config
, serviceID
);
5640 ok
= __remove_password(prefs
,
5642 kSCPropNetVPNAuthPassword
,
5643 kSCPropNetVPNAuthPasswordEncryption
,
5644 kSCValNetVPNAuthPasswordEncryptionKeychain
,
5648 ok
= SCNetworkInterfaceSetConfiguration(interface
, newConfig
);
5649 if (newConfig
!= NULL
) CFRelease(newConfig
);
5655 _SCErrorSet(kSCStatusInvalidArgument
);
5664 SCNetworkInterfaceSetPassword(SCNetworkInterfaceRef interface
,
5665 SCNetworkInterfacePasswordType passwordType
,
5667 CFDictionaryRef options
)
5669 CFStringRef account
= NULL
;
5670 CFDictionaryRef config
;
5671 CFStringRef description
= NULL
;
5672 CFStringRef label
= NULL
;
5674 SCPreferencesRef prefs
= NULL
;
5675 CFStringRef serviceID
= NULL
;
5677 if (!checkInterfacePassword(interface
, passwordType
, &prefs
, &serviceID
)) {
5681 switch (passwordType
) {
5682 case kSCNetworkInterfacePasswordTypePPP
: {
5683 SCNetworkServiceRef service
= NULL
;
5684 CFStringRef unique_id
;
5686 // get configuration
5687 config
= SCNetworkInterfaceGetConfiguration(interface
);
5690 unique_id
= getPasswordID(config
, serviceID
);
5692 // get "Account", "Name", "Kind"
5693 if (config
!= NULL
) {
5694 // auth name --> keychain "Account"
5695 account
= CFDictionaryGetValue(config
, kSCPropNetPPPAuthName
);
5697 // PPP [user defined] "name" --> keychain "Name"
5698 label
= CFDictionaryGetValue(config
, kSCPropUserDefinedName
);
5701 if (label
== NULL
) {
5702 // service name --> keychain "Name"
5703 service
= (SCNetworkServiceRef
)__SCNetworkServiceCreatePrivate(NULL
,
5708 label
= SCNetworkServiceGetName(service
);
5709 if (label
== NULL
) {
5710 // interface name --> keychain "Name"
5711 label
= SCNetworkInterfaceGetLocalizedDisplayName(interface
);
5715 if (bundle
!= NULL
) {
5716 // "PPP Password" --> keychain "Kind"
5717 description
= CFBundleCopyLocalizedString(bundle
,
5718 CFSTR("KEYCHAIN_KIND_PPP_PASSWORD"),
5719 CFSTR("PPP Password"),
5724 ok
= _SCPreferencesSystemKeychainPasswordItemSet(prefs
,
5726 (label
!= NULL
) ? label
: CFSTR("Network Connection"),
5727 (description
!= NULL
) ? description
: CFSTR("PPP Password"),
5732 CFMutableDictionaryRef newConfig
;
5734 if (config
!= NULL
) {
5735 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
5737 newConfig
= CFDictionaryCreateMutable(NULL
,
5739 &kCFTypeDictionaryKeyCallBacks
,
5740 &kCFTypeDictionaryValueCallBacks
);
5742 CFDictionarySetValue(newConfig
,
5743 kSCPropNetPPPAuthPassword
,
5745 CFDictionarySetValue(newConfig
,
5746 kSCPropNetPPPAuthPasswordEncryption
,
5747 kSCValNetPPPAuthPasswordEncryptionKeychain
);
5748 ok
= SCNetworkInterfaceSetConfiguration(interface
, newConfig
);
5749 CFRelease(newConfig
);
5752 if (description
!= NULL
) CFRelease(description
);
5753 if (service
!= NULL
) CFRelease(service
);
5757 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret
: {
5758 CFDictionaryRef baseConfig
= NULL
;
5760 SCNetworkServiceRef service
= NULL
;
5761 CFStringRef shared_id
;
5763 // get configuration
5764 extended
= CFEqual(SCNetworkInterfaceGetInterfaceType(interface
), kSCNetworkInterfaceTypePPP
);
5765 config
= SCNetworkInterfaceGetConfiguration(interface
);
5767 baseConfig
= config
;
5768 config
= SCNetworkInterfaceGetExtendedConfiguration(interface
, kSCEntNetIPSec
);
5771 // get sharedSecret ID
5772 shared_id
= copySharedSecretID(config
, serviceID
);
5774 // get "Account", "Name", "Kind"
5775 if (config
!= NULL
) {
5776 CFStringRef localIdentifier
;
5777 CFStringRef localIdentifierType
;
5779 if (CFDictionaryGetValueIfPresent(config
,
5780 kSCPropNetIPSecLocalIdentifierType
,
5781 (const void **)&localIdentifierType
)
5782 && CFEqual(localIdentifierType
, kSCValNetIPSecLocalIdentifierTypeKeyID
)
5783 && CFDictionaryGetValueIfPresent(config
,
5784 kSCPropNetIPSecLocalIdentifier
,
5785 (const void **)&localIdentifier
)
5786 && isA_CFString(localIdentifier
)) {
5787 // local identifier --> keychain "Account"
5788 account
= localIdentifier
;
5791 // PPP [user defined] "name" --> keychain "Name"
5793 label
= CFDictionaryGetValue(config
, kSCPropUserDefinedName
);
5795 if (baseConfig
!= NULL
) {
5796 label
= CFDictionaryGetValue(baseConfig
, kSCPropUserDefinedName
);
5801 if (label
== NULL
) {
5802 // service name --> keychain "Name"
5803 service
= (SCNetworkServiceRef
)__SCNetworkServiceCreatePrivate(NULL
,
5808 label
= SCNetworkServiceGetName(service
);
5809 if (label
== NULL
) {
5810 // interface name --> keychain "Name"
5811 label
= SCNetworkInterfaceGetLocalizedDisplayName(interface
);
5815 if (bundle
!= NULL
) {
5816 // "IPSec Shared Secret" --> keychain "Kind"
5817 description
= CFBundleCopyLocalizedString(bundle
,
5818 CFSTR("KEYCHAIN_KIND_IPSEC_SHARED_SECRET"),
5819 CFSTR("IPSec Shared Secret"),
5824 ok
= _SCPreferencesSystemKeychainPasswordItemSet(prefs
,
5826 (label
!= NULL
) ? label
: CFSTR("Network Connection"),
5827 (description
!= NULL
) ? description
: CFSTR("IPSec Shared Secret"),
5832 CFMutableDictionaryRef newConfig
= NULL
;
5834 if (config
!= NULL
) {
5835 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
5837 newConfig
= CFDictionaryCreateMutable(NULL
,
5839 &kCFTypeDictionaryKeyCallBacks
,
5840 &kCFTypeDictionaryValueCallBacks
);
5842 CFDictionarySetValue(newConfig
,
5843 kSCPropNetIPSecSharedSecret
,
5845 CFDictionarySetValue(newConfig
,
5846 kSCPropNetIPSecSharedSecretEncryption
,
5847 kSCValNetIPSecSharedSecretEncryptionKeychain
);
5849 ok
= SCNetworkInterfaceSetExtendedConfiguration(interface
,
5853 ok
= SCNetworkInterfaceSetConfiguration(interface
, newConfig
);
5855 CFRelease(newConfig
);
5858 if (description
!= NULL
) CFRelease(description
);
5859 if (service
!= NULL
) CFRelease(service
);
5860 CFRelease(shared_id
);
5864 case kSCNetworkInterfacePasswordTypeEAPOL
: {
5865 CFStringRef account
= NULL
;
5866 CFStringRef unique_id
= NULL
;
5868 // get configuration
5869 config
= SCNetworkInterfaceGetExtendedConfiguration(interface
, kSCEntNetEAPOL
);
5871 // get 802.1X identifier
5872 if (config
!= NULL
) {
5873 unique_id
= CFDictionaryGetValue(config
, kEAPClientPropUserPasswordKeychainItemID
);
5874 unique_id
= isA_CFString(unique_id
);
5876 if (unique_id
!= NULL
) {
5877 CFRetain(unique_id
);
5881 uuid
= CFUUIDCreate(NULL
);
5882 unique_id
= CFUUIDCreateString(NULL
, uuid
);
5886 // 802.1x UserName --> keychain "Account"
5887 if (config
!= NULL
) {
5888 account
= CFDictionaryGetValue(config
, kEAPClientPropUserName
);
5891 // get "Name", "Kind"
5892 if (bundle
!= NULL
) {
5893 CFStringRef interface_name
;
5895 // "Network Connection (%@)" --> keychain "Name"
5896 interface_name
= SCNetworkInterfaceGetLocalizedDisplayName(interface
);
5897 if (interface_name
!= NULL
) {
5898 CFStringRef label_fmt
;
5900 label_fmt
= CFBundleCopyLocalizedString(bundle
,
5901 CFSTR("KEYCHAIN_DESCRIPTION_EAPOL_INTERFACE"),
5902 CFSTR("Network Connection (%@)"),
5904 label
= CFStringCreateWithFormat(NULL
, NULL
, label_fmt
, interface_name
);
5905 CFRelease(label_fmt
);
5907 label
= CFBundleCopyLocalizedString(bundle
,
5908 CFSTR("KEYCHAIN_DESCRIPTION_EAPOL"),
5909 CFSTR("Network Connection"),
5913 // "802.1X Password" --> keychain "Kind"
5914 description
= CFBundleCopyLocalizedString(bundle
,
5915 CFSTR("KEYCHAIN_KIND_EAPOL"),
5916 CFSTR("802.1X Password"),
5921 ok
= _SCPreferencesSystemKeychainPasswordItemSet(prefs
,
5923 (label
!= NULL
) ? label
: CFSTR("Network Connection"),
5924 (description
!= NULL
) ? description
: CFSTR("802.1X Password"),
5929 CFMutableDictionaryRef newConfig
= NULL
;
5931 if (config
!= NULL
) {
5932 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
5934 newConfig
= CFDictionaryCreateMutable(NULL
,
5936 &kCFTypeDictionaryKeyCallBacks
,
5937 &kCFTypeDictionaryValueCallBacks
);
5939 CFDictionarySetValue(newConfig
,
5940 kEAPClientPropUserPasswordKeychainItemID
,
5942 ok
= SCNetworkInterfaceSetExtendedConfiguration(interface
,
5945 CFRelease(newConfig
);
5948 CFRelease(unique_id
);
5949 if (label
!= NULL
) CFRelease(label
);
5950 if (description
!= NULL
) CFRelease(description
);
5954 case kSCNetworkInterfacePasswordTypeIPSecXAuth
: {
5955 SCNetworkServiceRef service
= NULL
;
5956 CFStringRef xauth_id
;
5958 // get configuration
5959 config
= SCNetworkInterfaceGetConfiguration(interface
);
5962 xauth_id
= copyXAuthID(config
, serviceID
);
5964 // get "Account", "Name", "Kind"
5965 if (config
!= NULL
) {
5966 // auth name --> keychain "Account"
5967 account
= CFDictionaryGetValue(config
, kSCPropNetIPSecXAuthName
);
5969 // IPSec [user defined] "name" --> keychain "Name"
5970 label
= CFDictionaryGetValue(config
, kSCPropUserDefinedName
);
5973 if (label
== NULL
) {
5974 // service name --> keychain "Name"
5975 service
= (SCNetworkServiceRef
)__SCNetworkServiceCreatePrivate(NULL
,
5980 label
= SCNetworkServiceGetName(service
);
5981 if (label
== NULL
) {
5982 // interface name --> keychain "Name"
5983 label
= SCNetworkInterfaceGetLocalizedDisplayName(interface
);
5987 if (bundle
!= NULL
) {
5988 // "IPSec XAuth Password" --> keychain "Kind"
5989 description
= CFBundleCopyLocalizedString(bundle
,
5990 CFSTR("KEYCHAIN_KIND_IPSEC_XAUTH_PASSWORD"),
5991 CFSTR("IPSec XAuth Password"),
5996 ok
= _SCPreferencesSystemKeychainPasswordItemSet(prefs
,
5998 (label
!= NULL
) ? label
: CFSTR("Network Connection"),
5999 (description
!= NULL
) ? description
: CFSTR("IPSec XAuth Password"),
6004 CFMutableDictionaryRef newConfig
;
6006 if (config
!= NULL
) {
6007 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
6009 newConfig
= CFDictionaryCreateMutable(NULL
,
6011 &kCFTypeDictionaryKeyCallBacks
,
6012 &kCFTypeDictionaryValueCallBacks
);
6014 CFDictionarySetValue(newConfig
,
6015 kSCPropNetIPSecXAuthPassword
,
6017 CFDictionarySetValue(newConfig
,
6018 kSCPropNetIPSecXAuthPasswordEncryption
,
6019 kSCValNetIPSecXAuthPasswordEncryptionKeychain
);
6020 ok
= SCNetworkInterfaceSetConfiguration(interface
, newConfig
);
6021 CFRelease(newConfig
);
6024 CFRelease(xauth_id
);
6025 if (description
!= NULL
) CFRelease(description
);
6026 if (service
!= NULL
) CFRelease(service
);
6030 case kSCNetworkInterfacePasswordTypeVPN
: {
6031 SCNetworkServiceRef service
= NULL
;
6034 // get configuration
6035 config
= SCNetworkInterfaceGetConfiguration(interface
);
6038 vpn_id
= getPasswordID(config
, serviceID
);
6040 // get "Account", "Name", "Kind"
6041 if (config
!= NULL
) {
6042 // auth name --> keychain "Account"
6043 account
= CFDictionaryGetValue(config
, kSCPropNetVPNAuthName
);
6045 // VPN [user defined] "name" --> keychain "Name"
6046 label
= CFDictionaryGetValue(config
, kSCPropUserDefinedName
);
6049 if (label
== NULL
) {
6050 // service name --> keychain "Name"
6051 service
= (SCNetworkServiceRef
)__SCNetworkServiceCreatePrivate(NULL
,
6056 label
= SCNetworkServiceGetName(service
);
6057 if (label
== NULL
) {
6058 // interface name --> keychain "Name"
6059 label
= SCNetworkInterfaceGetLocalizedDisplayName(interface
);
6063 if (bundle
!= NULL
) {
6064 // "VPN Password" --> keychain "Kind"
6065 description
= CFBundleCopyLocalizedString(bundle
,
6066 CFSTR("KEYCHAIN_KIND_VPN_PASSWORD"),
6067 CFSTR("VPN Password"),
6072 ok
= _SCPreferencesSystemKeychainPasswordItemSet(prefs
,
6074 (label
!= NULL
) ? label
: CFSTR("Network Connection"),
6075 (description
!= NULL
) ? description
: CFSTR("VPN Password"),
6080 CFMutableDictionaryRef newConfig
;
6082 if (config
!= NULL
) {
6083 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
6085 newConfig
= CFDictionaryCreateMutable(NULL
,
6087 &kCFTypeDictionaryKeyCallBacks
,
6088 &kCFTypeDictionaryValueCallBacks
);
6090 CFDictionarySetValue(newConfig
,
6091 kSCPropNetVPNAuthPassword
,
6093 CFDictionarySetValue(newConfig
,
6094 kSCPropNetVPNAuthPasswordEncryption
,
6095 kSCValNetVPNAuthPasswordEncryptionKeychain
);
6096 ok
= SCNetworkInterfaceSetConfiguration(interface
, newConfig
);
6097 CFRelease(newConfig
);
6100 if (description
!= NULL
) CFRelease(description
);
6101 if (service
!= NULL
) CFRelease(service
);
6106 _SCErrorSet(kSCStatusInvalidArgument
);
6115 #pragma mark SCNetworkInterface [InterfaceNamer] SPIs
6119 _SCNetworkInterfaceCopyInterfaceInfo(SCNetworkInterfaceRef interface
)
6121 CFMutableDictionaryRef info
;
6122 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6125 if (interface
== NULL
) {
6129 info
= CFDictionaryCreateMutable(NULL
,
6131 &kCFTypeDictionaryKeyCallBacks
,
6132 &kCFTypeDictionaryValueCallBacks
);
6134 // add non-localized interface name
6135 name
= __SCNetworkInterfaceGetNonLocalizedDisplayName(interface
);
6137 CFDictionaryAddValue(info
, kSCPropUserDefinedName
, name
);
6141 if ((interfacePrivate
->usb
.vid
!= NULL
) || (interfacePrivate
->usb
.pid
!= NULL
)) {
6142 #if !TARGET_IPHONE_SIMULATOR
6143 if (interfacePrivate
->usb
.name
!= NULL
) {
6144 CFDictionaryAddValue(info
, CFSTR(kUSBProductString
), interfacePrivate
->usb
.name
);
6146 if (interfacePrivate
->usb
.vid
!= NULL
) {
6147 CFDictionaryAddValue(info
, CFSTR(kUSBVendorID
), interfacePrivate
->usb
.vid
);
6149 if (interfacePrivate
->usb
.pid
!= NULL
) {
6150 CFDictionaryAddValue(info
, CFSTR(kUSBProductID
), interfacePrivate
->usb
.pid
);
6152 #endif // !TARGET_IPHONE_SIMULATOR
6155 if (CFDictionaryGetCount(info
) == 0) {
6156 // do not return an empty dictionary
6165 SCNetworkInterfaceRef
6166 _SCNetworkInterfaceCreateWithIONetworkInterfaceObject(io_object_t if_obj
)
6168 SCNetworkInterfaceRef interface
= NULL
;
6170 /* initialize runtime */
6171 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
6173 if (IOObjectConformsTo(if_obj
, kIONetworkInterfaceClass
)) {
6174 interface
= createInterface(if_obj
, processNetworkInterface
);
6175 } else if (IOObjectConformsTo(if_obj
, kIOSerialBSDServiceValue
)) {
6176 interface
= createInterface(if_obj
, processSerialInterface
);
6184 _SCNetworkInterfaceGetConfigurationAction(SCNetworkInterfaceRef interface
)
6186 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6188 return interfacePrivate
->configurationAction
;
6193 _SCNetworkInterfaceGetHardwareAddress(SCNetworkInterfaceRef interface
)
6195 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6197 return interfacePrivate
->address
;
6202 _SCNetworkInterfaceGetIOInterfaceNamePrefix(SCNetworkInterfaceRef interface
)
6204 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6206 return interfacePrivate
->prefix
;
6211 _SCNetworkInterfaceGetIOInterfaceType(SCNetworkInterfaceRef interface
)
6213 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6215 return interfacePrivate
->type
;
6220 _SCNetworkInterfaceGetIOInterfaceUnit(SCNetworkInterfaceRef interface
)
6222 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6224 return interfacePrivate
->unit
;
6229 _SCNetworkInterfaceGetIOPath(SCNetworkInterfaceRef interface
)
6231 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6233 return interfacePrivate
->path
;
6238 _SCNetworkInterfaceGetIORegistryEntryID(SCNetworkInterfaceRef interface
)
6240 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6242 return interfacePrivate
->entryID
;
6247 _SCNetworkInterfaceIsBuiltin(SCNetworkInterfaceRef interface
)
6249 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6251 return interfacePrivate
->builtin
;
6256 #pragma mark SCNetworkInterface SPIs
6259 #if !TARGET_OS_EMBEDDED
6261 SCNetworkInterfaceRef
6262 _SCNetworkInterfaceCopyBTPANInterface(void)
6264 CFDictionaryRef dict
;
6265 SCNetworkInterfaceRef interface
= NULL
;
6268 key
= SCDynamicStoreKeyCreate(NULL
, CFSTR("%@" "InterfaceNamer"), kSCDynamicStoreDomainPlugin
);
6269 dict
= SCDynamicStoreCopyValue(NULL
, key
);
6272 CFStringRef if_name
;
6274 if (isA_CFDictionary(dict
) &&
6275 CFDictionaryGetValueIfPresent(dict
,
6276 CFSTR("_" BT_PAN_NAME
"_"),
6277 (const void **)&if_name
) &&
6278 isA_CFString(if_name
)) {
6279 CFMutableDictionaryRef entity
;
6281 entity
= CFDictionaryCreateMutable(NULL
,
6283 &kCFTypeDictionaryKeyCallBacks
,
6284 &kCFTypeDictionaryValueCallBacks
);
6285 CFDictionarySetValue(entity
,
6286 kSCPropNetInterfaceType
,
6287 kSCValNetInterfaceTypeEthernet
);
6288 CFDictionarySetValue(entity
,
6289 kSCPropNetInterfaceDeviceName
,
6291 CFDictionarySetValue(entity
,
6292 kSCPropUserDefinedName
,
6293 CFSTR(BT_PAN_NAME
));
6294 interface
= _SCNetworkInterfaceCreateWithEntity(NULL
, entity
, NULL
);
6303 #endif // !TARGET_OS_EMBEDDED
6307 _SCNetworkInterfaceCopySlashDevPath(SCNetworkInterfaceRef interface
)
6309 io_registry_entry_t device
;
6310 io_iterator_t device_iterator
= MACH_PORT_NULL
;
6311 CFStringRef device_path
= NULL
;
6312 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6314 CFStringRef match_keys
[2];
6315 CFTypeRef match_vals
[2];
6316 CFDictionaryRef match_dict
;
6317 CFDictionaryRef matching
;
6319 if (interfacePrivate
->entity_device
== NULL
) {
6323 if (interfacePrivate
->entity_device_unique
== NULL
) {
6327 match_keys
[0] = CFSTR(kIOTTYBaseNameKey
);
6328 match_vals
[0] = interfacePrivate
->entity_device
;
6329 match_dict
= CFDictionaryCreate(NULL
,
6330 (const void **)match_keys
,
6331 (const void **)match_vals
,
6333 &kCFTypeDictionaryKeyCallBacks
,
6334 &kCFTypeDictionaryValueCallBacks
);
6336 match_keys
[0] = CFSTR(kIOProviderClassKey
);
6337 match_vals
[0] = CFSTR(kIOSerialBSDServiceValue
);
6338 match_keys
[1] = CFSTR(kIOPropertyMatchKey
);
6339 match_vals
[1] = match_dict
;
6340 matching
= CFDictionaryCreate(NULL
,
6341 (const void **)match_keys
,
6342 (const void **)match_vals
,
6343 sizeof(match_keys
)/sizeof(match_keys
[0]),
6344 &kCFTypeDictionaryKeyCallBacks
,
6345 &kCFTypeDictionaryValueCallBacks
);
6346 CFRelease(match_dict
);
6348 // note: this "matching" dictionary will be consumed by the call to IOServiceGetMatchingServices
6349 kr
= IOServiceGetMatchingServices(masterPort
, matching
, &device_iterator
);
6350 if (kr
!= kIOReturnSuccess
) {
6351 SCLog(TRUE
, LOG_DEBUG
, CFSTR("IOServiceGetMatchingServices() failed, kr = 0x%x"), kr
);
6355 while ((device_path
== NULL
) &&
6356 ((device
= IOIteratorNext(device_iterator
)) != MACH_PORT_NULL
)) {
6357 CFDictionaryRef overrides
;
6359 overrides
= IORegistryEntrySearchCFProperty(device
,
6361 kSCNetworkInterfaceNetworkConfigurationOverridesKey
,
6363 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
6364 if (overrides
!= NULL
) {
6365 CFDictionaryRef modemOverrides
;
6367 modemOverrides
= CFDictionaryGetValue(overrides
, kSCEntNetModem
);
6368 if (modemOverrides
!= NULL
) {
6369 CFRetain(modemOverrides
);
6371 CFRelease(overrides
);
6372 overrides
= modemOverrides
;
6374 if (overrides
== NULL
) {
6375 overrides
= IORegistryEntrySearchCFProperty(device
,
6377 CFSTR("DeviceModemOverrides"),
6379 kIORegistryIterateRecursively
| kIORegistryIterateParents
);
6381 if (overrides
!= NULL
) {
6382 if (isA_CFDictionary(overrides
)) {
6383 CFStringRef matchIdentifier
;
6385 matchIdentifier
= CFDictionaryGetValue(overrides
, CFSTR("UniqueIdentifier"));
6386 if (isA_CFString(matchIdentifier
) &&
6387 CFEqual(interfacePrivate
->entity_device_unique
, matchIdentifier
)) {
6388 device_path
= IORegistryEntryCreateCFProperty(device
,
6389 CFSTR(kIOTTYDeviceKey
),
6394 CFRelease(overrides
);
6396 IOObjectRelease(device
);
6399 IOObjectRelease(device_iterator
);
6403 if (device_path
== NULL
) {
6404 // if we haven't found an exact match to our UniqueIdentifier
6405 // so we simply return the base name.
6406 device_path
= SCNetworkInterfaceGetBSDName(interface
);
6407 if (device_path
!= NULL
) {
6408 CFRetain(device_path
);
6417 _SCNetworkInterfaceIsBluetoothPAN(SCNetworkInterfaceRef interface
)
6419 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6421 return (interfacePrivate
->sort_order
== kSortBluetoothPAN_GN
);
6426 _SCNetworkInterfaceIsBluetoothPAN_NAP(SCNetworkInterfaceRef interface
)
6428 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6430 return (interfacePrivate
->sort_order
== kSortBluetoothPAN_NAP
);
6435 _SCNetworkInterfaceIsBluetoothP2P(SCNetworkInterfaceRef interface
)
6437 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6439 return (interfacePrivate
->sort_order
== kSortBluetoothPAN_U
);
6444 _SCNetworkInterfaceIsHiddenConfiguration(SCNetworkInterfaceRef interface
)
6446 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6448 return interfacePrivate
->hidden
;
6453 _SCNetworkInterfaceIsModemV92(SCNetworkInterfaceRef interface
)
6455 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6457 return interfacePrivate
->modemIsV92
;
6462 _SCNetworkInterfaceIsTethered(SCNetworkInterfaceRef interface
)
6464 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6466 return (interfacePrivate
->sort_order
== kSortTethered
);
6471 _SCNetworkInterfaceIsThunderbolt(SCNetworkInterfaceRef interface
)
6473 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6474 CFStringRef interfaceType
;
6476 if (!isA_SCNetworkInterface(interface
)) {
6480 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
6481 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeBridge
)) {
6486 members
= SCBridgeInterfaceGetMemberInterfaces(interface
);
6487 n
= (members
!= NULL
) ? CFArrayGetCount(members
) : 0;
6489 // if an empty bridge
6493 for (i
= 0; i
< n
; i
++) {
6494 SCNetworkInterfaceRef member
;
6495 SCNetworkInterfacePrivateRef memberPrivate
;
6497 member
= CFArrayGetValueAtIndex(members
, i
);
6498 memberPrivate
= (SCNetworkInterfacePrivateRef
)member
;
6499 if (memberPrivate
->sort_order
!= kSortThunderbolt
) {
6504 // if Ethernet Bridge interface with only Thunderbolt [IP] members
6508 return (interfacePrivate
->sort_order
== kSortThunderbolt
);
6513 #pragma mark SCNetworkInterface [internal] SPIs
6517 SCNetworkInterfacePrivateRef
6518 __SCNetworkInterfaceCreateCopy(CFAllocatorRef allocator
,
6519 SCNetworkInterfaceRef interface
,
6520 SCPreferencesRef prefs
,
6521 CFStringRef serviceID
)
6523 SCNetworkInterfacePrivateRef oldPrivate
= (SCNetworkInterfacePrivateRef
)interface
;
6524 SCNetworkInterfacePrivateRef newPrivate
;
6526 /* initialize runtime (and kSCNetworkInterfaceIPv4) */
6527 pthread_once(&initialized
, __SCNetworkInterfaceInitialize
);
6529 if (interface
== kSCNetworkInterfaceIPv4
) {
6530 return (SCNetworkInterfacePrivateRef
)CFRetain(interface
);
6533 newPrivate
= __SCNetworkInterfaceCreatePrivate(NULL
, NULL
, prefs
, serviceID
);
6534 newPrivate
->interface_type
= oldPrivate
->interface_type
;
6535 if (oldPrivate
->interface
!= NULL
) {
6536 newPrivate
->interface
= (SCNetworkInterfaceRef
)__SCNetworkInterfaceCreateCopy(NULL
, // allocator
6537 oldPrivate
->interface
, // interface
6538 prefs
, // [new] prefs
6539 serviceID
); // [new] serviceID
6541 if (oldPrivate
->name
!= NULL
) {
6542 newPrivate
->name
= CFRetain(oldPrivate
->name
);
6544 if (oldPrivate
->localized_name
!= NULL
) {
6545 newPrivate
->localized_name
= CFRetain(oldPrivate
->localized_name
);
6547 newPrivate
->localized_key
= oldPrivate
->localized_key
;
6548 if (oldPrivate
->localized_arg1
!= NULL
) {
6549 newPrivate
->localized_arg1
= CFRetain(oldPrivate
->localized_arg1
);
6551 if (oldPrivate
->localized_arg2
!= NULL
) {
6552 newPrivate
->localized_arg2
= CFRetain(oldPrivate
->localized_arg2
);
6554 if (oldPrivate
->unsaved
!= NULL
) {
6555 newPrivate
->unsaved
= CFDictionaryCreateMutableCopy(NULL
, 0, oldPrivate
->unsaved
);
6557 if (oldPrivate
->entity_device
!= NULL
) {
6558 newPrivate
->entity_device
= CFRetain(oldPrivate
->entity_device
);
6560 if (oldPrivate
->entity_device_unique
!= NULL
) {
6561 newPrivate
->entity_device_unique
= CFRetain(oldPrivate
->entity_device_unique
);
6563 newPrivate
->entity_type
= oldPrivate
->entity_type
;
6564 newPrivate
->entity_subtype
= oldPrivate
->entity_subtype
;
6565 if (oldPrivate
->supported_interface_types
!= NULL
) {
6566 newPrivate
->supported_interface_types
= CFArrayCreateMutableCopy(NULL
, 0, oldPrivate
->supported_interface_types
);
6568 if (oldPrivate
->supported_protocol_types
!= NULL
) {
6569 newPrivate
->supported_protocol_types
= CFArrayCreateMutableCopy(NULL
, 0, oldPrivate
->supported_protocol_types
);
6571 if (oldPrivate
->address
!= NULL
) {
6572 newPrivate
->address
= CFRetain(oldPrivate
->address
);
6574 newPrivate
->builtin
= oldPrivate
->builtin
;
6575 if (oldPrivate
->configurationAction
!= NULL
) {
6576 newPrivate
->configurationAction
= CFRetain(oldPrivate
->configurationAction
);
6578 newPrivate
->hidden
= oldPrivate
->hidden
;
6579 if (oldPrivate
->location
!= NULL
) {
6580 newPrivate
->location
= CFRetain(oldPrivate
->location
);
6582 if (oldPrivate
->path
!= NULL
) {
6583 newPrivate
->path
= CFRetain(oldPrivate
->path
);
6585 newPrivate
->entryID
= oldPrivate
->entryID
;
6586 if (oldPrivate
->overrides
!= NULL
) {
6587 newPrivate
->overrides
= CFDictionaryCreateMutableCopy(NULL
, 0, oldPrivate
->overrides
);
6589 newPrivate
->modemIsV92
= oldPrivate
->modemIsV92
;
6590 if (oldPrivate
->type
!= NULL
) {
6591 newPrivate
->type
= CFRetain(oldPrivate
->type
);
6593 if (oldPrivate
->unit
!= NULL
) {
6594 newPrivate
->unit
= CFRetain(oldPrivate
->unit
);
6596 if (oldPrivate
->usb
.name
!= NULL
) {
6597 newPrivate
->usb
.name
= CFRetain(oldPrivate
->usb
.name
);
6599 if (oldPrivate
->usb
.vid
!= NULL
) {
6600 newPrivate
->usb
.vid
= CFRetain(oldPrivate
->usb
.vid
);
6602 if (oldPrivate
->usb
.pid
!= NULL
) {
6603 newPrivate
->usb
.pid
= CFRetain(oldPrivate
->usb
.pid
);
6605 newPrivate
->sort_order
= oldPrivate
->sort_order
;
6607 newPrivate
->supportsBond
= oldPrivate
->supportsBond
;
6608 if (oldPrivate
->bond
.interfaces
!= NULL
) {
6609 newPrivate
->bond
.interfaces
= CFRetain(oldPrivate
->bond
.interfaces
);
6611 if (oldPrivate
->bond
.mode
!= NULL
) {
6612 newPrivate
->bond
.mode
= CFRetain(oldPrivate
->bond
.mode
);
6614 if (oldPrivate
->bond
.options
!= NULL
) {
6615 newPrivate
->bond
.options
= CFRetain(oldPrivate
->bond
.options
);
6618 newPrivate
->supportsBridge
= oldPrivate
->supportsBridge
;
6619 if (oldPrivate
->bridge
.interfaces
!= NULL
) {
6620 newPrivate
->bridge
.interfaces
= CFRetain(oldPrivate
->bridge
.interfaces
);
6622 if (oldPrivate
->bridge
.options
!= NULL
) {
6623 newPrivate
->bridge
.options
= CFRetain(oldPrivate
->bridge
.options
);
6626 newPrivate
->supportsVLAN
= oldPrivate
->supportsVLAN
;
6627 if (oldPrivate
->vlan
.interface
!= NULL
) {
6628 newPrivate
->vlan
.interface
= CFRetain(oldPrivate
->vlan
.interface
);
6630 if (oldPrivate
->vlan
.tag
!= NULL
) {
6631 newPrivate
->vlan
.tag
= CFRetain(oldPrivate
->vlan
.tag
);
6633 if (oldPrivate
->vlan
.options
!= NULL
) {
6634 newPrivate
->vlan
.options
= CFRetain(oldPrivate
->vlan
.options
);
6643 __SCNetworkInterfaceCopyDeepConfiguration(SCNetworkSetRef set
, SCNetworkInterfaceRef interface
)
6645 CFMutableArrayRef configs
;
6647 configs
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
6649 while (interface
!= NULL
) {
6650 CFStringRef defaultType
;
6651 CFMutableDictionaryRef interfaceConfiguration
;
6653 interfaceConfiguration
= CFDictionaryCreateMutable(NULL
,
6655 &kCFTypeDictionaryKeyCallBacks
,
6656 &kCFTypeDictionaryValueCallBacks
);
6658 defaultType
= __SCNetworkInterfaceGetDefaultConfigurationType(interface
);
6659 if (defaultType
!= NULL
) {
6660 CFDictionaryRef config
;
6661 CFArrayRef extendedTypes
;
6664 config
= __SCNetworkInterfaceGetConfiguration(interface
, defaultType
);
6666 config
= __SCNetworkInterfaceGetDefaultConfiguration(set
, interface
);
6668 if (config
== NULL
) {
6669 config
= (CFDictionaryRef
)kCFNull
;
6671 CFDictionarySetValue(interfaceConfiguration
, defaultType
, config
);
6673 extendedTypes
= extendedConfigurationTypes(interface
);
6674 if (extendedTypes
!= NULL
) {
6678 n
= CFArrayGetCount(extendedTypes
);
6679 for (i
= 0; i
< n
; i
++) {
6680 CFStringRef extendedType
;
6682 extendedType
= CFArrayGetValueAtIndex(extendedTypes
, i
);
6683 config
= __SCNetworkInterfaceGetConfiguration(interface
, extendedType
);
6684 if (config
== NULL
) {
6685 config
= (CFDictionaryRef
)kCFNull
;
6687 CFDictionarySetValue(interfaceConfiguration
, extendedType
, config
);
6690 CFRelease(extendedTypes
);
6694 CFArrayAppendValue(configs
, interfaceConfiguration
);
6695 CFRelease(interfaceConfiguration
);
6697 interface
= SCNetworkInterfaceGetInterface(interface
);
6704 __private_extern__ Boolean
6705 __SCNetworkInterfaceIsMember(SCPreferencesRef prefs
, SCNetworkInterfaceRef interface
)
6707 CFArrayRef interfaces
;
6708 Boolean match
= FALSE
;
6709 CFMutableSetRef members
;
6711 members
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
6713 #if !TARGET_OS_IPHONE
6714 // add Bond [member] interfaces
6715 interfaces
= SCBondInterfaceCopyAll(prefs
);
6716 if (interfaces
!= NULL
) {
6717 __SCBondInterfaceListCollectMembers(interfaces
, members
);
6718 CFRelease(interfaces
);
6720 #endif // !TARGET_OS_IPHONE
6722 // add Bridge [member] interfaces
6723 interfaces
= SCBridgeInterfaceCopyAll(prefs
);
6724 if (interfaces
!= NULL
) {
6725 __SCBridgeInterfaceListCollectMembers(interfaces
, members
);
6726 CFRelease(interfaces
);
6729 if (CFSetGetCount(members
) == 0) {
6733 while (interface
!= NULL
) {
6734 match
= CFSetContainsValue(members
, interface
);
6736 // if the interface is a member of an
6737 // Ethernet Bond or Bridge
6741 interface
= SCNetworkInterfaceGetInterface(interface
);
6753 __SCNetworkInterfaceSetDeepConfiguration(SCNetworkSetRef set
, SCNetworkInterfaceRef interface
, CFArrayRef configs
)
6757 for (i
= 0; interface
!= NULL
; i
++) {
6758 CFStringRef defaultType
;
6759 CFDictionaryRef interfaceConfiguration
;
6761 interfaceConfiguration
= (configs
!= NULL
) ? CFArrayGetValueAtIndex(configs
, i
) : NULL
;
6763 defaultType
= __SCNetworkInterfaceGetDefaultConfigurationType(interface
);
6764 if (defaultType
!= NULL
) {
6765 CFDictionaryRef config
;
6766 CFArrayRef extendedTypes
;
6768 config
= (interfaceConfiguration
!= NULL
) ? CFDictionaryGetValue(interfaceConfiguration
, defaultType
)
6770 if (config
== (CFDictionaryRef
)kCFNull
) {
6774 // if service is not associated with the set
6775 if (!__SCNetworkInterfaceSetConfiguration(interface
, defaultType
, config
, TRUE
)) {
6776 SCLog(TRUE
, LOG_DEBUG
,
6777 CFSTR("__SCNetworkInterfaceSetDeepConfiguration __SCNetworkInterfaceSetConfiguration() failed, interface=%@, type=%@"),
6782 // apply default configuration to this set
6783 if (!__SCNetworkInterfaceSetDefaultConfiguration(set
, interface
, defaultType
, config
, TRUE
)) {
6784 SCLog(TRUE
, LOG_DEBUG
,
6785 CFSTR("__SCNetworkInterfaceSetDeepConfiguration __SCNetworkInterfaceSetDefaultConfiguration() failed, interface=%@, type=%@"),
6791 extendedTypes
= extendedConfigurationTypes(interface
);
6792 if (extendedTypes
!= NULL
) {
6796 n
= CFArrayGetCount(extendedTypes
);
6797 for (j
= 0; j
< n
; j
++) {
6798 CFStringRef extendedType
;
6800 extendedType
= CFArrayGetValueAtIndex(extendedTypes
, j
);
6801 config
= (interfaceConfiguration
!= NULL
) ? CFDictionaryGetValue(interfaceConfiguration
, extendedType
)
6803 if (config
== (CFDictionaryRef
)kCFNull
) {
6806 if (!__SCNetworkInterfaceSetConfiguration(interface
, extendedType
, config
, TRUE
)) {
6807 SCLog(TRUE
, LOG_DEBUG
,
6808 CFSTR("__SCNetworkInterfaceSetDeepConfiguration __SCNetworkInterfaceSetConfiguration() failed, interface=%@, type=%@"),
6814 CFRelease(extendedTypes
);
6818 interface
= SCNetworkInterfaceGetInterface(interface
);
6825 SCNetworkInterfaceRef
6826 _SCNetworkInterfaceCopyActive(SCDynamicStoreRef store
, CFStringRef bsdName
)
6828 SCNetworkInterfaceRef interface
;
6830 interface
= _SCNetworkInterfaceCreateWithBSDName(NULL
, bsdName
, kIncludeAllVirtualInterfaces
);
6831 if (interface
== NULL
) {
6835 if (store
!= NULL
) {
6836 SCNetworkInterfacePrivateRef interfacePrivate
=
6837 (SCNetworkInterfacePrivateRef
)interface
;
6840 interfacePrivate
->store
= store
;
6847 SCNetworkServicePrimaryRank
6848 SCNetworkInterfaceGetPrimaryRank(SCNetworkInterfaceRef interface
)
6850 CFDictionaryRef entity
;
6851 SCNetworkInterfacePrivateRef interfacePrivate
=
6852 (SCNetworkInterfacePrivateRef
)interface
;
6856 SCNetworkServicePrimaryRank rank
= kSCNetworkServicePrimaryRankDefault
;
6857 SCDynamicStoreRef session
;
6859 ifName
= SCNetworkInterfaceGetBSDName(interface
);
6860 if ((ifName
== NULL
) || (interfacePrivate
->store
== NULL
)) {
6861 _SCErrorSet(kSCStatusInvalidArgument
);
6865 session
= interfacePrivate
->store
;
6867 path
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
,
6868 kSCDynamicStoreDomainState
,
6871 entity
= SCDynamicStoreCopyValue(session
, path
);
6874 if (entity
!= NULL
) {
6875 if (isA_CFDictionary(entity
)) {
6876 CFStringRef rankStr
=
6877 CFDictionaryGetValue(entity
, kSCPropNetServicePrimaryRank
);
6878 ok
= __str_to_rank(rankStr
, &rank
);
6884 rank
= kSCNetworkServicePrimaryRankDefault
;
6885 _SCErrorSet(kSCStatusInvalidArgument
);
6886 } else if (rank
== kSCNetworkServicePrimaryRankDefault
) {
6887 _SCErrorSet(kSCStatusOK
);
6894 SCNetworkInterfaceSetPrimaryRank(SCNetworkInterfaceRef interface
,
6895 SCNetworkServicePrimaryRank newRank
)
6897 CFDictionaryRef entity
;
6898 SCNetworkInterfacePrivateRef interfacePrivate
=
6899 (SCNetworkInterfacePrivateRef
)interface
;
6901 CFMutableDictionaryRef newEntity
;
6903 CFStringRef path
= NULL
;
6904 CFStringRef rankStr
;
6905 SCDynamicStoreRef session
;
6907 ifName
= SCNetworkInterfaceGetBSDName(interface
);
6908 if ((ifName
== NULL
) || (interfacePrivate
->store
== NULL
)) {
6909 _SCErrorSet(kSCStatusInvalidArgument
);
6913 session
= interfacePrivate
->store
;
6915 ok
= __rank_to_str(newRank
, &rankStr
);
6917 _SCErrorSet(kSCStatusInvalidArgument
);
6921 path
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
,
6922 kSCDynamicStoreDomainState
,
6926 entity
= SCDynamicStoreCopyValue(session
, path
);
6927 if (entity
!= NULL
) {
6928 if (!isA_CFDictionary(entity
)) {
6930 _SCErrorSet(kSCStatusFailed
);
6933 newEntity
= CFDictionaryCreateMutableCopy(NULL
, 0, entity
);
6936 newEntity
= CFDictionaryCreateMutable(NULL
,
6938 &kCFTypeDictionaryKeyCallBacks
,
6939 &kCFTypeDictionaryValueCallBacks
);
6942 if (rankStr
!= NULL
) {
6943 CFDictionarySetValue(newEntity
, kSCPropNetServicePrimaryRank
, rankStr
);
6945 CFDictionaryRemoveValue(newEntity
, kSCPropNetServicePrimaryRank
);
6948 if (CFDictionaryGetCount(newEntity
) > 0) {
6949 ok
= SCDynamicStoreSetValue(session
, path
, newEntity
);
6951 ok
= SCDynamicStoreRemoveValue(session
, path
);
6954 CFRelease(newEntity
);
6958 if (path
!= NULL
) CFRelease(path
);