2 * Copyright (c) 2001-2007 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 * November 6, 2006 Allan Nathanson <ajn@apple.com>
28 * Dan Markarian <markarian@apple.com>
29 * Dieter Siegmund <dieter@apple.com>
30 * - updated code to name interfaces quicker (without need for
31 * calling IOKitWaitQuiet).
33 * October 3, 2003 Allan Nathanson <ajn@apple.com>
34 * - sort new interfaces by IOKit path (rather than MAC address) to
35 * help facilitate a more predictable interface-->name mapping for
36 * like hardware configurations.
38 * June 23, 2001 Allan Nathanson <ajn@apple.com>
39 * - update to public SystemConfiguration.framework APIs
41 * January 23, 2001 Dieter Siegmund <dieter@apple.com>
47 * - module that receives IOKit Network Interface messages
48 * and names any interface that currently does not have a name
49 * - uses Interface Type and MACAddress as the unique identifying
50 * keys; any interface that doesn't contain both of these properties
51 * is ignored and not processed
52 * - stores the Interface Type, MACAddress, and Unit in permanent storage
53 * to give persistent interface names
61 #include <sys/sockio.h>
63 #include <sys/param.h>
64 #include <mach/mach.h>
65 #include <net/ethernet.h>
66 #include <net/if_types.h>
68 #include <CoreFoundation/CoreFoundation.h>
70 #include <SystemConfiguration/SystemConfiguration.h>
71 #include <SystemConfiguration/SCDPlugin.h>
72 #include <SystemConfiguration/SCPrivate.h> // for SCLog(), SCPrint()
73 #include <SystemConfiguration/SCValidation.h>
75 #include <IOKit/IOKitLib.h>
76 #include <IOKit/IOBSD.h>
77 #include <IOKit/IOMessage.h>
78 #include <IOKit/network/IONetworkController.h>
79 #include <IOKit/network/IONetworkInterface.h>
82 #define kIOBuiltin "IOBuiltin"
85 #define kIONetworkStackUserCommand "IONetworkStackUserCommand"
86 #define kRegisterInterface 1
88 #define kSCNetworkInterfaceType "SCNetworkInterfaceType"
89 #define kSCNetworkInterfaceActive "Active"
91 #define MY_PLUGIN_NAME "InterfaceNamer"
92 #define MY_PLUGIN_ID CFSTR("com.apple.SystemConfiguration." MY_PLUGIN_NAME)
94 #define WAIT_QUIET_TIMEOUT_KEY "WaitQuietTimeout"
95 #define WAIT_QUIET_TIMEOUT_DEFAULT 60.0
99 * "IONetworkStack" connect object used to "name" an interface.
101 static io_connect_t S_connect
= MACH_PORT_NULL
;
105 * An array of CFDictionary's representing the interfaces
106 * that have been identified and [need to be] named.
108 static CFMutableArrayRef S_dblist
= NULL
;
112 * A boolean that enables additional logging.
114 static boolean_t S_debug
= FALSE
;
118 * An array of SCNetworkInterface's representing the
119 * interfaces that have been identified.
121 static CFMutableArrayRef S_iflist
= NULL
;
125 * IOServiceAddMatchingNotification object used to watch for
126 * new network interfaces.
128 static io_iterator_t S_iter
= MACH_PORT_NULL
;
132 * notification object for receiving IOKit notifications of
133 * new devices or state changes.
135 static IONotificationPortRef S_notify
= NULL
;
137 /* S_prev_active_list
138 * An array of CFDictionary's representing the previously
141 static CFMutableArrayRef S_prev_active_list
= NULL
;
145 * IOServiceAddInterestNotification object used to watch for
146 * IOKit matching to quiesce.
148 static io_object_t S_quiet
= MACH_PORT_NULL
;
152 * IOServiceAddMatchingNotification object used to watch for
153 * the availability of the "IONetworkStack" object.
155 static io_iterator_t S_stack
= MACH_PORT_NULL
;
159 * A dictionary containing Information about each network
160 * interface. For now, the key is the BSD name and the
161 * value is a CFNumber noting how long (in milliseconds)
162 * it took for the interface to be recognized/named.
164 static CFMutableDictionaryRef S_state
= NULL
;
168 * CFRunLoopTimer tracking how long we are willing to wait
169 * for IOKit matching to quiesce (IOKitWaitQuiet).
171 static CFRunLoopTimerRef S_timer
= NULL
;
174 * Virtual network interface configuration
175 * S_prefs : SCPreferences to configuration
176 * S_bonds : most recently actived Bond configuration
177 * S_vlans : most recently actived VLAN configuration
179 static SCPreferencesRef S_prefs
= NULL
;
180 static CFArrayRef S_bonds
= NULL
;
181 static CFArrayRef S_vlans
= NULL
;
184 addTimestamp(CFMutableDictionaryRef dict
, CFStringRef key
)
189 now
= CFAbsoluteTimeGetCurrent();
190 val
= CFNumberCreate(NULL
, kCFNumberDoubleType
, &now
);
191 CFDictionaryAddValue(dict
, key
, val
);
196 static CFComparisonResult
197 if_unit_compare(const void *val1
, const void *val2
, void *context
)
199 CFComparisonResult res
;
205 type1
= CFDictionaryGetValue((CFDictionaryRef
)val1
,
206 CFSTR(kIOInterfaceType
));
207 type2
= CFDictionaryGetValue((CFDictionaryRef
)val2
,
208 CFSTR(kIOInterfaceType
));
209 res
= CFNumberCompare(type1
, type2
, NULL
);
210 if (res
!= kCFCompareEqualTo
) {
213 unit1
= CFDictionaryGetValue((CFDictionaryRef
)val1
,
214 CFSTR(kIOInterfaceUnit
));
215 unit2
= CFDictionaryGetValue((CFDictionaryRef
)val2
,
216 CFSTR(kIOInterfaceUnit
));
217 return (CFNumberCompare(unit1
, unit2
, NULL
));
221 read_file(char * filename
, size_t * data_length
)
229 if (stat(filename
, &sb
) == -1)
239 fd
= open(filename
, O_RDONLY
);
243 if (read(fd
, data
, len
) != len
) {
245 CFSTR(MY_PLUGIN_NAME
": read %s failed, %s"),
246 filename
, strerror(errno
));
259 static CFPropertyListRef
260 readPropertyList(char * filename
)
264 CFDataRef data
= NULL
;
265 CFPropertyListRef plist
= NULL
;
266 CFStringRef errorString
= NULL
;
268 buf
= read_file(filename
, &bufsize
);
272 data
= CFDataCreate(NULL
, buf
, bufsize
);
277 plist
= CFPropertyListCreateFromXMLData(NULL
, data
,
278 kCFPropertyListMutableContainers
,
281 if (errorString
!= NULL
) {
283 CFSTR(MY_PLUGIN_NAME
": %@"),
285 CFRelease(errorString
);
296 #define INTERFACES CFSTR("Interfaces")
297 #define NETWORK_INTERFACES_PREFS CFSTR("NetworkInterfaces.plist")
298 #define OLD_NETWORK_INTERFACES_FILE "/var/db/NetworkInterfaces.xml"
301 writeInterfaceList(CFArrayRef if_list
)
304 SCPreferencesRef prefs
;
306 if (isA_CFArray(if_list
) == NULL
) {
310 prefs
= SCPreferencesCreate(NULL
, MY_PLUGIN_ID
, NETWORK_INTERFACES_PREFS
);
313 CFSTR(MY_PLUGIN_NAME
": SCPreferencesCreate failed, %s"),
314 SCErrorString(SCError()));
318 cur_list
= SCPreferencesGetValue(prefs
, INTERFACES
);
319 if (_SC_CFEqual(cur_list
, if_list
)) {
323 if (!SCPreferencesSetValue(prefs
, INTERFACES
, if_list
)) {
325 CFSTR(MY_PLUGIN_NAME
": SCPreferencesSetValue failed, %s"),
326 SCErrorString(SCError()));
330 if (!SCPreferencesCommitChanges(prefs
)) {
331 SCLog((SCError() != EROFS
), LOG_ERR
,
332 CFSTR(MY_PLUGIN_NAME
": SCPreferencesCommitChanges failed, %s"),
333 SCErrorString(SCError()));
343 static CFMutableArrayRef
347 CFMutableArrayRef plist
= NULL
;
348 SCPreferencesRef prefs
= NULL
;
350 prefs
= SCPreferencesCreate(NULL
, MY_PLUGIN_ID
, NETWORK_INTERFACES_PREFS
);
353 CFSTR(MY_PLUGIN_NAME
": SCPreferencesCreate failed, %s"),
354 SCErrorString(SCError()));
358 if_list
= SCPreferencesGetValue(prefs
, INTERFACES
);
359 if (!isA_CFArray(if_list
)) {
360 if_list
= (CFArrayRef
)readPropertyList(OLD_NETWORK_INTERFACES_FILE
);
361 if (if_list
== NULL
) {
364 if (!isA_CFArray(if_list
)) {
369 writeInterfaceList(if_list
);
370 (void)unlink(OLD_NETWORK_INTERFACES_FILE
);
374 if (if_list
!= NULL
) {
376 CFIndex n
= CFArrayGetCount(if_list
);
378 plist
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
379 for (i
= 0; i
< n
; i
++) {
380 CFDictionaryRef dict
;
382 dict
= CFArrayGetValueAtIndex(if_list
, i
);
383 if (isA_CFDictionary(dict
) &&
384 CFDictionaryContainsKey(dict
, CFSTR(kIOInterfaceType
)) &&
385 CFDictionaryContainsKey(dict
, CFSTR(kIOInterfaceUnit
)) &&
386 CFDictionaryContainsKey(dict
, CFSTR(kIOMACAddress
))) {
387 CFArrayAppendValue(plist
, dict
);
397 static CFMutableArrayRef
398 previouslyActiveInterfaces()
400 CFMutableArrayRef active
;
404 if (S_dblist
== NULL
) {
408 active
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
410 n
= CFArrayGetCount(S_dblist
);
411 for (i
= 0; i
< n
; i
++) {
412 CFDictionaryRef if_dict
;
414 if_dict
= CFArrayGetValueAtIndex(S_dblist
, i
);
415 if (CFDictionaryContainsKey(if_dict
, CFSTR(kSCNetworkInterfaceActive
))) {
416 CFMutableDictionaryRef new_dict
;
418 new_dict
= CFDictionaryCreateMutableCopy(NULL
, 0, if_dict
);
419 CFDictionaryRemoveValue(new_dict
, CFSTR(kSCNetworkInterfaceActive
));
420 CFArraySetValueAtIndex(S_dblist
, i
, new_dict
);
421 CFArrayAppendValue(active
, new_dict
);
433 SCDynamicStoreRef store
;
435 store
= SCDynamicStoreCreate(NULL
, CFSTR(MY_PLUGIN_NAME
), NULL
, NULL
);
440 key
= SCDynamicStoreKeyCreate(NULL
, CFSTR("%@" MY_PLUGIN_NAME
),
441 kSCDynamicStoreDomainPlugin
);
442 (void)SCDynamicStoreSetValue(store
, key
, S_state
);
450 updateVirtualNetworkInterfaceConfiguration(SCPreferencesRef prefs
,
451 SCPreferencesNotification notificationType
,
454 CFArrayRef interfaces
;
456 if ((notificationType
& kSCPreferencesNotificationApply
) != kSCPreferencesNotificationApply
) {
461 // if a new interface has been "named"
463 if (S_bonds
!= NULL
) {
467 if (S_vlans
!= NULL
) {
473 // update Bond configuration
475 interfaces
= SCBondInterfaceCopyAll(prefs
);
476 if ((S_bonds
== NULL
) && (interfaces
== NULL
)) {
480 if ((S_bonds
!= NULL
) && (interfaces
!= NULL
) && CFEqual(S_bonds
, interfaces
)) {
482 CFRelease(interfaces
);
485 if (S_bonds
!= NULL
) CFRelease(S_bonds
);
486 S_bonds
= interfaces
;
488 if (!_SCBondInterfaceUpdateConfiguration(prefs
)) {
490 CFSTR(MY_PLUGIN_NAME
": _SCBondInterfaceUpdateConfiguration failed, %s"),
491 SCErrorString(SCError()));
496 // update VLAN configuration
498 interfaces
= SCVLANInterfaceCopyAll(prefs
);
499 if ((S_vlans
== NULL
) && (interfaces
== NULL
)) {
503 if ((S_vlans
!= NULL
) && (interfaces
!= NULL
) && CFEqual(S_vlans
, interfaces
)) {
505 CFRelease(interfaces
);
508 if (S_vlans
!= NULL
) CFRelease(S_vlans
);
509 S_vlans
= interfaces
;
511 if (!_SCVLANInterfaceUpdateConfiguration(prefs
)) {
513 CFSTR(MY_PLUGIN_NAME
": _SCVLANInterfaceUpdateConfiguration failed, %s"),
514 SCErrorString(SCError()));
519 // we are finished with current prefs, wait for changes
521 SCPreferencesSynchronize(prefs
);
525 static CFDictionaryRef
526 createInterfaceDict(SCNetworkInterfaceRef interface
)
528 CFMutableDictionaryRef new_if
;
531 new_if
= CFDictionaryCreateMutable(NULL
,
533 &kCFTypeDictionaryKeyCallBacks
,
534 &kCFTypeDictionaryValueCallBacks
);
536 val
= _SCNetworkInterfaceGetIOPath(interface
);
538 CFDictionarySetValue(new_if
, CFSTR(kIOPathMatchKey
), val
);
541 val
= _SCNetworkInterfaceGetIOInterfaceType(interface
);
543 CFDictionarySetValue(new_if
, CFSTR(kIOInterfaceType
), val
);
546 val
= _SCNetworkInterfaceGetIOInterfaceUnit(interface
);
548 CFDictionarySetValue(new_if
, CFSTR(kIOInterfaceUnit
), val
);
551 val
= _SCNetworkInterfaceGetHardwareAddress(interface
);
553 CFDictionarySetValue(new_if
, CFSTR(kIOMACAddress
), val
);
556 val
= SCNetworkInterfaceGetBSDName(interface
);
558 CFDictionarySetValue(new_if
, CFSTR(kIOBSDNameKey
), val
);
561 val
= SCNetworkInterfaceGetInterfaceType(interface
);
563 CFDictionarySetValue(new_if
, CFSTR(kSCNetworkInterfaceType
), val
);
566 CFDictionarySetValue(new_if
,
568 _SCNetworkInterfaceIsBuiltin(interface
) ? kCFBooleanTrue
: kCFBooleanFalse
);
570 CFDictionarySetValue(new_if
, CFSTR(kSCNetworkInterfaceActive
), kCFBooleanTrue
);
575 static CFDictionaryRef
576 lookupInterfaceByAddress(CFArrayRef db_list
, SCNetworkInterfaceRef interface
, CFIndex
* where
)
583 if (db_list
== NULL
) {
586 type
= _SCNetworkInterfaceGetIOInterfaceType(interface
);
587 addr
= _SCNetworkInterfaceGetHardwareAddress(interface
);
588 if (type
== NULL
|| addr
== NULL
) {
592 n
= CFArrayGetCount(db_list
);
593 for (i
= 0; i
< n
; i
++) {
595 CFDictionaryRef dict
= CFArrayGetValueAtIndex(db_list
, i
);
598 t
= CFDictionaryGetValue(dict
, CFSTR(kIOInterfaceType
));
599 a
= CFDictionaryGetValue(dict
, CFSTR(kIOMACAddress
));
600 if (t
== NULL
|| a
== NULL
)
603 if (CFEqual(type
, t
) && CFEqual(addr
, a
)) {
613 static CFDictionaryRef
614 lookupInterfaceByUnit(CFArrayRef db_list
, SCNetworkInterfaceRef interface
, CFIndex
* where
)
621 if (db_list
== NULL
) {
624 type
= _SCNetworkInterfaceGetIOInterfaceType(interface
);
625 unit
= _SCNetworkInterfaceGetIOInterfaceUnit(interface
);
626 if (type
== NULL
|| unit
== NULL
) {
630 n
= CFArrayGetCount(db_list
);
631 for (i
= 0; i
< n
; i
++) {
632 CFDictionaryRef dict
= CFArrayGetValueAtIndex(db_list
, i
);
636 t
= CFDictionaryGetValue(dict
, CFSTR(kIOInterfaceType
));
637 u
= CFDictionaryGetValue(dict
, CFSTR(kIOInterfaceUnit
));
638 if (t
== NULL
|| u
== NULL
) {
642 if (CFEqual(type
, t
) && CFEqual(unit
, u
)) {
651 static CFDictionaryRef
652 lookupAirPortInterface(CFArrayRef db_list
, CFIndex
* where
)
657 if (db_list
== NULL
) {
660 n
= CFArrayGetCount(db_list
);
661 for (i
= 0; i
< n
; i
++) {
662 CFDictionaryRef dict
;
665 dict
= CFArrayGetValueAtIndex(db_list
, i
);
666 if_type
= CFDictionaryGetValue(dict
, CFSTR(kSCNetworkInterfaceType
));
667 if ((if_type
!= NULL
) &&
668 CFEqual(if_type
, kSCNetworkInterfaceTypeIEEE80211
)) {
678 insertInterface(CFMutableArrayRef db_list
, SCNetworkInterfaceRef interface
)
681 CFDictionaryRef if_dict
;
685 CFIndex n
= CFArrayGetCount(db_list
);
686 CFComparisonResult res
;
688 if_name
= SCNetworkInterfaceGetBSDName(interface
);
689 if (if_name
!= NULL
) {
690 addTimestamp(S_state
, if_name
);
693 if_dict
= createInterfaceDict(interface
);
694 if_type
= _SCNetworkInterfaceGetIOInterfaceType(interface
);
695 if_unit
= _SCNetworkInterfaceGetIOInterfaceUnit(interface
);
696 if ((if_type
== NULL
) || (if_unit
== NULL
)) {
701 for (i
= 0; i
< n
; i
++) {
704 CFDictionaryRef dict
= CFArrayGetValueAtIndex(db_list
, i
);
706 db_type
= CFDictionaryGetValue(dict
, CFSTR(kIOInterfaceType
));
707 db_unit
= CFDictionaryGetValue(dict
, CFSTR(kIOInterfaceUnit
));
708 res
= CFNumberCompare(if_type
, db_type
, NULL
);
709 if (res
== kCFCompareLessThan
710 || (res
== kCFCompareEqualTo
711 && (CFNumberCompare(if_unit
, db_unit
, NULL
)
712 == kCFCompareLessThan
))) {
713 CFArrayInsertValueAtIndex(db_list
, i
, if_dict
);
719 CFArrayAppendValue(S_dblist
, if_dict
);
725 replaceInterface(SCNetworkInterfaceRef interface
)
729 if (S_dblist
== NULL
) {
730 S_dblist
= CFArrayCreateMutable(NULL
, 0,
731 &kCFTypeArrayCallBacks
);
733 // remove any dict that has our type/addr
734 if (lookupInterfaceByAddress(S_dblist
, interface
, &where
) != NULL
) {
735 CFArrayRemoveValueAtIndex(S_dblist
, where
);
737 // remove any dict that has the same type/unit
738 if (lookupInterfaceByUnit(S_dblist
, interface
, &where
) != NULL
) {
739 CFArrayRemoveValueAtIndex(S_dblist
, where
);
741 insertInterface(S_dblist
, interface
);
746 getHighestUnitForType(CFNumberRef if_type
)
750 CFNumberRef ret_unit
= NULL
;
752 if (S_dblist
== NULL
) {
756 n
= CFArrayGetCount(S_dblist
);
757 for (i
= 0; i
< n
; i
++) {
758 CFDictionaryRef dict
= CFArrayGetValueAtIndex(S_dblist
, i
);
761 type
= CFDictionaryGetValue(dict
, CFSTR(kIOInterfaceType
));
762 if (CFEqual(type
, if_type
)) {
765 unit
= CFDictionaryGetValue(dict
, CFSTR(kIOInterfaceUnit
));
767 || (CFNumberCompare(unit
, ret_unit
, NULL
)
768 == kCFCompareGreaterThan
)) {
778 * Function: registerInterface
780 * Register a single interface with the given service path to the
781 * data link layer (BSD), using the specified unit number.
784 registerInterface(io_connect_t connect
,
788 static const int command
= kRegisterInterface
;
789 CFMutableDictionaryRef dict
;
793 dict
= CFDictionaryCreateMutable(NULL
, 0,
794 &kCFTypeDictionaryKeyCallBacks
,
795 &kCFTypeDictionaryValueCallBacks
);
796 num
= CFNumberCreate(NULL
, kCFNumberIntType
, &command
);
797 CFDictionarySetValue(dict
, CFSTR(kIONetworkStackUserCommand
), num
);
799 CFDictionarySetValue(dict
, CFSTR(kIOPathMatchKey
), path
);
800 CFDictionarySetValue(dict
, CFSTR(kIOInterfaceUnit
), unit
);
801 kr
= IOConnectSetCFProperties(connect
, dict
);
806 static SCNetworkInterfaceRef
807 lookupIOKitPath(CFStringRef if_path
)
809 io_registry_entry_t entry
= MACH_PORT_NULL
;
810 SCNetworkInterfaceRef interface
= NULL
;
812 mach_port_t masterPort
= MACH_PORT_NULL
;
815 kr
= IOMasterPort(bootstrap_port
, &masterPort
);
816 if (kr
!= KERN_SUCCESS
) {
818 CFSTR(MY_PLUGIN_NAME
": IOMasterPort returned 0x%x\n"),
822 _SC_cfstring_to_cstring(if_path
, path
, sizeof(path
), kCFStringEncodingASCII
);
823 entry
= IORegistryEntryFromPath(masterPort
, path
);
824 if (entry
== MACH_PORT_NULL
) {
826 CFSTR(MY_PLUGIN_NAME
": IORegistryEntryFromPath(%@) failed"),
831 interface
= _SCNetworkInterfaceCreateWithIONetworkInterfaceObject(entry
);
834 if (masterPort
!= MACH_PORT_NULL
) {
835 mach_port_deallocate(mach_task_self(), masterPort
);
837 if (entry
!= MACH_PORT_NULL
) {
838 IOObjectRelease(entry
);
845 displayInterface(SCNetworkInterfaceRef interface
)
852 name
= SCNetworkInterfaceGetBSDName(interface
);
853 unit
= _SCNetworkInterfaceGetIOInterfaceUnit(interface
);
854 type
= _SCNetworkInterfaceGetIOInterfaceType(interface
);
855 addr
= SCNetworkInterfaceGetHardwareAddressString(interface
);
857 SCLog(TRUE
, LOG_INFO
,
858 CFSTR(MY_PLUGIN_NAME
": %s%@%sType: %@, %s%@%sMAC address: %@"),
859 (name
!= NULL
) ? "BSD Name: " : "",
860 (name
!= NULL
) ? name
: CFSTR(""),
861 (name
!= NULL
) ? ", " : "",
863 (unit
!= NULL
) ? "Unit: " : "",
864 (unit
!= NULL
) ? (CFTypeRef
)unit
: (CFTypeRef
)CFSTR(""),
865 (unit
!= NULL
) ? ", " : "",
870 builtinCount(CFArrayRef if_list
, CFIndex last
, CFNumberRef if_type
)
875 for (i
= 0; i
< last
; i
++) {
876 SCNetworkInterfaceRef builtin_if
;
877 CFNumberRef builtin_type
;
879 builtin_if
= CFArrayGetValueAtIndex(if_list
, i
);
880 builtin_type
= _SCNetworkInterfaceGetIOInterfaceType(builtin_if
);
881 if (CFEqual(if_type
, builtin_type
)) {
882 if (_SCNetworkInterfaceIsBuiltin(builtin_if
)) {
883 n
++; // if built-in interface
891 static __inline__ boolean_t
894 return (S_quiet
== MACH_PORT_NULL
);
898 nameInterfaces(CFMutableArrayRef if_list
)
901 CFIndex n
= CFArrayGetCount(if_list
);
903 for (i
= 0; i
< n
; i
++) {
904 SCNetworkInterfaceRef interface
;
910 interface
= CFArrayGetValueAtIndex(if_list
, i
);
911 path
= _SCNetworkInterfaceGetIOPath(interface
);
912 type
= _SCNetworkInterfaceGetIOInterfaceType(interface
);
913 unit
= _SCNetworkInterfaceGetIOInterfaceUnit(interface
);
919 if_name
= SCNetworkInterfaceGetBSDName(interface
);
920 if ((if_name
== NULL
) || !CFDictionaryContainsKey(S_state
, if_name
)) {
921 SCLog(TRUE
, LOG_INFO
,
922 CFSTR(MY_PLUGIN_NAME
": Interface already has a unit number"));
923 displayInterface(interface
);
927 // update the list of interfaces that were previously named
928 if ((S_prev_active_list
!= NULL
)
929 && lookupInterfaceByAddress(S_prev_active_list
, interface
, &where
) != NULL
) {
930 CFArrayRemoveValueAtIndex(S_prev_active_list
, where
);
933 CFDictionaryRef dbdict
;
936 dbdict
= lookupInterfaceByAddress(S_dblist
, interface
, NULL
);
937 if (dbdict
!= NULL
) {
938 unit
= CFDictionaryGetValue(dbdict
, CFSTR(kIOInterfaceUnit
));
941 SCLog(S_debug
, LOG_INFO
,
942 CFSTR(MY_PLUGIN_NAME
": Interface assigned unit %@ (from database)"),
947 if_type
= SCNetworkInterfaceGetInterfaceType(interface
);
948 if ((if_type
!= NULL
) &&
949 CFEqual(if_type
, kSCNetworkInterfaceTypeIEEE80211
)) {
950 dbdict
= lookupAirPortInterface(S_dblist
, NULL
);
951 if (dbdict
!= NULL
) {
952 unit
= CFDictionaryGetValue(dbdict
, CFSTR(kIOInterfaceUnit
));
955 SCLog(S_debug
, LOG_INFO
,
956 CFSTR(MY_PLUGIN_NAME
": Interface assigned unit %@ (updating database)"),
962 if ((dbdict
!= NULL
) && (S_prev_active_list
!= NULL
)) {
963 // update the list of interfaces that were previously named
964 where
= CFArrayGetFirstIndexOfValue(S_prev_active_list
,
965 CFRangeMake(0, CFArrayGetCount(S_prev_active_list
)),
967 if (where
!= kCFNotFound
) {
968 CFArrayRemoveValueAtIndex(S_prev_active_list
, where
);
972 if (dbdict
== NULL
) {
973 boolean_t is_builtin
;
977 // if new interface, wait until quiet before naming
978 addTimestamp(S_state
, path
);
982 is_builtin
= _SCNetworkInterfaceIsBuiltin(interface
);
985 // built-in interface, use the reserved slots
986 next_unit
= builtinCount(if_list
, i
, type
);
988 // not built-in, skip over the reserved slots
989 next_unit
= builtinCount(if_list
, n
, type
);
991 unit
= getHighestUnitForType(type
);
995 CFNumberGetValue(unit
, kCFNumberIntType
, &high_unit
);
996 if (high_unit
>= next_unit
) {
997 next_unit
= high_unit
+ 1;
1001 unit
= CFNumberCreate(NULL
, kCFNumberIntType
, &next_unit
);
1003 SCLog(S_debug
, LOG_INFO
,
1004 CFSTR(MY_PLUGIN_NAME
": Interface assigned unit %@ (%s)"),
1006 is_builtin
? "built-in" : "next available");
1009 kr
= registerInterface(S_connect
, path
, unit
);
1010 if (kr
!= KERN_SUCCESS
) {
1011 SCLog(TRUE
, LOG_ERR
,
1012 CFSTR(MY_PLUGIN_NAME
": failed to name the interface, kr=0x%x"),
1015 displayInterface(interface
);
1018 SCNetworkInterfaceRef new_interface
;
1020 new_interface
= lookupIOKitPath(path
);
1021 if (new_interface
!= NULL
) {
1022 CFNumberRef new_unit
;
1024 new_unit
= _SCNetworkInterfaceGetIOInterfaceUnit(new_interface
);
1025 if (CFEqual(unit
, new_unit
) == FALSE
) {
1026 SCLog(S_debug
, LOG_INFO
,
1027 CFSTR(MY_PLUGIN_NAME
1028 ": interface type %@ assigned "
1029 "unit %@ instead of %@"),
1030 type
, new_unit
, unit
);
1033 displayInterface(new_interface
);
1036 // update if_list (with the interface name & unit)
1037 CFArraySetValueAtIndex(if_list
, i
, new_interface
);
1038 CFRelease(new_interface
);
1039 interface
= new_interface
; // if_list holds the reference
1047 replaceInterface(interface
);
1055 if (S_connect
== MACH_PORT_NULL
) {
1056 // if we don't have the "IONetworkStack" connect object
1060 if (S_iflist
!= NULL
) {
1063 n
= CFArrayGetCount(S_iflist
);
1065 CFArraySortValues(S_iflist
, CFRangeMake(0, n
), _SCNetworkInterfaceCompare
, NULL
);
1067 nameInterfaces(S_iflist
);
1072 * The registry [matching] has quiesced so let's
1073 * - save the DB with the interfaces that have been named
1074 * - update the VLAN/BOND configuration
1075 * - tell everyone that we've finished (at least for now)
1076 * - log those interfaces which are no longer present
1077 * in the HW config (or have yet to show up).
1079 writeInterfaceList(S_dblist
);
1080 updateVirtualNetworkInterfaceConfiguration(NULL
, kSCPreferencesNotificationApply
, NULL
);
1083 if (S_iflist
!= NULL
) {
1084 CFRelease(S_iflist
);
1088 if (S_prev_active_list
!= NULL
) {
1093 n
= CFArrayGetCount(S_prev_active_list
);
1094 SCLog(TRUE
, LOG_INFO
,
1095 CFSTR(MY_PLUGIN_NAME
": Interface%s not [yet] active"),
1096 (n
> 0) ? "s" : "");
1097 for (i
= 0; i
< n
; i
++) {
1098 CFDictionaryRef if_dict
;
1103 if_dict
= CFArrayGetValueAtIndex(S_prev_active_list
, i
);
1104 name
= CFDictionaryGetValue(if_dict
, CFSTR(kIOBSDNameKey
));
1105 type
= CFDictionaryGetValue(if_dict
, CFSTR(kIOInterfaceType
));
1106 unit
= CFDictionaryGetValue(if_dict
, CFSTR(kIOInterfaceUnit
));
1107 SCLog(TRUE
, LOG_INFO
,
1108 CFSTR(MY_PLUGIN_NAME
": %s%@%sType: %@, Unit: %@"),
1109 (name
!= NULL
) ? "BSD Name: " : "",
1110 (name
!= NULL
) ? name
: CFSTR(""),
1111 (name
!= NULL
) ? ", " : "",
1116 CFRelease(S_prev_active_list
);
1117 S_prev_active_list
= NULL
;
1120 if ((S_prev_active_list
!= NULL
) && (CFArrayGetCount(S_prev_active_list
) == 0)) {
1122 * if we've named all of the interfaces that
1123 * were used during the previous boot.
1125 addTimestamp(S_state
, CFSTR("*RELEASE*"));
1126 SCLog(S_debug
, LOG_INFO
,
1127 CFSTR(MY_PLUGIN_NAME
": last boot interfaces have been named"));
1129 CFRelease(S_prev_active_list
);
1130 S_prev_active_list
= NULL
;
1137 static CFComparisonResult
1138 compareMacAddress(const void *val1
, const void *val2
, void *context
)
1140 CFDataRef mac1
= (CFDataRef
)val1
;
1141 CFDataRef mac2
= (CFDataRef
)val2
;
1144 CFComparisonResult res
;
1146 n1
= CFDataGetLength(mac1
);
1147 n2
= CFDataGetLength(mac2
);
1149 res
= kCFCompareLessThan
;
1150 } else if (n2
> n1
) {
1151 res
= kCFCompareGreaterThan
;
1153 res
= bcmp(CFDataGetBytePtr(mac1
), CFDataGetBytePtr(mac2
), n1
);
1160 updatePlatformUUID()
1163 CFMutableArrayRef addrs
= NULL
;
1167 io_registry_entry_t platform
;
1169 platform
= IORegistryEntryFromPath(kIOMasterPortDefault
, kIODeviceTreePlane
":/");
1170 if (platform
== MACH_PORT_NULL
) {
1174 guid
= IORegistryEntryCreateCFProperty(platform
, CFSTR(kIOPlatformUUIDKey
), NULL
, 0);
1176 // if GUID already defined
1180 addrs
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1181 n
= (S_dblist
!= NULL
) ? CFArrayGetCount(S_dblist
) : 0;
1182 for (i
= 0; i
< n
; i
++) {
1183 CFBooleanRef builtin
;
1184 CFDictionaryRef dict
;
1187 dict
= CFArrayGetValueAtIndex(S_dblist
, i
);
1188 type
= CFDictionaryGetValue(dict
, CFSTR(kSCNetworkInterfaceType
));
1189 if (!isA_CFString(type
) || !CFEqual(type
, kSCNetworkInterfaceTypeEthernet
)) {
1192 builtin
= CFDictionaryGetValue(dict
, CFSTR(kIOBuiltin
));
1193 if (!isA_CFBoolean(builtin
) || !CFBooleanGetValue(builtin
)) {
1196 addr
= CFDictionaryGetValue(dict
, CFSTR(kIOMACAddress
));
1197 if (!isA_CFData(addr
) || (CFDataGetLength(addr
) != ETHER_ADDR_LEN
)) {
1200 CFArrayAppendValue(addrs
, addr
);
1203 if (CFArrayGetCount(addrs
) == 0) {
1204 // if no ethernet interfaces, look for wireless
1205 for (i
= 0; i
< n
; i
++) {
1206 CFDictionaryRef dict
;
1209 dict
= CFArrayGetValueAtIndex(S_dblist
, i
);
1210 type
= CFDictionaryGetValue(dict
, CFSTR(kSCNetworkInterfaceType
));
1211 if (!isA_CFString(type
) || !CFEqual(type
, kSCNetworkInterfaceTypeIEEE80211
)) {
1214 addr
= CFDictionaryGetValue(dict
, CFSTR(kIOMACAddress
));
1215 if (!isA_CFData(addr
) || (CFDataGetLength(addr
) != ETHER_ADDR_LEN
)) {
1218 CFArrayAppendValue(addrs
, addr
);
1222 n
= CFArrayGetCount(addrs
);
1225 SCLog(TRUE
, LOG_ERR
,
1226 CFSTR(MY_PLUGIN_NAME
": no network interfaces, could not update platform UUID"));
1229 // sort by MAC address
1230 CFArraySortValues(addrs
, CFRangeMake(0, n
), compareMacAddress
, NULL
);
1234 CFUUIDBytes bytes
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
1235 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1240 addr
= CFArrayGetValueAtIndex(addrs
, 0);
1241 bcopy(CFDataGetBytePtr(addr
),
1242 (void *)&bytes
+ sizeof(bytes
) - ETHER_ADDR_LEN
,
1244 uuid
= CFUUIDCreateFromUUIDBytes(NULL
, bytes
);
1245 guid
= CFUUIDCreateString(NULL
, uuid
);
1248 SCLog(TRUE
, LOG_INFO
,
1249 CFSTR(MY_PLUGIN_NAME
": setting platform UUID = %@"),
1251 kr
= IORegistryEntrySetCFProperty(platform
, CFSTR(kIOPlatformUUIDKey
), guid
);
1252 if (kr
!= KERN_SUCCESS
) {
1253 SCLog(TRUE
, LOG_ERR
,
1254 CFSTR(MY_PLUGIN_NAME
": IORegistryEntrySetCFProperty(platform UUID) failed, kr=0x%x"),
1258 addTimestamp(S_state
, CFSTR("*PLATFORM-UUID*"));
1266 if (addrs
!= NULL
) CFRelease(addrs
);
1267 if (platform
!= MACH_PORT_NULL
) IOObjectRelease(platform
);
1268 if (guid
!= NULL
) CFRelease(guid
);
1273 interfaceArrivalCallback(void *refcon
, io_iterator_t iter
)
1277 while ((obj
= IOIteratorNext(iter
)) != MACH_PORT_NULL
) {
1278 SCNetworkInterfaceRef interface
;
1280 interface
= _SCNetworkInterfaceCreateWithIONetworkInterfaceObject(obj
);
1281 if (interface
!= NULL
) {
1282 if (S_iflist
== NULL
) {
1283 S_iflist
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1285 CFArrayAppendValue(S_iflist
, interface
);
1286 CFRelease(interface
);
1288 IOObjectRelease(obj
);
1296 * Function: stackCallback
1298 * Get a reference to the single IONetworkStack object instance in
1299 * the kernel. Naming requests must be sent to this object, which is
1300 * attached as a client to all network interface objects in the system.
1302 * Call IOObjectRelease on the returned object.
1305 stackCallback(void *refcon
, io_iterator_t iter
)
1310 stack
= IOIteratorNext(iter
);
1311 if (stack
== MACH_PORT_NULL
) {
1315 kr
= IOServiceOpen(stack
, mach_task_self(), 0, &S_connect
);
1316 if (kr
!= KERN_SUCCESS
) {
1317 SCLog(TRUE
, LOG_ERR
,
1318 CFSTR(MY_PLUGIN_NAME
": IOServiceOpen returned 0x%x"),
1323 addTimestamp(S_state
, CFSTR("*STACK*"));
1324 SCLog(S_debug
, LOG_INFO
,
1325 CFSTR(MY_PLUGIN_NAME
": IONetworkStack found"));
1327 if (S_stack
!= MACH_PORT_NULL
) {
1328 IOObjectRelease(S_stack
);
1329 S_stack
= MACH_PORT_NULL
;
1335 if (stack
!= MACH_PORT_NULL
) {
1336 IOObjectRelease(stack
);
1343 quietCallback(void *refcon
,
1344 io_service_t service
,
1345 natural_t messageType
,
1346 void *messageArgument
)
1348 if (messageArgument
!= NULL
) {
1353 if (messageType
== kIOMessageServiceBusyStateChange
) {
1354 addTimestamp(S_state
, CFSTR("*QUIET*"));
1355 SCLog(S_debug
, LOG_INFO
,
1356 CFSTR(MY_PLUGIN_NAME
": IOKit quiet"));
1359 if (S_connect
== MACH_PORT_NULL
) {
1360 SCLog(TRUE
, LOG_ERR
,
1361 CFSTR(MY_PLUGIN_NAME
": No network stack object"));
1365 if (S_quiet
!= MACH_PORT_NULL
) {
1366 IOObjectRelease(S_quiet
);
1367 S_quiet
= MACH_PORT_NULL
;
1370 if (S_timer
!= NULL
) {
1371 CFRunLoopTimerInvalidate(S_timer
);
1376 // grab (and name) any additional interfaces.
1377 interfaceArrivalCallback((void *)S_notify
, S_iter
);
1379 updatePlatformUUID();
1385 iterateRegistryBusy(io_iterator_t iterator
, CFArrayRef nodes
, int *count
)
1387 kern_return_t kr
= kIOReturnSuccess
;;
1390 while ((kr
== kIOReturnSuccess
) &&
1391 ((obj
= IOIteratorNext(iterator
)) != MACH_PORT_NULL
)) {
1395 CFMutableArrayRef newNodes
;
1396 CFMutableStringRef str
= NULL
;
1398 if (nodes
== NULL
) {
1399 newNodes
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1401 newNodes
= CFArrayCreateMutableCopy(NULL
, 0, nodes
);
1404 kr
= IORegistryEntryGetName(obj
, name
);
1405 if (kr
!= kIOReturnSuccess
) {
1406 SCLog(TRUE
, LOG_ERR
,
1407 CFSTR(MY_PLUGIN_NAME
": reportBusy IORegistryEntryGetName returned 0x%x"),
1412 str
= CFStringCreateMutable(NULL
, 0);
1413 CFStringAppendCString(str
, name
, kCFStringEncodingUTF8
);
1415 kr
= IORegistryEntryGetLocationInPlane(obj
, kIOServicePlane
, location
);
1417 case kIOReturnSuccess
:
1418 CFStringAppendCString(str
, "@", kCFStringEncodingUTF8
);
1419 CFStringAppendCString(str
, location
, kCFStringEncodingUTF8
);
1421 case kIOReturnNotFound
:
1424 SCLog(TRUE
, LOG_ERR
,
1425 CFSTR(MY_PLUGIN_NAME
": reportBusy IORegistryEntryGetLocationInPlane returned 0x%x"),
1431 CFArrayAppendValue(newNodes
, str
);
1434 kr
= IOServiceGetBusyState(obj
, &busy
);
1435 if (kr
!= kIOReturnSuccess
) {
1436 SCLog(TRUE
, LOG_ERR
,
1437 CFSTR(MY_PLUGIN_NAME
": reportBusy IOServiceGetBusyState returned 0x%x"),
1445 if ((*count
)++ == 0) {
1446 SCLog(TRUE
, LOG_WARNING
, CFSTR(MY_PLUGIN_NAME
": Busy services :"));
1449 path
= CFStringCreateByCombiningStrings(NULL
, newNodes
, CFSTR("/"));
1450 SCLog(TRUE
, LOG_WARNING
, CFSTR(MY_PLUGIN_NAME
": %@ [%d]"), path
, busy
);
1454 kr
= IORegistryIteratorEnterEntry(iterator
);
1455 if (kr
!= kIOReturnSuccess
) {
1456 SCLog(TRUE
, LOG_ERR
,
1457 CFSTR(MY_PLUGIN_NAME
": reportBusy IORegistryIteratorEnterEntry returned 0x%x"),
1462 iterateRegistryBusy(iterator
, newNodes
, count
);
1464 kr
= IORegistryIteratorExitEntry(iterator
);
1465 if (kr
!= kIOReturnSuccess
) {
1466 SCLog(TRUE
, LOG_ERR
,
1467 CFSTR(MY_PLUGIN_NAME
": reportBusy IORegistryIteratorExitEntry returned 0x%x"),
1473 CFRelease(newNodes
);
1474 IOObjectRelease(obj
);
1484 io_iterator_t iterator
= MACH_PORT_NULL
;
1487 kr
= IORegistryCreateIterator(kIOMasterPortDefault
,
1491 if (kr
!= kIOReturnSuccess
) {
1492 SCLog(TRUE
, LOG_ERR
,
1493 CFSTR(MY_PLUGIN_NAME
": reportBusy IORegistryCreateIterator returned 0x%x"),
1498 iterateRegistryBusy(iterator
, NULL
, &count
);
1499 SCLog((count
== 0), LOG_WARNING
,
1500 CFSTR(MY_PLUGIN_NAME
": w/no busy services"));
1501 IOObjectRelease(iterator
);
1506 timerCallback(CFRunLoopTimerRef timer
, void *info
)
1509 * We've been waiting for IOKit to quiesce and it just
1510 * hasn't happenned. Time to just move on!
1512 addTimestamp(S_state
, CFSTR("*TIMEOUT*"));
1513 SCLog(TRUE
, LOG_ERR
,
1514 CFSTR(MY_PLUGIN_NAME
": timed out waiting for IOKit to quiesce"));
1517 quietCallback((void *)S_notify
, MACH_PORT_NULL
, 0, NULL
);
1522 setup_IOKit(CFBundleRef bundle
)
1525 CFDictionaryRef dict
;
1527 mach_port_t masterPort
= MACH_PORT_NULL
;
1529 io_object_t root
= MACH_PORT_NULL
;
1530 double timeout
= WAIT_QUIET_TIMEOUT_DEFAULT
;
1532 // read DB of previously named network interfaces
1533 S_dblist
= readInterfaceList();
1534 if (S_dblist
!= NULL
) {
1537 n
= CFArrayGetCount(S_dblist
);
1539 CFArraySortValues(S_dblist
, CFRangeMake(0, n
), if_unit_compare
, NULL
);
1543 // get interfaces that were named during the last boot
1544 S_prev_active_list
= previouslyActiveInterfaces();
1546 // track how long we've waited to see each interface.
1547 S_state
= CFDictionaryCreateMutable(NULL
,
1549 &kCFTypeDictionaryKeyCallBacks
,
1550 &kCFTypeDictionaryValueCallBacks
);
1551 addTimestamp(S_state
, CFSTR("*START*"));
1553 // Creates and returns a notification object for receiving IOKit
1554 // notifications of new devices or state changes.
1555 kr
= IOMasterPort(bootstrap_port
, &masterPort
);
1556 if (kr
!= KERN_SUCCESS
) {
1557 SCLog(TRUE
, LOG_ERR
,
1558 CFSTR(MY_PLUGIN_NAME
": IOMasterPort returned 0x%x"),
1563 S_notify
= IONotificationPortCreate(masterPort
);
1564 if (S_notify
== NULL
) {
1565 SCLog(TRUE
, LOG_ERR
,
1566 CFSTR(MY_PLUGIN_NAME
": IONotificationPortCreate failed"));
1570 // watch IOKit matching activity
1571 root
= IORegistryEntryFromPath(masterPort
, kIOServicePlane
":/");
1572 if (root
== MACH_PORT_NULL
) {
1573 SCLog(TRUE
, LOG_ERR
,
1574 CFSTR(MY_PLUGIN_NAME
": IORegistryEntryFromPath failed"));
1578 kr
= IOServiceAddInterestNotification(S_notify
,
1582 (void *)S_notify
, // refCon
1583 &S_quiet
); // notification
1584 if (kr
!= KERN_SUCCESS
) {
1585 SCLog(TRUE
, LOG_ERR
,
1586 CFSTR(MY_PLUGIN_NAME
": IOServiceAddInterestNotification returned 0x%x"),
1591 kr
= IOServiceGetBusyState(root
, &busy
);
1592 if (kr
!= KERN_SUCCESS
) {
1593 SCLog(TRUE
, LOG_ERR
,
1594 CFSTR(MY_PLUGIN_NAME
": IOServiceGetBusyState returned 0x%x"),
1599 // add a timer so we don't wait forever for IOKit to quiesce
1600 dict
= CFBundleGetInfoDictionary(bundle
);
1601 if (isA_CFDictionary(dict
)) {
1604 num
= CFDictionaryGetValue(dict
, CFSTR(WAIT_QUIET_TIMEOUT_KEY
));
1606 if (!isA_CFNumber(num
) ||
1607 !CFNumberGetValue(num
, kCFNumberDoubleType
, &timeout
) ||
1609 SCLog(TRUE
, LOG_ERR
,
1610 CFSTR(MY_PLUGIN_NAME
": " WAIT_QUIET_TIMEOUT_KEY
" value error"));
1611 timeout
= WAIT_QUIET_TIMEOUT_DEFAULT
;
1615 S_timer
= CFRunLoopTimerCreate(NULL
,
1616 CFAbsoluteTimeGetCurrent() + timeout
,
1622 if (S_timer
== NULL
) {
1623 SCLog(TRUE
, LOG_ERR
,
1624 CFSTR(MY_PLUGIN_NAME
": CFRunLoopTimerCreate failed"));
1628 CFRunLoopAddTimer(CFRunLoopGetCurrent(), S_timer
, kCFRunLoopDefaultMode
);
1630 // watch for the introduction of the IONetworkStack
1631 kr
= IOServiceAddMatchingNotification(S_notify
,
1632 kIOFirstMatchNotification
,
1633 IOServiceMatching("IONetworkStack"),
1635 (void *)S_notify
, // refCon
1636 &S_stack
); // notification
1637 if (kr
!= KERN_SUCCESS
) {
1638 SCLog(TRUE
, LOG_ERR
,
1639 CFSTR(MY_PLUGIN_NAME
": IOServiceAddMatchingNotification returned 0x%x"),
1644 // check and see if the stack is already available and arm the
1645 // notification for its introduction.
1646 stackCallback((void *)S_notify
, S_stack
);
1648 // watch for the introduction of new network interfaces
1649 kr
= IOServiceAddMatchingNotification(S_notify
,
1650 kIOFirstMatchNotification
,
1651 IOServiceMatching("IONetworkInterface"),
1652 &interfaceArrivalCallback
,
1653 (void *)S_notify
, // refCon
1654 &S_iter
); // notification
1655 if (kr
!= KERN_SUCCESS
) {
1656 SCLog(TRUE
, LOG_ERR
,
1657 CFSTR(MY_PLUGIN_NAME
": IOServiceAddMatchingNotification returned 0x%x"),
1662 // Get the current list of matches and arm the notification for
1663 // future interface arrivals.
1664 interfaceArrivalCallback((void *)S_notify
, S_iter
);
1666 // Check if IOKit has already quiesced.
1667 quietCallback((void *)S_notify
,
1669 kIOMessageServiceBusyStateChange
,
1672 CFRunLoopAddSource(CFRunLoopGetCurrent(),
1673 IONotificationPortGetRunLoopSource(S_notify
),
1674 kCFRunLoopDefaultMode
);
1676 #ifdef WAIT_PREVIOUS_BOOT_INTERFACES_OR_QUIET
1678 * Start the wheels turning until we've named all of
1679 * the interfaces that were used during the previous
1680 * boot, until IOKit [matching] has quiesced, or
1681 * until we've waited long enough.
1683 CFRunLoopAddTimer(CFRunLoopGetCurrent(), S_timer
, MY_PLUGIN_ID
);
1684 CFRunLoopAddSource(CFRunLoopGetCurrent(),
1685 IONotificationPortGetRunLoopSource(S_notify
),
1687 while (S_prev_active_list
!= NULL
) {
1690 rlStatus
= CFRunLoopRunInMode(MY_PLUGIN_ID
, 1.0e10
, TRUE
);
1692 #endif /* WAIT_PREVIOUS_BOOT_INTERFACES_OR_QUIET */
1697 if (root
!= MACH_PORT_NULL
) {
1698 IOObjectRelease(root
);
1700 if (masterPort
!= MACH_PORT_NULL
) {
1701 mach_port_deallocate(mach_task_self(), masterPort
);
1708 setup_Virtual(CFBundleRef bundle
)
1710 // open a SCPreferences session
1711 S_prefs
= SCPreferencesCreate(NULL
, CFSTR(MY_PLUGIN_NAME
), NULL
);
1712 if (S_prefs
== NULL
) {
1713 SCLog(TRUE
, LOG_ERR
,
1714 CFSTR(MY_PLUGIN_NAME
": SCPreferencesCreate() failed: %s"),
1715 SCErrorString(SCError()));
1719 // register for change notifications.
1720 if (!SCPreferencesSetCallback(S_prefs
, updateVirtualNetworkInterfaceConfiguration
, NULL
)) {
1721 SCLog(TRUE
, LOG_ERR
,
1722 CFSTR(MY_PLUGIN_NAME
": SCPreferencesSetCallBack() failed: %s"),
1723 SCErrorString(SCError()));
1729 if (!SCPreferencesScheduleWithRunLoop(S_prefs
, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode
)) {
1730 SCLog(TRUE
, LOG_ERR
,
1731 CFSTR(MY_PLUGIN_NAME
": SCPreferencesScheduleWithRunLoop() failed: %s"),
1732 SCErrorString(SCError()));
1742 load_InterfaceNamer(CFBundleRef bundle
, Boolean bundleVerbose
)
1744 if (bundleVerbose
) {
1748 // setup virtual network interface monitoring
1749 if (!setup_Virtual(bundle
)) {
1753 // setup [IOKit] network interface monitoring
1754 if (!setup_IOKit(bundle
)) {
1761 if (S_connect
!= MACH_PORT_NULL
) {
1762 IOServiceClose(S_connect
);
1763 S_connect
= MACH_PORT_NULL
;
1765 if (S_dblist
!= NULL
) {
1766 CFRelease(S_dblist
);
1769 if (S_iter
!= MACH_PORT_NULL
) {
1770 IOObjectRelease(S_iter
);
1771 S_iter
= MACH_PORT_NULL
;
1773 if (S_notify
!= MACH_PORT_NULL
) {
1774 IONotificationPortDestroy(S_notify
);
1776 if (S_quiet
!= MACH_PORT_NULL
) {
1777 IOObjectRelease(S_quiet
);
1778 S_quiet
= MACH_PORT_NULL
;
1780 if (S_stack
!= MACH_PORT_NULL
) {
1781 IOObjectRelease(S_stack
);
1782 S_stack
= MACH_PORT_NULL
;
1784 if (S_state
!= NULL
) {
1788 if (S_timer
!= NULL
) {
1789 CFRunLoopTimerInvalidate(S_timer
);
1797 //------------------------------------------------------------------------
1801 main(int argc
, char ** argv
)
1804 _sc_verbose
= (argc
> 1) ? TRUE
: FALSE
;
1806 load_InterfaceNamer(CFBundleGetMainBundle(), (argc
> 1) ? TRUE
: FALSE
);
1814 #ifdef TEST_PLATFORM_UUID
1816 main(int argc
, char ** argv
)
1818 CFArrayRef interfaces
;
1821 _sc_verbose
= (argc
> 1) ? TRUE
: FALSE
;
1823 S_dblist
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1824 interfaces
= SCNetworkInterfaceCopyAll();
1825 if (interfaces
!= NULL
) {
1829 n
= CFArrayGetCount(interfaces
);
1830 for (i
= 0; i
< n
; i
++) {
1831 CFDictionaryRef dict
;
1832 SCNetworkInterfaceRef interface
;
1834 interface
= CFArrayGetValueAtIndex(interfaces
, i
);
1835 dict
= createInterfaceDict(interface
);
1836 CFArrayAppendValue(S_dblist
, dict
);
1839 CFRelease(interfaces
);
1841 updatePlatformUUID();
1842 CFRelease(S_dblist
);
1846 #endif /* TEST_PLATFORM_UUID */