2 * Copyright (c) 2001-2011 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 20, 2006 Joe Liu <joe.liu@apple.com>
28 * Allan Nathanson <ajn@apple.com>
29 * - register interface by entryID (and not path)
31 * November 6, 2006 Allan Nathanson <ajn@apple.com>
32 * Dan Markarian <markarian@apple.com>
33 * Dieter Siegmund <dieter@apple.com>
34 * - updated code to name interfaces quicker (without need for
35 * calling IOKitWaitQuiet).
37 * October 3, 2003 Allan Nathanson <ajn@apple.com>
38 * - sort new interfaces by IOKit path (rather than MAC address) to
39 * help facilitate a more predictable interface-->name mapping for
40 * like hardware configurations.
42 * June 23, 2001 Allan Nathanson <ajn@apple.com>
43 * - update to public SystemConfiguration.framework APIs
45 * January 23, 2001 Dieter Siegmund <dieter@apple.com>
51 * - module that receives IOKit Network Interface messages
52 * and names any interface that currently does not have a name
53 * - uses Interface Type and MACAddress as the unique identifying
54 * keys; any interface that doesn't contain both of these properties
55 * is ignored and not processed
56 * - stores the Interface Type, MACAddress, and Unit in permanent storage
57 * to give persistent interface names
65 #include <sys/ioctl.h>
66 #include <sys/socket.h>
67 #include <sys/sockio.h>
69 #include <sys/sysctl.h>
70 #include <sys/param.h>
71 #include <mach/mach.h>
72 #include <net/ethernet.h>
74 #include <net/if_types.h>
76 #include <CoreFoundation/CoreFoundation.h>
78 #include <SystemConfiguration/SystemConfiguration.h>
79 #include <SystemConfiguration/SCDPlugin.h>
80 #include <SystemConfiguration/SCPrivate.h> // for SCLog(), SCPrint()
81 #include <SystemConfiguration/SCValidation.h>
83 #include <IOKit/IOKitLib.h>
84 #include <IOKit/IOKitLibPrivate.h>
85 #include <IOKit/IOBSD.h>
86 #include <IOKit/IOMessage.h>
87 #include <IOKit/network/IONetworkController.h>
88 #include <IOKit/network/IONetworkInterface.h>
89 #include <IOKit/network/IONetworkStack.h>
90 #include <IOKit/usb/USB.h>
92 #ifdef kIONetworkStackUserCommandKey
93 #define USE_REGISTRY_ENTRY_ID
96 #ifndef USE_REGISTRY_ENTRY_ID
97 // from <IOKit/network/IONetworkStack.h>
98 #define kIONetworkStackUserCommandKey "IONetworkStackUserCommand"
100 kRegisterInterfaceWithFixedUnit
= 0,
102 kRegisterAllInterfaces
104 #endif // !USE_REGISTRY_ENTRY_ID
106 #define kSCNetworkInterfaceInfo "SCNetworkInterfaceInfo"
107 #define kSCNetworkInterfaceType "SCNetworkInterfaceType"
108 #define kSCNetworkInterfaceActive "Active"
110 #define MY_PLUGIN_NAME "InterfaceNamer"
111 #define MY_PLUGIN_ID CFSTR("com.apple.SystemConfiguration." MY_PLUGIN_NAME)
113 #define WAIT_STACK_TIMEOUT_KEY "WaitStackTimeout"
114 #define WAIT_STACK_TIMEOUT_DEFAULT 300.0
116 #define WAIT_QUIET_TIMEOUT_KEY "WaitQuietTimeout"
117 #define WAIT_QUIET_TIMEOUT_DEFAULT 60.0
121 * "IONetworkStack" connect object used to "name" an interface.
123 static io_connect_t S_connect
= MACH_PORT_NULL
;
127 * An array of CFDictionary's representing the interfaces
128 * that have been identified and [need to be] named.
130 static CFMutableArrayRef S_dblist
= NULL
;
134 * A boolean that enables additional logging.
136 static boolean_t S_debug
= FALSE
;
140 * An array of SCNetworkInterface's representing the
141 * interfaces that have been identified.
143 static CFMutableArrayRef S_iflist
= NULL
;
147 * IOServiceAddMatchingNotification object used to watch for
148 * new network interfaces.
150 static io_iterator_t S_iter
= MACH_PORT_NULL
;
154 * Hardware model for this network configuration.
156 static CFStringRef S_model
= NULL
;
160 * notification object for receiving IOKit notifications of
161 * new devices or state changes.
163 static IONotificationPortRef S_notify
= NULL
;
165 /* S_prev_active_list
166 * An array of CFDictionary's representing the previously
169 static CFMutableArrayRef S_prev_active_list
= NULL
;
173 * IOServiceAddInterestNotification object used to watch for
174 * IOKit matching to quiesce.
176 static io_object_t S_quiet
= MACH_PORT_NULL
;
180 * IOServiceAddMatchingNotification object used to watch for
181 * the availability of the "IONetworkStack" object.
183 static io_iterator_t S_stack
= MACH_PORT_NULL
;
187 * A dictionary containing Information about each network
188 * interface. For now, the key is the BSD name and the
189 * value is a CFNumber noting how long (in milliseconds)
190 * it took for the interface to be recognized/named.
192 static CFMutableDictionaryRef S_state
= NULL
;
196 * CFRunLoopTimer tracking how long we are willing to wait
197 * for IOKit matching to quiesce (IOKitWaitQuiet).
200 * time to wait for the IONetworkStack object to appear before timeout
203 * time to wait for the IOKit to quiesce (after the IONetworkStack is
206 static CFRunLoopTimerRef S_timer
= NULL
;
207 static double S_stack_timeout
= WAIT_STACK_TIMEOUT_DEFAULT
;
208 static double S_quiet_timeout
= WAIT_QUIET_TIMEOUT_DEFAULT
;
212 * Virtual network interface configuration
213 * S_prefs : SCPreferences to configuration
214 * S_bonds : most recently actived Bond configuration
215 * S_bridges : most recently actived Bridge configuration
216 * S_vlans : most recently actived VLAN configuration
218 static SCPreferencesRef S_prefs
= NULL
;
219 static CFArrayRef S_bonds
= NULL
;
220 static CFArrayRef S_bridges
= NULL
;
221 static CFArrayRef S_vlans
= NULL
;
224 addTimestamp(CFMutableDictionaryRef dict
, CFStringRef key
)
229 now
= CFAbsoluteTimeGetCurrent();
230 val
= CFNumberCreate(NULL
, kCFNumberDoubleType
, &now
);
231 CFDictionaryAddValue(dict
, key
, val
);
236 #define INTERFACES CFSTR("Interfaces")
237 #define MODEL CFSTR("Model")
238 #define NETWORK_INTERFACES_PREFS CFSTR("NetworkInterfaces.plist")
243 if (S_model
== NULL
) {
245 int mib
[] = { CTL_HW
, HW_MODEL
};
246 size_t n
= sizeof(hwModel
);
250 bzero(&hwModel
, sizeof(hwModel
));
251 ret
= sysctl(mib
, sizeof(mib
) / sizeof(mib
[0]), &hwModel
, &n
, NULL
, 0);
253 SCLog(TRUE
, LOG_ERR
, CFSTR("sysctl() CTL_HW/HW_MODEL failed: %s"), strerror(errno
));
256 hwModel
[sizeof(hwModel
) - 1] = '\0';
258 S_model
= CFStringCreateWithCString(NULL
, hwModel
, kCFStringEncodingASCII
);
265 static CFComparisonResult
266 if_unit_compare(const void *val1
, const void *val2
, void *context
)
268 CFComparisonResult res
;
274 type1
= CFDictionaryGetValue((CFDictionaryRef
)val1
,
275 CFSTR(kIOInterfaceType
));
276 type2
= CFDictionaryGetValue((CFDictionaryRef
)val2
,
277 CFSTR(kIOInterfaceType
));
278 res
= CFNumberCompare(type1
, type2
, NULL
);
279 if (res
!= kCFCompareEqualTo
) {
282 unit1
= CFDictionaryGetValue((CFDictionaryRef
)val1
,
283 CFSTR(kIOInterfaceUnit
));
284 unit2
= CFDictionaryGetValue((CFDictionaryRef
)val2
,
285 CFSTR(kIOInterfaceUnit
));
286 return (CFNumberCompare(unit1
, unit2
, NULL
));
290 reportIssue(const char *signature
, CFStringRef issue
)
294 m
= asl_new(ASL_TYPE_MSG
);
295 asl_set(m
, "com.apple.message.domain", "com.apple.SystemConfiguration." MY_PLUGIN_NAME
);
296 asl_set(m
, "com.apple.message.signature", signature
);
297 asl_set(m
, "com.apple.message.result", "failure");
298 SCLOG(NULL
, m
, ~ASL_LEVEL_ERR
, CFSTR("%s\n%@"), signature
, issue
);
305 writeInterfaceList(CFArrayRef if_list
)
308 CFStringRef new_model
;
309 CFStringRef old_model
;
310 SCPreferencesRef prefs
;
312 if (isA_CFArray(if_list
) == NULL
) {
316 prefs
= SCPreferencesCreate(NULL
, MY_PLUGIN_ID
, NETWORK_INTERFACES_PREFS
);
319 CFSTR(MY_PLUGIN_NAME
": SCPreferencesCreate failed, %s"),
320 SCErrorString(SCError()));
324 cur_list
= SCPreferencesGetValue(prefs
, INTERFACES
);
325 if (_SC_CFEqual(cur_list
, if_list
)) {
329 old_model
= SCPreferencesGetValue(prefs
, MODEL
);
330 new_model
= hw_model();
331 if ((new_model
!= NULL
) && !_SC_CFEqual(old_model
, new_model
)) {
333 if ((old_model
!= NULL
) && (cur_list
!= NULL
)) {
337 // if interface list was created on other hardware
338 history
= CFStringCreateWithFormat(NULL
, NULL
,
342 SCPreferencesSetValue(prefs
, history
, cur_list
);
346 CFSTR(MY_PLUGIN_NAME
": Hardware model changed\n"
347 MY_PLUGIN_NAME
": created on \"%@\"\n"
348 MY_PLUGIN_NAME
": now on \"%@\""),
352 issue
= CFStringCreateWithFormat(NULL
, NULL
,
356 reportIssue("Hardware model changed", issue
);
360 if (!SCPreferencesSetValue(prefs
, MODEL
, new_model
)) {
362 CFSTR(MY_PLUGIN_NAME
": SCPreferencesSetValue failed, %s"),
363 SCErrorString(SCError()));
368 if (!SCPreferencesSetValue(prefs
, INTERFACES
, if_list
)) {
370 CFSTR(MY_PLUGIN_NAME
": SCPreferencesSetValue failed, %s"),
371 SCErrorString(SCError()));
375 if (!SCPreferencesCommitChanges(prefs
)) {
376 SCLog((SCError() != EROFS
), LOG_ERR
,
377 CFSTR(MY_PLUGIN_NAME
": SCPreferencesCommitChanges failed, %s"),
378 SCErrorString(SCError()));
388 static CFMutableArrayRef
392 CFStringRef old_model
;
393 CFMutableArrayRef plist
= NULL
;
394 SCPreferencesRef prefs
= NULL
;
396 prefs
= SCPreferencesCreate(NULL
, MY_PLUGIN_ID
, NETWORK_INTERFACES_PREFS
);
399 CFSTR(MY_PLUGIN_NAME
": SCPreferencesCreate failed, %s"),
400 SCErrorString(SCError()));
404 if_list
= SCPreferencesGetValue(prefs
, INTERFACES
);
405 if_list
= isA_CFArray(if_list
);
407 old_model
= SCPreferencesGetValue(prefs
, MODEL
);
408 if (old_model
!= NULL
) {
409 CFStringRef new_model
;
411 new_model
= hw_model();
412 if (!_SC_CFEqual(old_model
, new_model
)) {
413 // if interface list was created on other hardware
418 if (if_list
!= NULL
) {
420 CFIndex n
= CFArrayGetCount(if_list
);
422 plist
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
423 for (i
= 0; i
< n
; i
++) {
424 CFDictionaryRef dict
;
426 dict
= CFArrayGetValueAtIndex(if_list
, i
);
427 if (isA_CFDictionary(dict
) &&
428 CFDictionaryContainsKey(dict
, CFSTR(kIOInterfaceType
)) &&
429 CFDictionaryContainsKey(dict
, CFSTR(kIOInterfaceUnit
)) &&
430 CFDictionaryContainsKey(dict
, CFSTR(kIOMACAddress
))) {
431 CFArrayAppendValue(plist
, dict
);
442 static CFMutableArrayRef
443 previouslyActiveInterfaces()
445 CFMutableArrayRef active
;
449 if (S_dblist
== NULL
) {
453 active
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
455 n
= CFArrayGetCount(S_dblist
);
456 for (i
= 0; i
< n
; i
++) {
457 CFDictionaryRef if_dict
;
459 if_dict
= CFArrayGetValueAtIndex(S_dblist
, i
);
460 if (CFDictionaryContainsKey(if_dict
, CFSTR(kSCNetworkInterfaceActive
))) {
461 CFMutableDictionaryRef new_dict
;
463 new_dict
= CFDictionaryCreateMutableCopy(NULL
, 0, if_dict
);
464 CFDictionaryRemoveValue(new_dict
, CFSTR(kSCNetworkInterfaceActive
));
465 CFArraySetValueAtIndex(S_dblist
, i
, new_dict
);
466 CFArrayAppendValue(active
, new_dict
);
478 SCDynamicStoreRef store
;
480 store
= SCDynamicStoreCreate(NULL
, CFSTR(MY_PLUGIN_NAME
), NULL
, NULL
);
485 key
= SCDynamicStoreKeyCreate(NULL
, CFSTR("%@" MY_PLUGIN_NAME
),
486 kSCDynamicStoreDomainPlugin
);
487 (void)SCDynamicStoreSetValue(store
, key
, S_state
);
495 updateBondInterfaceConfiguration(SCPreferencesRef prefs
)
497 CFArrayRef interfaces
;
499 interfaces
= SCBondInterfaceCopyAll(prefs
);
500 if ((interfaces
!= NULL
) && (CFArrayGetCount(interfaces
) == 0)) {
501 CFRelease(interfaces
);
505 if (_SC_CFEqual(S_bonds
, interfaces
)) {
507 if (interfaces
!= NULL
) CFRelease(interfaces
);
511 if (S_bonds
!= NULL
) CFRelease(S_bonds
);
512 S_bonds
= interfaces
;
514 if (!_SCBondInterfaceUpdateConfiguration(prefs
)) {
516 CFSTR(MY_PLUGIN_NAME
": _SCBondInterfaceUpdateConfiguration failed, %s"),
517 SCErrorString(SCError()));
524 updateBridgeInterfaceConfiguration(SCPreferencesRef prefs
)
526 CFArrayRef interfaces
;
528 interfaces
= SCBridgeInterfaceCopyAll(prefs
);
529 if ((interfaces
!= NULL
) && (CFArrayGetCount(interfaces
) == 0)) {
530 CFRelease(interfaces
);
534 if (_SC_CFEqual(S_bridges
, interfaces
)) {
536 if (interfaces
!= NULL
) CFRelease(interfaces
);
540 if (S_bridges
!= NULL
) CFRelease(S_bridges
);
541 S_bridges
= interfaces
;
543 if (!_SCBridgeInterfaceUpdateConfiguration(prefs
)) {
545 CFSTR(MY_PLUGIN_NAME
": _SCBridgeInterfaceUpdateConfiguration failed, %s"),
546 SCErrorString(SCError()));
553 updateVLANInterfaceConfiguration(SCPreferencesRef prefs
)
555 CFArrayRef interfaces
;
557 interfaces
= SCVLANInterfaceCopyAll(prefs
);
558 if ((interfaces
!= NULL
) && (CFArrayGetCount(interfaces
) == 0)) {
559 CFRelease(interfaces
);
563 if (_SC_CFEqual(S_vlans
, interfaces
)) {
565 if (interfaces
!= NULL
) CFRelease(interfaces
);
569 if (S_vlans
!= NULL
) CFRelease(S_vlans
);
570 S_vlans
= interfaces
;
572 if (!_SCVLANInterfaceUpdateConfiguration(prefs
)) {
574 CFSTR(MY_PLUGIN_NAME
": _SCVLANInterfaceUpdateConfiguration failed, %s"),
575 SCErrorString(SCError()));
582 updateVirtualNetworkInterfaceConfiguration(SCPreferencesRef prefs
,
583 SCPreferencesNotification notificationType
,
586 if ((notificationType
& kSCPreferencesNotificationApply
) != kSCPreferencesNotificationApply
) {
591 // if a new interface has been "named"
593 if (S_bonds
!= NULL
) {
597 if (S_bridges
!= NULL
) {
598 CFRelease(S_bridges
);
601 if (S_vlans
!= NULL
) {
607 updateBondInterfaceConfiguration (prefs
);
608 updateBridgeInterfaceConfiguration(prefs
);
609 updateVLANInterfaceConfiguration (prefs
);
611 // we are finished with current prefs, wait for changes
612 SCPreferencesSynchronize(prefs
);
616 static CFDictionaryRef
617 createInterfaceDict(SCNetworkInterfaceRef interface
)
619 CFMutableDictionaryRef new_if
;
622 new_if
= CFDictionaryCreateMutable(NULL
,
624 &kCFTypeDictionaryKeyCallBacks
,
625 &kCFTypeDictionaryValueCallBacks
);
627 val
= _SCNetworkInterfaceCopyInterfaceInfo(interface
);
629 CFDictionarySetValue(new_if
, CFSTR(kSCNetworkInterfaceInfo
), val
);
633 val
= _SCNetworkInterfaceGetIOPath(interface
);
635 CFDictionarySetValue(new_if
, CFSTR(kIOPathMatchKey
), val
);
638 val
= _SCNetworkInterfaceGetIOInterfaceType(interface
);
640 CFDictionarySetValue(new_if
, CFSTR(kIOInterfaceType
), val
);
643 val
= _SCNetworkInterfaceGetIOInterfaceUnit(interface
);
645 CFDictionarySetValue(new_if
, CFSTR(kIOInterfaceUnit
), val
);
648 val
= _SCNetworkInterfaceGetHardwareAddress(interface
);
650 CFDictionarySetValue(new_if
, CFSTR(kIOMACAddress
), val
);
653 val
= SCNetworkInterfaceGetBSDName(interface
);
655 CFDictionarySetValue(new_if
, CFSTR(kIOBSDNameKey
), val
);
658 val
= SCNetworkInterfaceGetInterfaceType(interface
);
660 CFDictionarySetValue(new_if
, CFSTR(kSCNetworkInterfaceType
), val
);
663 CFDictionarySetValue(new_if
,
665 _SCNetworkInterfaceIsBuiltin(interface
) ? kCFBooleanTrue
: kCFBooleanFalse
);
667 CFDictionarySetValue(new_if
, CFSTR(kSCNetworkInterfaceActive
), kCFBooleanTrue
);
672 static CFDictionaryRef
673 lookupInterfaceByAddress(CFArrayRef db_list
, SCNetworkInterfaceRef interface
, CFIndex
* where
)
680 if (db_list
== NULL
) {
683 type
= _SCNetworkInterfaceGetIOInterfaceType(interface
);
684 addr
= _SCNetworkInterfaceGetHardwareAddress(interface
);
685 if (type
== NULL
|| addr
== NULL
) {
689 n
= CFArrayGetCount(db_list
);
690 for (i
= 0; i
< n
; i
++) {
692 CFDictionaryRef dict
= CFArrayGetValueAtIndex(db_list
, i
);
695 t
= CFDictionaryGetValue(dict
, CFSTR(kIOInterfaceType
));
696 a
= CFDictionaryGetValue(dict
, CFSTR(kIOMACAddress
));
697 if (t
== NULL
|| a
== NULL
)
700 if (CFEqual(type
, t
) && CFEqual(addr
, a
)) {
710 static CFDictionaryRef
711 lookupInterfaceByUnit(CFArrayRef db_list
, SCNetworkInterfaceRef interface
, CFIndex
* where
)
718 if (db_list
== NULL
) {
721 type
= _SCNetworkInterfaceGetIOInterfaceType(interface
);
722 unit
= _SCNetworkInterfaceGetIOInterfaceUnit(interface
);
723 if (type
== NULL
|| unit
== NULL
) {
727 n
= CFArrayGetCount(db_list
);
728 for (i
= 0; i
< n
; i
++) {
729 CFDictionaryRef dict
= CFArrayGetValueAtIndex(db_list
, i
);
733 t
= CFDictionaryGetValue(dict
, CFSTR(kIOInterfaceType
));
734 u
= CFDictionaryGetValue(dict
, CFSTR(kIOInterfaceUnit
));
735 if (t
== NULL
|| u
== NULL
) {
739 if (CFEqual(type
, t
) && CFEqual(unit
, u
)) {
749 CFDictionaryRef match_info
;
750 CFStringRef match_type
;
751 CFBooleanRef match_builtin
;
752 CFMutableArrayRef matches
;
753 } matchContext
, *matchContextRef
;
755 static CFDictionaryRef
756 thinInterfaceInfo(CFDictionaryRef info
)
761 if (CFDictionaryGetValueIfPresent(info
, CFSTR(kUSBVendorID
), (const void **)&num
)
763 && CFNumberGetValue(num
, kCFNumberIntType
, &vid
)
764 && (vid
== kIOUSBVendorIDAppleComputer
)) {
765 CFMutableDictionaryRef thin
;
767 // if this is an Apple USB device than we trust that
768 // the non-localized name will be correct.
769 thin
= CFDictionaryCreateMutableCopy(NULL
, 0, info
);
770 CFDictionaryRemoveValue(thin
, CFSTR(kUSBProductString
));
771 CFDictionaryRemoveValue(thin
, CFSTR(kUSBVendorID
));
772 CFDictionaryRemoveValue(thin
, CFSTR(kUSBProductID
));
776 return CFRetain(info
);
780 matchInterfaceInfo(CFDictionaryRef known_info
, CFDictionaryRef match_info
)
784 match
= _SC_CFEqual(known_info
, match_info
);
786 isA_CFDictionary(known_info
) &&
787 isA_CFDictionary(match_info
)) {
789 // if not an exact match, try thinning
790 known_info
= thinInterfaceInfo(known_info
);
791 match_info
= thinInterfaceInfo(match_info
);
792 match
= _SC_CFEqual(known_info
, match_info
);
793 CFRelease(known_info
);
794 CFRelease(match_info
);
801 matchKnown(const void *value
, void *context
)
803 CFDictionaryRef known_dict
= (CFDictionaryRef
)value
;
804 matchContextRef match_context
= (matchContextRef
)context
;
806 // match interface type
808 CFStringRef known_type
;
810 known_type
= CFDictionaryGetValue(known_dict
, CFSTR(kSCNetworkInterfaceType
));
811 if (!_SC_CFEqual(known_type
, match_context
->match_type
)) {
816 // match SCNetworkInterfaceInfo
818 CFDictionaryRef known_info
;
820 known_info
= CFDictionaryGetValue(known_dict
, CFSTR(kSCNetworkInterfaceInfo
));
821 if (!matchInterfaceInfo(known_info
, match_context
->match_info
)) {
826 // if requested, match [non-]builtin
827 if (match_context
->match_builtin
!= NULL
) {
828 CFBooleanRef known_builtin
;
830 known_builtin
= CFDictionaryGetValue(known_dict
, CFSTR(kIOBuiltin
));
831 if (!isA_CFBoolean(known_builtin
)) {
832 known_builtin
= kCFBooleanFalse
;
834 if (!_SC_CFEqual(known_builtin
, match_context
->match_builtin
)) {
839 // if we have a match
840 if (match_context
->matches
== NULL
) {
841 match_context
->matches
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
843 CFArrayAppendValue(match_context
->matches
, known_dict
);
849 matchUnnamed(const void *value
, void *context
)
851 SCNetworkInterfaceRef known_if
= (SCNetworkInterfaceRef
)value
;
852 matchContextRef match_context
= (matchContextRef
)context
;
854 if (match_context
->matches
== NULL
) {
858 // match interface type
860 CFStringRef known_type
;
862 known_type
= SCNetworkInterfaceGetInterfaceType(known_if
);
863 if (!_SC_CFEqual(known_type
, match_context
->match_type
)) {
868 // match SCNetworkInterfaceInfo
870 CFDictionaryRef known_info
;
873 known_info
= _SCNetworkInterfaceCopyInterfaceInfo(known_if
);
874 match
= matchInterfaceInfo(known_info
, match_context
->match_info
);
875 if (known_info
!= NULL
) CFRelease(known_info
);
881 // if requested, match [non-]builtin
882 if (match_context
->match_builtin
!= NULL
) {
883 CFBooleanRef known_builtin
;
885 known_builtin
= _SCNetworkInterfaceIsBuiltin(known_if
) ? kCFBooleanTrue
887 if (!_SC_CFEqual(known_builtin
, match_context
->match_builtin
)) {
892 // if we have a match
893 CFRelease(match_context
->matches
);
894 match_context
->matches
= NULL
;
900 * lookupMatchingInterface
902 * Looks at the interfaces that have already been [or need to be] named with
903 * the goal of allowing a system using a single network interface/adaptor of
904 * a given type (vendor, model, ...) to not care about the specific adaptor
905 * that is used (i.e. swapping dongle's is OK). Once a system has had more
906 * than one interface/adaptor connected at the same time than we assume that
907 * the network configuration is being setup for multi-homing that should be
910 * If no matches are found or if more than one match is found, return NULL.
911 * If a single match is found, return the match.
913 static CFDictionaryRef
914 lookupMatchingInterface(SCNetworkInterfaceRef interface
,
915 CFArrayRef db_list
, // already named
916 CFArrayRef if_list
, // to be named
917 CFIndex if_list_index
,
918 CFBooleanRef builtin
)
921 CFDictionaryRef match
= NULL
;
922 matchContext match_context
;
924 if_type
= SCNetworkInterfaceGetInterfaceType(interface
);
925 if (if_type
== NULL
) {
929 match_context
.match_type
= if_type
;
930 match_context
.match_info
= _SCNetworkInterfaceCopyInterfaceInfo(interface
);
931 match_context
.match_builtin
= builtin
;
932 match_context
.matches
= NULL
;
934 // check for matches to already named interfaces
935 // ... and appends each match that we find to match_context.matches
936 if (db_list
!= NULL
) {
937 CFArrayApplyFunction(db_list
,
938 CFRangeMake(0, CFArrayGetCount(db_list
)),
943 // check for matches to to be named interfaces
944 // ... and CFReleases match_context.matches if we find another network
945 // interface of the same type that also needs to be named
946 if (if_list
!= NULL
) {
947 CFIndex if_list_count
;
949 if_list_count
= CFArrayGetCount(if_list
);
950 if (if_list_index
< if_list_count
) {
951 CFArrayApplyFunction(if_list
,
952 CFRangeMake(if_list_index
, if_list_count
- if_list_index
),
958 // check if we have a single match
959 if (match_context
.matches
!= NULL
) {
960 if (CFArrayGetCount(match_context
.matches
) == 1) {
961 match
= CFArrayGetValueAtIndex(match_context
.matches
, 0);
963 CFRelease(match_context
.matches
);
967 Boolean active
= TRUE
;
970 name
= CFDictionaryGetValue(match
, CFSTR(kIOBSDNameKey
));
971 if (isA_CFString(name
)) {
974 sock
= socket(AF_INET
, SOCK_DGRAM
, 0);
978 (void)_SC_cfstring_to_cstring(name
, ifr
.ifr_name
, sizeof(ifr
.ifr_name
), kCFStringEncodingASCII
);
979 if (ioctl(sock
, SIOCGIFFLAGS
, &ifr
) == -1) {
980 // if interface name not currently in-use
992 if (match_context
.match_info
!= NULL
) CFRelease(match_context
.match_info
);
997 insertInterface(CFMutableArrayRef db_list
, SCNetworkInterfaceRef interface
)
1000 CFDictionaryRef if_dict
;
1001 CFStringRef if_name
;
1002 CFNumberRef if_type
;
1003 CFNumberRef if_unit
;
1004 CFIndex n
= CFArrayGetCount(db_list
);
1005 CFComparisonResult res
;
1007 if_name
= SCNetworkInterfaceGetBSDName(interface
);
1008 if (if_name
!= NULL
) {
1009 addTimestamp(S_state
, if_name
);
1012 if_dict
= createInterfaceDict(interface
);
1013 if_type
= _SCNetworkInterfaceGetIOInterfaceType(interface
);
1014 if_unit
= _SCNetworkInterfaceGetIOInterfaceUnit(interface
);
1015 if ((if_type
== NULL
) || (if_unit
== NULL
)) {
1020 for (i
= 0; i
< n
; i
++) {
1021 CFNumberRef db_type
;
1022 CFNumberRef db_unit
;
1023 CFDictionaryRef dict
= CFArrayGetValueAtIndex(db_list
, i
);
1025 db_type
= CFDictionaryGetValue(dict
, CFSTR(kIOInterfaceType
));
1026 db_unit
= CFDictionaryGetValue(dict
, CFSTR(kIOInterfaceUnit
));
1027 res
= CFNumberCompare(if_type
, db_type
, NULL
);
1028 if (res
== kCFCompareLessThan
1029 || (res
== kCFCompareEqualTo
1030 && (CFNumberCompare(if_unit
, db_unit
, NULL
)
1031 == kCFCompareLessThan
))) {
1032 CFArrayInsertValueAtIndex(db_list
, i
, if_dict
);
1038 CFArrayAppendValue(S_dblist
, if_dict
);
1044 replaceInterface(SCNetworkInterfaceRef interface
)
1049 if (S_dblist
== NULL
) {
1050 S_dblist
= CFArrayCreateMutable(NULL
, 0,
1051 &kCFTypeArrayCallBacks
);
1053 // remove any dict that has our type/addr
1054 while (lookupInterfaceByAddress(S_dblist
, interface
, &where
) != NULL
) {
1055 CFArrayRemoveValueAtIndex(S_dblist
, where
);
1058 // remove any dict that has the same type/unit
1059 while (lookupInterfaceByUnit(S_dblist
, interface
, &where
) != NULL
) {
1060 CFArrayRemoveValueAtIndex(S_dblist
, where
);
1063 insertInterface(S_dblist
, interface
);
1068 issue
= CFStringCreateWithFormat(NULL
, NULL
,
1069 CFSTR("n = %d, %@"),
1072 reportIssue("Multiple interfaces updated", issue
);
1080 getHighestUnitForType(CFNumberRef if_type
)
1084 CFNumberRef ret_unit
= NULL
;
1086 if (S_dblist
== NULL
) {
1090 n
= CFArrayGetCount(S_dblist
);
1091 for (i
= 0; i
< n
; i
++) {
1092 CFDictionaryRef dict
= CFArrayGetValueAtIndex(S_dblist
, i
);
1095 type
= CFDictionaryGetValue(dict
, CFSTR(kIOInterfaceType
));
1096 if (CFEqual(type
, if_type
)) {
1099 unit
= CFDictionaryGetValue(dict
, CFSTR(kIOInterfaceUnit
));
1100 if (ret_unit
== NULL
1101 || (CFNumberCompare(unit
, ret_unit
, NULL
)
1102 == kCFCompareGreaterThan
)) {
1111 #ifdef USE_REGISTRY_ENTRY_ID
1112 static kern_return_t
1113 registerInterfaceWithIORegistryEntryID(io_connect_t connect
,
1119 CFMutableDictionaryRef dict
;
1123 dict
= CFDictionaryCreateMutable(NULL
, 0,
1124 &kCFTypeDictionaryKeyCallBacks
,
1125 &kCFTypeDictionaryValueCallBacks
);
1126 num
= CFNumberCreate(NULL
, kCFNumberIntType
, &command
);
1127 CFDictionarySetValue(dict
, CFSTR(kIONetworkStackUserCommandKey
), num
);
1129 data
= CFDataCreate(NULL
, (void *) &entryID
, sizeof(entryID
));
1130 CFDictionarySetValue(dict
, CFSTR(kIORegistryEntryIDKey
), data
);
1132 CFDictionarySetValue(dict
, CFSTR(kIOInterfaceUnit
), unit
);
1133 kr
= IOConnectSetCFProperties(connect
, dict
);
1138 static SCNetworkInterfaceRef
1139 lookupIORegistryEntryID(uint64_t entryID
)
1141 io_registry_entry_t entry
= MACH_PORT_NULL
;
1142 SCNetworkInterfaceRef interface
= NULL
;
1143 io_iterator_t iterator
= MACH_PORT_NULL
;
1145 mach_port_t masterPort
= MACH_PORT_NULL
;
1147 kr
= IOMasterPort(bootstrap_port
, &masterPort
);
1148 if (kr
!= KERN_SUCCESS
) {
1149 SCLog(TRUE
, LOG_ERR
,
1150 CFSTR(MY_PLUGIN_NAME
": IOMasterPort returned 0x%x"),
1155 kr
= IOServiceGetMatchingServices(masterPort
,
1156 IORegistryEntryIDMatching(entryID
),
1158 if ((kr
!= KERN_SUCCESS
) || (iterator
== MACH_PORT_NULL
)) {
1159 SCLog(TRUE
, LOG_ERR
,
1160 CFSTR(MY_PLUGIN_NAME
": IOServiceGetMatchingServices(0x%llx) returned 0x%x/%d"),
1167 entry
= IOIteratorNext(iterator
);
1168 if (entry
== MACH_PORT_NULL
) {
1169 SCLog(TRUE
, LOG_ERR
,
1170 CFSTR(MY_PLUGIN_NAME
": IORegistryEntryIDMatching(0x%llx) failed"),
1175 interface
= _SCNetworkInterfaceCreateWithIONetworkInterfaceObject(entry
);
1178 if (masterPort
!= MACH_PORT_NULL
) {
1179 mach_port_deallocate(mach_task_self(), masterPort
);
1181 if (entry
!= MACH_PORT_NULL
) {
1182 IOObjectRelease(entry
);
1184 if (iterator
!= MACH_PORT_NULL
) {
1185 IOObjectRelease(iterator
);
1190 #else // USE_REGISTRY_ENTRY_ID
1192 * Function: registerInterface
1194 * Register a single interface with the given service path to the
1195 * data link layer (BSD), using the specified unit number.
1197 static kern_return_t
1198 registerInterfaceWithIOServicePath(io_connect_t connect
,
1203 CFMutableDictionaryRef dict
;
1207 dict
= CFDictionaryCreateMutable(NULL
, 0,
1208 &kCFTypeDictionaryKeyCallBacks
,
1209 &kCFTypeDictionaryValueCallBacks
);
1210 num
= CFNumberCreate(NULL
, kCFNumberIntType
, &command
);
1211 CFDictionarySetValue(dict
, CFSTR(kIONetworkStackUserCommandKey
), num
);
1213 CFDictionarySetValue(dict
, CFSTR(kIOPathMatchKey
), path
);
1214 CFDictionarySetValue(dict
, CFSTR(kIOInterfaceUnit
), unit
);
1215 kr
= IOConnectSetCFProperties(connect
, dict
);
1220 static SCNetworkInterfaceRef
1221 lookupIOKitPath(CFStringRef if_path
)
1223 io_registry_entry_t entry
= MACH_PORT_NULL
;
1224 SCNetworkInterfaceRef interface
= NULL
;
1226 mach_port_t masterPort
= MACH_PORT_NULL
;
1229 kr
= IOMasterPort(bootstrap_port
, &masterPort
);
1230 if (kr
!= KERN_SUCCESS
) {
1231 SCLog(TRUE
, LOG_ERR
,
1232 CFSTR(MY_PLUGIN_NAME
": IOMasterPort returned 0x%x"),
1236 _SC_cfstring_to_cstring(if_path
, path
, sizeof(path
), kCFStringEncodingASCII
);
1237 entry
= IORegistryEntryFromPath(masterPort
, path
);
1238 if (entry
== MACH_PORT_NULL
) {
1239 SCLog(TRUE
, LOG_ERR
,
1240 CFSTR(MY_PLUGIN_NAME
": IORegistryEntryFromPath(%@) failed"),
1245 interface
= _SCNetworkInterfaceCreateWithIONetworkInterfaceObject(entry
);
1248 if (masterPort
!= MACH_PORT_NULL
) {
1249 mach_port_deallocate(mach_task_self(), masterPort
);
1251 if (entry
!= MACH_PORT_NULL
) {
1252 IOObjectRelease(entry
);
1257 #endif // USE_REGISTRY_ENTRY_ID
1260 displayInterface(SCNetworkInterfaceRef interface
)
1267 name
= SCNetworkInterfaceGetBSDName(interface
);
1268 unit
= _SCNetworkInterfaceGetIOInterfaceUnit(interface
);
1269 type
= _SCNetworkInterfaceGetIOInterfaceType(interface
);
1270 addr
= SCNetworkInterfaceGetHardwareAddressString(interface
);
1272 SCLog(TRUE
, LOG_INFO
,
1273 CFSTR(MY_PLUGIN_NAME
": %s%@%sType: %@, %s%@%sMAC address: %@"),
1274 (name
!= NULL
) ? "BSD Name: " : "",
1275 (name
!= NULL
) ? name
: CFSTR(""),
1276 (name
!= NULL
) ? ", " : "",
1278 (unit
!= NULL
) ? "Unit: " : "",
1279 (unit
!= NULL
) ? (CFTypeRef
)unit
: (CFTypeRef
)CFSTR(""),
1280 (unit
!= NULL
) ? ", " : "",
1285 builtinCount(CFArrayRef if_list
, CFIndex last
, CFNumberRef if_type
)
1290 for (i
= 0; i
< last
; i
++) {
1291 SCNetworkInterfaceRef builtin_if
;
1292 CFNumberRef builtin_type
;
1294 builtin_if
= CFArrayGetValueAtIndex(if_list
, i
);
1295 builtin_type
= _SCNetworkInterfaceGetIOInterfaceType(builtin_if
);
1296 if (CFEqual(if_type
, builtin_type
)) {
1297 if (_SCNetworkInterfaceIsBuiltin(builtin_if
)) {
1298 n
++; // if built-in interface
1306 static __inline__ boolean_t
1309 return (S_quiet
== MACH_PORT_NULL
);
1313 nameInterfaces(CFMutableArrayRef if_list
)
1316 CFIndex n
= CFArrayGetCount(if_list
);
1318 for (i
= 0; i
< n
; i
++) {
1320 SCNetworkInterfaceRef interface
;
1328 interface
= CFArrayGetValueAtIndex(if_list
, i
);
1329 path
= _SCNetworkInterfaceGetIOPath(interface
);
1330 type
= _SCNetworkInterfaceGetIOInterfaceType(interface
);
1331 unit
= _SCNetworkInterfaceGetIOInterfaceUnit(interface
);
1332 entryID
= _SCNetworkInterfaceGetIORegistryEntryID(interface
);
1336 CFStringRef if_name
;
1338 if_name
= SCNetworkInterfaceGetBSDName(interface
);
1339 if ((if_name
== NULL
) || !CFDictionaryContainsKey(S_state
, if_name
)) {
1340 SCLog(TRUE
, LOG_INFO
,
1341 CFSTR(MY_PLUGIN_NAME
": Interface already has a unit number"));
1342 displayInterface(interface
);
1346 // update the list of interfaces that were previously named
1347 if ((S_prev_active_list
!= NULL
)
1348 && lookupInterfaceByAddress(S_prev_active_list
, interface
, &where
) != NULL
) {
1349 CFArrayRemoveValueAtIndex(S_prev_active_list
, where
);
1352 CFDictionaryRef dbdict
;
1353 boolean_t is_builtin
;
1357 dbdict
= lookupInterfaceByAddress(S_dblist
, interface
, NULL
);
1358 if (dbdict
!= NULL
) {
1359 unit
= CFDictionaryGetValue(dbdict
, CFSTR(kIOInterfaceUnit
));
1362 SCLog(S_debug
, LOG_INFO
,
1363 CFSTR(MY_PLUGIN_NAME
": Interface assigned unit %@ (from database)"),
1367 if ((dbdict
== NULL
) && !isQuiet()) {
1368 // if new interface, wait until quiet before naming
1369 addTimestamp(S_state
, path
);
1373 is_builtin
= _SCNetworkInterfaceIsBuiltin(interface
);
1375 if (dbdict
== NULL
) {
1376 dbdict
= lookupMatchingInterface(interface
,
1380 is_builtin
? kCFBooleanTrue
: kCFBooleanFalse
);
1381 if (dbdict
!= NULL
) {
1382 unit
= CFDictionaryGetValue(dbdict
, CFSTR(kIOInterfaceUnit
));
1385 SCLog(S_debug
, LOG_INFO
,
1386 CFSTR(MY_PLUGIN_NAME
": Interface assigned unit %@ (updating database)"),
1391 if ((dbdict
!= NULL
) && (S_prev_active_list
!= NULL
)) {
1392 // update the list of interfaces that were previously named
1393 where
= CFArrayGetFirstIndexOfValue(S_prev_active_list
,
1394 CFRangeMake(0, CFArrayGetCount(S_prev_active_list
)),
1396 if (where
!= kCFNotFound
) {
1397 CFArrayRemoveValueAtIndex(S_prev_active_list
, where
);
1401 if (dbdict
== NULL
) {
1405 // built-in interface, use the reserved slots
1406 next_unit
= builtinCount(if_list
, i
, type
);
1408 // not built-in, skip over the reserved slots
1409 next_unit
= builtinCount(if_list
, n
, type
);
1411 unit
= getHighestUnitForType(type
);
1415 CFNumberGetValue(unit
, kCFNumberIntType
, &high_unit
);
1416 if (high_unit
>= next_unit
) {
1417 next_unit
= high_unit
+ 1;
1421 unit
= CFNumberCreate(NULL
, kCFNumberIntType
, &next_unit
);
1423 SCLog(S_debug
, LOG_INFO
,
1424 CFSTR(MY_PLUGIN_NAME
": Interface assigned unit %@ (%s)"),
1426 is_builtin
? "built-in" : "next available");
1431 #ifdef USE_REGISTRY_ENTRY_ID
1432 kr
= registerInterfaceWithIORegistryEntryID(S_connect
,
1435 (dbdict
== NULL
) ? kIONetworkStackRegisterInterfaceWithLowestUnit
1436 : kIONetworkStackRegisterInterfaceWithUnit
);
1437 #else // USE_REGISTRY_ENTRY_ID
1438 kr
= registerInterfaceWithIOServicePath(S_connect
,
1441 (dbdict
== NULL
) ? kRegisterInterface
1442 : kRegisterInterfaceWithFixedUnit
);
1443 #endif // USE_REGISTRY_ENTRY_ID
1444 if (kr
!= KERN_SUCCESS
) {
1445 const char *signature
;
1447 signature
= (dbdict
== NULL
) ? "failed to name new interface"
1448 : "failed to name known interface";
1450 SCLog(TRUE
, LOG_ERR
,
1451 CFSTR(MY_PLUGIN_NAME
": %s, kr=0x%x\n"
1452 MY_PLUGIN_NAME
": path = %@\n"
1453 MY_PLUGIN_NAME
": id = 0x%llx\n"
1454 MY_PLUGIN_NAME
": unit = %@"),
1462 displayInterface(interface
);
1465 // report issue w/MessageTracer
1466 str
= CFStringCreateWithFormat(NULL
, NULL
,
1467 CFSTR("kr=0x%x, path=%@, unit=%@"),
1471 reportIssue(signature
, str
);
1474 if ((dbdict
!= NULL
) && (retries
++ < 5)) {
1475 usleep(50 * 1000); // sleep 50ms between attempts
1479 ok
= FALSE
; // ... and don't update the database
1481 SCNetworkInterfaceRef new_interface
;
1484 SCLog(TRUE
, LOG_ERR
,
1485 CFSTR(MY_PLUGIN_NAME
": %s interface named after %d %s\n"
1486 MY_PLUGIN_NAME
": path = %@\n"
1487 MY_PLUGIN_NAME
": unit = %@"),
1488 (dbdict
== NULL
) ? "New" : "Known",
1490 (retries
== 1) ? "try" : "tries",
1494 #ifdef SHOW_NAMING_FAILURE
1495 str
= CFStringCreateWithFormat(NULL
,
1497 CFSTR("\"%s\" interface named after %d %s, unit = %@"),
1498 (dbdict
== NULL
) ? "New" : "Known",
1500 (retries
== 1) ? "try" : "tries",
1502 CFUserNotificationDisplayNotice(0,
1503 kCFUserNotificationStopAlertLevel
,
1508 CFSTR("Please report repeated failures."),
1511 #endif // SHOW_NAMING_FAILURE
1514 #ifdef USE_REGISTRY_ENTRY_ID
1515 new_interface
= lookupIORegistryEntryID(entryID
);
1516 #else // USE_REGISTRY_ENTRY_ID
1517 new_interface
= lookupIOKitPath(path
);
1518 #endif // USE_REGISTRY_ENTRY_ID
1519 if (new_interface
!= NULL
) {
1520 CFNumberRef new_unit
;
1522 new_unit
= _SCNetworkInterfaceGetIOInterfaceUnit(new_interface
);
1523 if (CFEqual(unit
, new_unit
) == FALSE
) {
1524 SCLog(S_debug
, LOG_INFO
,
1525 CFSTR(MY_PLUGIN_NAME
1526 ": interface type %@ assigned "
1527 "unit %@ instead of %@"),
1528 type
, new_unit
, unit
);
1531 displayInterface(new_interface
);
1534 // update if_list (with the interface name & unit)
1535 CFArraySetValueAtIndex(if_list
, i
, new_interface
);
1536 CFRelease(new_interface
);
1537 interface
= new_interface
; // if_list holds the reference
1539 if (is_builtin
&& (S_prev_active_list
!= NULL
)) {
1542 // update the list of [built-in] interfaces that were previously named
1543 if (lookupInterfaceByUnit(S_prev_active_list
, interface
, &where
) != NULL
) {
1544 SCLog(S_debug
, LOG_INFO
,
1545 CFSTR(MY_PLUGIN_NAME
": and updated database (new address)"));
1546 CFArrayRemoveValueAtIndex(S_prev_active_list
, where
);
1557 replaceInterface(interface
);
1566 if (S_connect
== MACH_PORT_NULL
) {
1567 // if we don't have the "IONetworkStack" connect object
1571 if (S_iflist
!= NULL
) {
1574 n
= CFArrayGetCount(S_iflist
);
1576 CFArraySortValues(S_iflist
, CFRangeMake(0, n
), _SCNetworkInterfaceCompare
, NULL
);
1578 nameInterfaces(S_iflist
);
1583 * The registry [matching] has quiesced so let's
1584 * - save the DB with the interfaces that have been named
1585 * - update the VLAN/BOND configuration
1586 * - tell everyone that we've finished (at least for now)
1587 * - log those interfaces which are no longer present
1588 * in the HW config (or have yet to show up).
1590 writeInterfaceList(S_dblist
);
1591 updateVirtualNetworkInterfaceConfiguration(NULL
, kSCPreferencesNotificationApply
, NULL
);
1594 if (S_iflist
!= NULL
) {
1595 CFRelease(S_iflist
);
1599 if (S_prev_active_list
!= NULL
) {
1604 n
= CFArrayGetCount(S_prev_active_list
);
1606 SCLog(TRUE
, LOG_INFO
,
1607 CFSTR(MY_PLUGIN_NAME
": Interface%s not [yet] active"),
1608 (n
> 1) ? "s" : "");
1610 for (i
= 0; i
< n
; i
++) {
1611 CFDictionaryRef if_dict
;
1616 if_dict
= CFArrayGetValueAtIndex(S_prev_active_list
, i
);
1617 name
= CFDictionaryGetValue(if_dict
, CFSTR(kIOBSDNameKey
));
1618 type
= CFDictionaryGetValue(if_dict
, CFSTR(kIOInterfaceType
));
1619 unit
= CFDictionaryGetValue(if_dict
, CFSTR(kIOInterfaceUnit
));
1620 SCLog(TRUE
, LOG_INFO
,
1621 CFSTR(MY_PLUGIN_NAME
": %s%@%sType: %@, Unit: %@"),
1622 (name
!= NULL
) ? "BSD Name: " : "",
1623 (name
!= NULL
) ? name
: CFSTR(""),
1624 (name
!= NULL
) ? ", " : "",
1629 CFRelease(S_prev_active_list
);
1630 S_prev_active_list
= NULL
;
1633 if ((S_prev_active_list
!= NULL
) && (CFArrayGetCount(S_prev_active_list
) == 0)) {
1635 * if we've named all of the interfaces that
1636 * were used during the previous boot.
1638 addTimestamp(S_state
, CFSTR("*RELEASE*"));
1639 SCLog(S_debug
, LOG_INFO
,
1640 CFSTR(MY_PLUGIN_NAME
": last boot interfaces have been named"));
1642 CFRelease(S_prev_active_list
);
1643 S_prev_active_list
= NULL
;
1650 static CFComparisonResult
1651 compareMacAddress(const void *val1
, const void *val2
, void *context
)
1653 CFDataRef mac1
= (CFDataRef
)val1
;
1654 CFDataRef mac2
= (CFDataRef
)val2
;
1657 CFComparisonResult res
;
1659 n1
= CFDataGetLength(mac1
);
1660 n2
= CFDataGetLength(mac2
);
1662 res
= kCFCompareLessThan
;
1663 } else if (n2
> n1
) {
1664 res
= kCFCompareGreaterThan
;
1666 res
= bcmp(CFDataGetBytePtr(mac1
), CFDataGetBytePtr(mac2
), n1
);
1672 #ifndef kIOPlatformUUIDKey
1673 #define kIOPlatformUUIDKey "IOPlatformUUID"
1676 updatePlatformUUID()
1679 CFMutableArrayRef addrs
= NULL
;
1683 io_registry_entry_t platform
;
1685 platform
= IORegistryEntryFromPath(kIOMasterPortDefault
, kIODeviceTreePlane
":/");
1686 if (platform
== MACH_PORT_NULL
) {
1690 guid
= IORegistryEntryCreateCFProperty(platform
, CFSTR(kIOPlatformUUIDKey
), NULL
, 0);
1692 // if GUID already defined
1696 addrs
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1697 n
= (S_dblist
!= NULL
) ? CFArrayGetCount(S_dblist
) : 0;
1698 for (i
= 0; i
< n
; i
++) {
1699 CFBooleanRef builtin
;
1700 CFDictionaryRef dict
;
1703 dict
= CFArrayGetValueAtIndex(S_dblist
, i
);
1704 type
= CFDictionaryGetValue(dict
, CFSTR(kSCNetworkInterfaceType
));
1705 if (!isA_CFString(type
) || !CFEqual(type
, kSCNetworkInterfaceTypeEthernet
)) {
1708 builtin
= CFDictionaryGetValue(dict
, CFSTR(kIOBuiltin
));
1709 if (!isA_CFBoolean(builtin
) || !CFBooleanGetValue(builtin
)) {
1712 addr
= CFDictionaryGetValue(dict
, CFSTR(kIOMACAddress
));
1713 if (!isA_CFData(addr
) || (CFDataGetLength(addr
) != ETHER_ADDR_LEN
)) {
1716 CFArrayAppendValue(addrs
, addr
);
1719 if (CFArrayGetCount(addrs
) == 0) {
1720 // if no ethernet interfaces, look for wireless
1721 for (i
= 0; i
< n
; i
++) {
1722 CFDictionaryRef dict
;
1725 dict
= CFArrayGetValueAtIndex(S_dblist
, i
);
1726 type
= CFDictionaryGetValue(dict
, CFSTR(kSCNetworkInterfaceType
));
1727 if (!isA_CFString(type
) || !CFEqual(type
, kSCNetworkInterfaceTypeIEEE80211
)) {
1730 addr
= CFDictionaryGetValue(dict
, CFSTR(kIOMACAddress
));
1731 if (!isA_CFData(addr
) || (CFDataGetLength(addr
) != ETHER_ADDR_LEN
)) {
1734 CFArrayAppendValue(addrs
, addr
);
1738 n
= CFArrayGetCount(addrs
);
1741 SCLog(TRUE
, LOG_ERR
,
1742 CFSTR(MY_PLUGIN_NAME
": no network interfaces, could not update platform UUID"));
1745 // sort by MAC address
1746 CFArraySortValues(addrs
, CFRangeMake(0, n
), compareMacAddress
, NULL
);
1750 CFUUIDBytes bytes
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
1751 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1756 addr
= CFArrayGetValueAtIndex(addrs
, 0);
1757 bcopy(CFDataGetBytePtr(addr
),
1758 (void *)&bytes
+ sizeof(bytes
) - ETHER_ADDR_LEN
,
1760 uuid
= CFUUIDCreateFromUUIDBytes(NULL
, bytes
);
1761 guid
= CFUUIDCreateString(NULL
, uuid
);
1764 SCLog(TRUE
, LOG_INFO
,
1765 CFSTR(MY_PLUGIN_NAME
": setting platform UUID = %@"),
1767 kr
= IORegistryEntrySetCFProperty(platform
, CFSTR(kIOPlatformUUIDKey
), guid
);
1768 if (kr
!= KERN_SUCCESS
) {
1769 SCLog(TRUE
, LOG_ERR
,
1770 CFSTR(MY_PLUGIN_NAME
": IORegistryEntrySetCFProperty(platform UUID) failed, kr=0x%x"),
1774 addTimestamp(S_state
, CFSTR("*PLATFORM-UUID*"));
1782 if (addrs
!= NULL
) CFRelease(addrs
);
1783 if (platform
!= MACH_PORT_NULL
) IOObjectRelease(platform
);
1784 if (guid
!= NULL
) CFRelease(guid
);
1789 interfaceArrivalCallback(void *refcon
, io_iterator_t iter
)
1793 while ((obj
= IOIteratorNext(iter
)) != MACH_PORT_NULL
) {
1794 SCNetworkInterfaceRef interface
;
1796 interface
= _SCNetworkInterfaceCreateWithIONetworkInterfaceObject(obj
);
1797 if (interface
!= NULL
) {
1798 if (S_iflist
== NULL
) {
1799 S_iflist
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1801 CFArrayAppendValue(S_iflist
, interface
);
1802 CFRelease(interface
);
1804 IOObjectRelease(obj
);
1812 * Function: stackCallback
1814 * Get a reference to the single IONetworkStack object instance in
1815 * the kernel. Naming requests must be sent to this object, which is
1816 * attached as a client to all network interface objects in the system.
1818 * Call IOObjectRelease on the returned object.
1821 stackCallback(void *refcon
, io_iterator_t iter
)
1826 stack
= IOIteratorNext(iter
);
1827 if (stack
== MACH_PORT_NULL
) {
1831 kr
= IOServiceOpen(stack
, mach_task_self(), 0, &S_connect
);
1832 if (kr
!= KERN_SUCCESS
) {
1833 SCLog(TRUE
, LOG_ERR
,
1834 CFSTR(MY_PLUGIN_NAME
": IOServiceOpen returned 0x%x"),
1839 addTimestamp(S_state
, CFSTR("*STACK*"));
1840 SCLog(S_debug
, LOG_INFO
,
1841 CFSTR(MY_PLUGIN_NAME
": IONetworkStack found"));
1843 if (S_stack
!= MACH_PORT_NULL
) {
1844 IOObjectRelease(S_stack
);
1845 S_stack
= MACH_PORT_NULL
;
1848 if ((S_timer
!= NULL
) && CFRunLoopTimerIsValid(S_timer
)) {
1849 // With the IONetworkStack object now available we can
1850 // reset (shorten?) the time we are willing to wait for
1851 // IOKit to quiesce.
1852 CFRunLoopTimerSetNextFireDate(S_timer
,
1853 CFAbsoluteTimeGetCurrent() + S_quiet_timeout
);
1859 if (stack
!= MACH_PORT_NULL
) {
1860 IOObjectRelease(stack
);
1867 quietCallback(void *refcon
,
1868 io_service_t service
,
1869 natural_t messageType
,
1870 void *messageArgument
)
1872 if (messageArgument
!= NULL
) {
1877 if (messageType
== kIOMessageServiceBusyStateChange
) {
1878 addTimestamp(S_state
, CFSTR("*QUIET*"));
1879 SCLog(S_debug
, LOG_INFO
,
1880 CFSTR(MY_PLUGIN_NAME
": IOKit quiet"));
1883 if (S_connect
== MACH_PORT_NULL
) {
1884 SCLog(TRUE
, LOG_ERR
,
1885 CFSTR(MY_PLUGIN_NAME
": No network stack object"));
1889 if (S_quiet
!= MACH_PORT_NULL
) {
1890 IOObjectRelease(S_quiet
);
1891 S_quiet
= MACH_PORT_NULL
;
1894 if (S_timer
!= NULL
) {
1895 CFRunLoopTimerInvalidate(S_timer
);
1900 // grab (and name) any additional interfaces.
1901 interfaceArrivalCallback((void *)S_notify
, S_iter
);
1903 updatePlatformUUID();
1909 iterateRegistryBusy(io_iterator_t iterator
, CFArrayRef nodes
, CFMutableStringRef snapshot
, int *count
)
1911 kern_return_t kr
= kIOReturnSuccess
;;
1914 while ((kr
== kIOReturnSuccess
) &&
1915 ((obj
= IOIteratorNext(iterator
)) != MACH_PORT_NULL
)) {
1916 uint64_t accumulated_busy_time
;
1917 uint32_t busy_state
;
1920 CFMutableArrayRef newNodes
;
1922 CFMutableStringRef str
= NULL
;
1924 if (nodes
== NULL
) {
1925 newNodes
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1927 newNodes
= CFArrayCreateMutableCopy(NULL
, 0, nodes
);
1930 kr
= IORegistryEntryGetName(obj
, name
);
1931 if (kr
!= kIOReturnSuccess
) {
1932 SCLog(TRUE
, LOG_ERR
,
1933 CFSTR(MY_PLUGIN_NAME
": captureBusy IORegistryEntryGetName returned 0x%x"),
1938 str
= CFStringCreateMutable(NULL
, 0);
1939 CFStringAppendCString(str
, name
, kCFStringEncodingUTF8
);
1941 kr
= IORegistryEntryGetLocationInPlane(obj
, kIOServicePlane
, location
);
1943 case kIOReturnSuccess
:
1944 CFStringAppendCString(str
, "@", kCFStringEncodingUTF8
);
1945 CFStringAppendCString(str
, location
, kCFStringEncodingUTF8
);
1947 case kIOReturnNotFound
:
1950 SCLog(TRUE
, LOG_ERR
,
1951 CFSTR(MY_PLUGIN_NAME
": captureBusy IORegistryEntryGetLocationInPlane returned 0x%x"),
1957 CFArrayAppendValue(newNodes
, str
);
1960 kr
= IOServiceGetBusyStateAndTime(obj
, &state
, &busy_state
, &accumulated_busy_time
);
1961 if (kr
!= kIOReturnSuccess
) {
1962 SCLog(TRUE
, LOG_ERR
,
1963 CFSTR(MY_PLUGIN_NAME
": captureBusy IOServiceGetBusyStateAndTime returned 0x%x"),
1968 #ifdef TEST_SNAPSHOT
1971 #endif // TEST_SNAPSHOT
1973 if (busy_state
!= 0) {
1976 if ((*count
)++ == 0) {
1977 CFStringAppend(snapshot
, CFSTR("Busy services :"));
1980 path
= CFStringCreateByCombiningStrings(NULL
, newNodes
, CFSTR("/"));
1981 CFStringAppendFormat(snapshot
, NULL
,
1982 CFSTR("\n %@ [%s%s%s%d, %lld ms]"),
1984 (state
& kIOServiceRegisteredState
) ? "" : "!registered, ",
1985 (state
& kIOServiceMatchedState
) ? "" : "!matched, ",
1986 (state
& kIOServiceInactiveState
) ? "inactive, " : "",
1987 accumulated_busy_time
/ kMillisecondScale
);
1991 kr
= IORegistryIteratorEnterEntry(iterator
);
1992 if (kr
!= kIOReturnSuccess
) {
1993 SCLog(TRUE
, LOG_ERR
,
1994 CFSTR(MY_PLUGIN_NAME
": captureBusy IORegistryIteratorEnterEntry returned 0x%x"),
1999 iterateRegistryBusy(iterator
, newNodes
, snapshot
, count
);
2001 kr
= IORegistryIteratorExitEntry(iterator
);
2002 if (kr
!= kIOReturnSuccess
) {
2003 SCLog(TRUE
, LOG_ERR
,
2004 CFSTR(MY_PLUGIN_NAME
": captureBusy IORegistryIteratorExitEntry returned 0x%x"),
2010 CFRelease(newNodes
);
2011 IOObjectRelease(obj
);
2021 io_iterator_t iterator
= MACH_PORT_NULL
;
2023 CFMutableStringRef snapshot
;
2025 snapshot
= CFStringCreateMutable(NULL
, 0);
2027 kr
= IORegistryCreateIterator(kIOMasterPortDefault
,
2031 if (kr
!= kIOReturnSuccess
) {
2032 SCLog(TRUE
, LOG_ERR
,
2033 CFSTR(MY_PLUGIN_NAME
": captureBusy IORegistryCreateIterator returned 0x%x"),
2038 iterateRegistryBusy(iterator
, NULL
, snapshot
, &count
);
2040 CFStringAppend(snapshot
, CFSTR("w/no busy services"));
2043 IOObjectRelease(iterator
);
2048 timerCallback(CFRunLoopTimerRef timer
, void *info
)
2050 CFStringRef snapshot
;
2052 // We've been waiting for IOKit to quiesce and it just
2053 // hasn't happenned. Time to just move on!
2054 addTimestamp(S_state
, CFSTR("*TIMEOUT*"));
2057 snapshot
= captureBusy();
2058 SCLog(TRUE
, LOG_ERR
,
2059 CFSTR(MY_PLUGIN_NAME
": timed out waiting for IOKit to quiesce\n%@"),
2061 reportIssue("timed out waiting for IOKit to quiesce", snapshot
);
2062 CFRelease(snapshot
);
2064 quietCallback((void *)S_notify
, MACH_PORT_NULL
, 0, NULL
);
2069 setup_IOKit(CFBundleRef bundle
)
2073 mach_port_t masterPort
= MACH_PORT_NULL
;
2075 io_object_t root
= MACH_PORT_NULL
;
2077 // read DB of previously named network interfaces
2078 S_dblist
= readInterfaceList();
2079 if (S_dblist
!= NULL
) {
2082 n
= CFArrayGetCount(S_dblist
);
2084 CFArraySortValues(S_dblist
, CFRangeMake(0, n
), if_unit_compare
, NULL
);
2088 // get interfaces that were named during the last boot
2089 S_prev_active_list
= previouslyActiveInterfaces();
2091 // track how long we've waited to see each interface.
2092 S_state
= CFDictionaryCreateMutable(NULL
,
2094 &kCFTypeDictionaryKeyCallBacks
,
2095 &kCFTypeDictionaryValueCallBacks
);
2096 addTimestamp(S_state
, CFSTR("*START*"));
2098 // Creates and returns a notification object for receiving IOKit
2099 // notifications of new devices or state changes.
2100 kr
= IOMasterPort(bootstrap_port
, &masterPort
);
2101 if (kr
!= KERN_SUCCESS
) {
2102 SCLog(TRUE
, LOG_ERR
,
2103 CFSTR(MY_PLUGIN_NAME
": IOMasterPort returned 0x%x"),
2108 S_notify
= IONotificationPortCreate(masterPort
);
2109 if (S_notify
== NULL
) {
2110 SCLog(TRUE
, LOG_ERR
,
2111 CFSTR(MY_PLUGIN_NAME
": IONotificationPortCreate failed"));
2115 // watch IOKit matching activity
2116 root
= IORegistryEntryFromPath(masterPort
, kIOServicePlane
":/");
2117 if (root
== MACH_PORT_NULL
) {
2118 SCLog(TRUE
, LOG_ERR
,
2119 CFSTR(MY_PLUGIN_NAME
": IORegistryEntryFromPath failed"));
2123 kr
= IOServiceAddInterestNotification(S_notify
,
2127 (void *)S_notify
, // refCon
2128 &S_quiet
); // notification
2129 if (kr
!= KERN_SUCCESS
) {
2130 SCLog(TRUE
, LOG_ERR
,
2131 CFSTR(MY_PLUGIN_NAME
": IOServiceAddInterestNotification returned 0x%x"),
2136 kr
= IOServiceGetBusyState(root
, &busy
);
2137 if (kr
!= KERN_SUCCESS
) {
2138 SCLog(TRUE
, LOG_ERR
,
2139 CFSTR(MY_PLUGIN_NAME
": IOServiceGetBusyState returned 0x%x"),
2144 // add a timer so we don't wait forever for IOKit to quiesce
2145 S_timer
= CFRunLoopTimerCreate(NULL
,
2146 CFAbsoluteTimeGetCurrent() + S_stack_timeout
,
2152 if (S_timer
== NULL
) {
2153 SCLog(TRUE
, LOG_ERR
,
2154 CFSTR(MY_PLUGIN_NAME
": CFRunLoopTimerCreate failed"));
2158 CFRunLoopAddTimer(CFRunLoopGetCurrent(), S_timer
, kCFRunLoopDefaultMode
);
2160 // watch for the introduction of the IONetworkStack
2161 kr
= IOServiceAddMatchingNotification(S_notify
,
2162 kIOFirstMatchNotification
,
2163 IOServiceMatching("IONetworkStack"),
2165 (void *)S_notify
, // refCon
2166 &S_stack
); // notification
2167 if (kr
!= KERN_SUCCESS
) {
2168 SCLog(TRUE
, LOG_ERR
,
2169 CFSTR(MY_PLUGIN_NAME
": IOServiceAddMatchingNotification returned 0x%x"),
2174 // check and see if the stack is already available and arm the
2175 // notification for its introduction.
2176 stackCallback((void *)S_notify
, S_stack
);
2178 // watch for the introduction of new network interfaces
2179 kr
= IOServiceAddMatchingNotification(S_notify
,
2180 kIOFirstMatchNotification
,
2181 IOServiceMatching("IONetworkInterface"),
2182 &interfaceArrivalCallback
,
2183 (void *)S_notify
, // refCon
2184 &S_iter
); // notification
2185 if (kr
!= KERN_SUCCESS
) {
2186 SCLog(TRUE
, LOG_ERR
,
2187 CFSTR(MY_PLUGIN_NAME
": IOServiceAddMatchingNotification returned 0x%x"),
2192 // Get the current list of matches and arm the notification for
2193 // future interface arrivals.
2194 interfaceArrivalCallback((void *)S_notify
, S_iter
);
2196 // Check if IOKit has already quiesced.
2197 quietCallback((void *)S_notify
,
2199 kIOMessageServiceBusyStateChange
,
2200 (void *)(uintptr_t)busy
);
2202 CFRunLoopAddSource(CFRunLoopGetCurrent(),
2203 IONotificationPortGetRunLoopSource(S_notify
),
2204 kCFRunLoopDefaultMode
);
2206 #ifdef WAIT_PREVIOUS_BOOT_INTERFACES_OR_QUIET
2208 * Start the wheels turning until we've named all of
2209 * the interfaces that were used during the previous
2210 * boot, until IOKit [matching] has quiesced, or
2211 * until we've waited long enough.
2213 CFRunLoopAddTimer(CFRunLoopGetCurrent(), S_timer
, MY_PLUGIN_ID
);
2214 CFRunLoopAddSource(CFRunLoopGetCurrent(),
2215 IONotificationPortGetRunLoopSource(S_notify
),
2217 while (S_prev_active_list
!= NULL
) {
2220 rlStatus
= CFRunLoopRunInMode(MY_PLUGIN_ID
, 1.0e10
, TRUE
);
2222 #endif /* WAIT_PREVIOUS_BOOT_INTERFACES_OR_QUIET */
2227 if (root
!= MACH_PORT_NULL
) {
2228 IOObjectRelease(root
);
2230 if (masterPort
!= MACH_PORT_NULL
) {
2231 mach_port_deallocate(mach_task_self(), masterPort
);
2238 setup_Virtual(CFBundleRef bundle
)
2240 // open a SCPreferences session
2241 S_prefs
= SCPreferencesCreate(NULL
, CFSTR(MY_PLUGIN_NAME
), NULL
);
2242 if (S_prefs
== NULL
) {
2243 SCLog(TRUE
, LOG_ERR
,
2244 CFSTR(MY_PLUGIN_NAME
": SCPreferencesCreate() failed: %s"),
2245 SCErrorString(SCError()));
2249 // register for change notifications.
2250 if (!SCPreferencesSetCallback(S_prefs
, updateVirtualNetworkInterfaceConfiguration
, NULL
)) {
2251 SCLog(TRUE
, LOG_ERR
,
2252 CFSTR(MY_PLUGIN_NAME
": SCPreferencesSetCallBack() failed: %s"),
2253 SCErrorString(SCError()));
2259 if (!SCPreferencesScheduleWithRunLoop(S_prefs
, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode
)) {
2260 if (SCError() != kSCStatusNoStoreServer
) {
2261 SCLog(TRUE
, LOG_ERR
,
2262 CFSTR(MY_PLUGIN_NAME
": SCPreferencesScheduleWithRunLoop() failed: %s"),
2263 SCErrorString(SCError()));
2273 exec_InterfaceNamer(void *arg
)
2275 CFBundleRef bundle
= (CFBundleRef
)arg
;
2276 CFDictionaryRef dict
;
2278 #if !TARGET_OS_EMBEDDED
2279 pthread_setname_np(MY_PLUGIN_NAME
" thread");
2280 #endif // !TARGET_OS_EMBEDDED
2282 dict
= CFBundleGetInfoDictionary(bundle
);
2283 if (isA_CFDictionary(dict
)) {
2286 num
= CFDictionaryGetValue(dict
, CFSTR(WAIT_STACK_TIMEOUT_KEY
));
2288 if (!isA_CFNumber(num
) ||
2289 !CFNumberGetValue(num
, kCFNumberDoubleType
, &S_stack_timeout
) ||
2290 (S_stack_timeout
<= 0.0)) {
2291 SCLog(TRUE
, LOG_ERR
,
2292 CFSTR(MY_PLUGIN_NAME
": " WAIT_STACK_TIMEOUT_KEY
" value error"));
2293 S_stack_timeout
= WAIT_STACK_TIMEOUT_DEFAULT
;
2297 num
= CFDictionaryGetValue(dict
, CFSTR(WAIT_QUIET_TIMEOUT_KEY
));
2299 if (!isA_CFNumber(num
) ||
2300 !CFNumberGetValue(num
, kCFNumberDoubleType
, &S_quiet_timeout
) ||
2301 (S_quiet_timeout
<= 0.0)) {
2302 SCLog(TRUE
, LOG_ERR
,
2303 CFSTR(MY_PLUGIN_NAME
": " WAIT_QUIET_TIMEOUT_KEY
" value error"));
2304 S_quiet_timeout
= WAIT_QUIET_TIMEOUT_DEFAULT
;
2309 // setup virtual network interface monitoring
2310 if (!setup_Virtual(bundle
)) {
2314 // setup [IOKit] network interface monitoring
2315 if (!setup_IOKit(bundle
)) {
2322 if (S_connect
!= MACH_PORT_NULL
) {
2323 IOServiceClose(S_connect
);
2324 S_connect
= MACH_PORT_NULL
;
2326 if (S_dblist
!= NULL
) {
2327 CFRelease(S_dblist
);
2330 if (S_iter
!= MACH_PORT_NULL
) {
2331 IOObjectRelease(S_iter
);
2332 S_iter
= MACH_PORT_NULL
;
2334 if (S_notify
!= MACH_PORT_NULL
) {
2335 IONotificationPortDestroy(S_notify
);
2337 if (S_quiet
!= MACH_PORT_NULL
) {
2338 IOObjectRelease(S_quiet
);
2339 S_quiet
= MACH_PORT_NULL
;
2341 if (S_stack
!= MACH_PORT_NULL
) {
2342 IOObjectRelease(S_stack
);
2343 S_stack
= MACH_PORT_NULL
;
2345 if (S_state
!= NULL
) {
2349 if (S_timer
!= NULL
) {
2350 CFRunLoopTimerInvalidate(S_timer
);
2356 #if !TARGET_OS_EMBEDDED
2359 #endif // !TARGET_OS_EMBEDDED
2366 load_InterfaceNamer(CFBundleRef bundle
, Boolean bundleVerbose
)
2368 if (bundleVerbose
) {
2372 #if !TARGET_OS_EMBEDDED
2374 pthread_attr_t tattr
;
2377 CFRetain(bundle
); // released in exec_InterfaceNamer
2379 pthread_attr_init(&tattr
);
2380 pthread_attr_setscope(&tattr
, PTHREAD_SCOPE_SYSTEM
);
2381 pthread_attr_setdetachstate(&tattr
, PTHREAD_CREATE_DETACHED
);
2382 // pthread_attr_setstacksize(&tattr, 96 * 1024); // each thread gets a 96K stack
2383 pthread_create(&tid
, &tattr
, exec_InterfaceNamer
, bundle
);
2384 pthread_attr_destroy(&tattr
);
2386 #else // !TARGET_OS_EMBEDDED
2387 (void)exec_InterfaceNamer(bundle
);
2388 #endif // !TARGET_OS_EMBEDDED
2393 //------------------------------------------------------------------------
2397 main(int argc
, char ** argv
)
2400 _sc_verbose
= (argc
> 1) ? TRUE
: FALSE
;
2402 load_InterfaceNamer(CFBundleGetMainBundle(), (argc
> 1) ? TRUE
: FALSE
);
2410 #ifdef TEST_PLATFORM_UUID
2412 main(int argc
, char ** argv
)
2414 CFArrayRef interfaces
;
2417 _sc_verbose
= (argc
> 1) ? TRUE
: FALSE
;
2419 S_dblist
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
2420 interfaces
= SCNetworkInterfaceCopyAll();
2421 if (interfaces
!= NULL
) {
2425 n
= CFArrayGetCount(interfaces
);
2426 for (i
= 0; i
< n
; i
++) {
2427 CFDictionaryRef dict
;
2428 SCNetworkInterfaceRef interface
;
2430 interface
= CFArrayGetValueAtIndex(interfaces
, i
);
2431 dict
= createInterfaceDict(interface
);
2432 CFArrayAppendValue(S_dblist
, dict
);
2435 CFRelease(interfaces
);
2437 updatePlatformUUID();
2438 CFRelease(S_dblist
);
2442 #endif /* TEST_PLATFORM_UUID */
2444 #ifdef TEST_SNAPSHOT
2446 main(int argc
, char ** argv
)
2448 CFStringRef snapshot
;
2451 _sc_verbose
= (argc
> 1) ? TRUE
: FALSE
;
2453 snapshot
= captureBusy();
2454 SCPrint(TRUE
, stdout
, CFSTR("%@\n"), snapshot
);
2455 CFRelease(snapshot
);
2460 #endif /* TEST_SNAPSHOT */