2 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 * Modification History
27 * July 22, 2004 Allan Nathanson <ajn@apple.com>
32 #include <CoreFoundation/CoreFoundation.h>
33 #include <CoreFoundation/CFRuntime.h>
35 #include <SystemConfiguration/SystemConfiguration.h>
36 #include <SystemConfiguration/SCNetworkConfigurationInternal.h>
37 #include <SystemConfiguration/SCValidation.h>
38 #include <SystemConfiguration/SCPrivate.h>
40 #include <SystemConfiguration/BondConfiguration.h>
41 #include <SystemConfiguration/BondConfigurationPrivate.h>
46 #include <sys/types.h>
47 #include <sys/ioctl.h>
48 #include <sys/socket.h>
49 #include <sys/sysctl.h>
50 #include <net/ethernet.h>
51 #define KERNEL_PRIVATE
53 #include <net/if_var.h>
55 #include <net/if_bond_var.h>
56 #include <net/if_types.h>
57 #include <net/if_media.h>
58 #include <net/route.h>
60 /* ---------- Bond support ---------- */
67 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
69 SCLog(TRUE
, LOG_ERR
, CFSTR("socket() failed: %s"), strerror(errno
));
70 _SCErrorSet(kSCStatusFailed
);
77 siocgifmedia(int s
, const char * ifname
, int * status
, int * active
)
79 struct ifmediareq ifmr
;
83 bzero(&ifmr
, sizeof(ifmr
));
84 strncpy(ifmr
.ifm_name
, ifname
, sizeof(ifmr
.ifm_name
));
85 if (ioctl(s
, SIOCGIFMEDIA
, &ifmr
) < 0) {
86 SCLog(TRUE
, LOG_ERR
, CFSTR("SIOCGIFMEDIA(%s) failed, %s\n"),
87 ifname
, strerror(errno
));
90 if (ifmr
.ifm_count
!= 0) {
91 *status
= ifmr
.ifm_status
;
92 *active
= ifmr
.ifm_active
;
97 static struct if_bond_status_req
*
98 if_bond_status_req_copy(int s
, const char * ifname
)
101 struct if_bond_req ibr
;
102 struct if_bond_status_req
* ibsr_p
;
105 bzero(&ifr
, sizeof(ifr
));
106 strncpy(ifr
.ifr_name
, ifname
, sizeof(ifr
.ifr_name
));
107 bzero((char *)&ibr
, sizeof(ibr
));
108 ibr
.ibr_op
= IF_BOND_OP_GET_STATUS
;
109 ibsr_p
= &ibr
.ibr_ibru
.ibru_status
;
110 ibsr_p
->ibsr_version
= IF_BOND_STATUS_REQ_VERSION
;
111 ifr
.ifr_data
= (caddr_t
)&ibr
;
113 /* how many of them are there? */
114 if (ioctl(s
, SIOCGIFBOND
, (caddr_t
)&ifr
) < 0) {
115 SCLog(TRUE
, LOG_ERR
, CFSTR("SIOCGIFBOND(%s) failed: %s"),
116 ifname
, strerror(errno
));
119 buf
= malloc(sizeof(struct if_bond_status
) * ibsr_p
->ibsr_total
+ sizeof(*ibsr_p
));
123 if (ibsr_p
->ibsr_total
== 0) {
126 ibsr_p
->ibsr_count
= ibsr_p
->ibsr_total
;
127 ibsr_p
->ibsr_buffer
= buf
+ sizeof(*ibsr_p
);
130 if (ioctl(s
, SIOCGIFBOND
, (caddr_t
)&ifr
) < 0) {
131 SCLog(TRUE
, LOG_ERR
, CFSTR("SIOCGIFBOND(%s) failed: %s"),
132 ifname
, strerror(errno
));
136 (*(struct if_bond_status_req
*)buf
) = *ibsr_p
;
137 return ((struct if_bond_status_req
*)buf
);
147 _Bond_addDevice(int s
, CFStringRef interface
, CFStringRef device
)
149 struct if_bond_req breq
;
153 bzero(&ifr
, sizeof(ifr
));
154 (void) _SC_cfstring_to_cstring(interface
,
156 sizeof(ifr
.ifr_name
),
157 kCFStringEncodingASCII
);
158 ifr
.ifr_data
= (caddr_t
)&breq
;
161 bzero(&breq
, sizeof(breq
));
162 breq
.ibr_op
= IF_BOND_OP_ADD_INTERFACE
;
163 (void) _SC_cfstring_to_cstring(device
,
164 breq
.ibr_ibru
.ibru_if_name
,
165 sizeof(breq
.ibr_ibru
.ibru_if_name
),
166 kCFStringEncodingASCII
);
168 // add new bond member
169 if (ioctl(s
, SIOCSIFBOND
, (caddr_t
)&ifr
) == -1) {
171 CFSTR("could not add interface \"%@\" to bond \"%@\": %s"),
175 _SCErrorSet(kSCStatusFailed
);
179 // mark the added interface "up"
180 if (!__markInterfaceUp(s
, device
)) {
181 _SCErrorSet(kSCStatusFailed
);
190 _Bond_removeDevice(int s
, CFStringRef interface
, CFStringRef device
)
192 struct if_bond_req breq
;
196 bzero(&ifr
, sizeof(ifr
));
197 (void) _SC_cfstring_to_cstring(interface
,
199 sizeof(ifr
.ifr_name
),
200 kCFStringEncodingASCII
);
201 ifr
.ifr_data
= (caddr_t
)&breq
;
203 // bond member to remove
204 bzero(&breq
, sizeof(breq
));
205 breq
.ibr_op
= IF_BOND_OP_REMOVE_INTERFACE
;
206 (void) _SC_cfstring_to_cstring(device
,
207 breq
.ibr_ibru
.ibru_if_name
,
208 sizeof(breq
.ibr_ibru
.ibru_if_name
),
209 kCFStringEncodingASCII
);
211 // remove bond member
212 if (ioctl(s
, SIOCSIFBOND
, (caddr_t
)&ifr
) == -1) {
214 CFSTR("could not remove interface \"%@\" from bond \"%@\": %s"),
218 _SCErrorSet(kSCStatusFailed
);
226 /* ---------- Bond "device" ---------- */
229 IsBondSupported(CFStringRef device
)
231 CFMutableDictionaryRef entity
;
232 SCNetworkInterfaceRef interface
;
233 Boolean isBond
= FALSE
;
235 entity
= CFDictionaryCreateMutable(NULL
,
237 &kCFTypeDictionaryKeyCallBacks
,
238 &kCFTypeDictionaryValueCallBacks
);
239 CFDictionarySetValue(entity
, kSCPropNetInterfaceType
, kSCValNetInterfaceTypeEthernet
);
240 CFDictionarySetValue(entity
, kSCPropNetInterfaceDeviceName
, device
);
241 interface
= __SCNetworkInterfaceCreateWithEntity(NULL
, entity
, NULL
);
244 if (interface
!= NULL
) {
245 SCNetworkInterfacePrivateRef interfacePrivate
;
247 interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
248 if (interfacePrivate
->path
!= NULL
) {
249 isBond
= interfacePrivate
->supportsBond
;
251 CFRelease(interface
);
257 /* ---------- BondInterface ---------- */
261 /* base CFType information */
262 CFRuntimeBase cfBase
;
264 /* bond interface configuration */
265 CFStringRef ifname
; // e.g. bond0, bond1, ...
266 CFArrayRef devices
; // e.g. en0, en1, ...
267 CFDictionaryRef options
; // e.g. UserDefinedName
269 } BondInterfacePrivate
, * BondInterfacePrivateRef
;
272 static CFStringRef
__BondInterfaceCopyDescription (CFTypeRef cf
);
273 static void __BondInterfaceDeallocate (CFTypeRef cf
);
274 static Boolean
__BondInterfaceEqual (CFTypeRef cf1
, CFTypeRef cf2
);
277 static const CFRuntimeClass __BondInterfaceClass
= {
279 "BondInterface", // className
282 __BondInterfaceDeallocate
, // dealloc
283 __BondInterfaceEqual
, // equal
285 NULL
, // copyFormattingDesc
286 __BondInterfaceCopyDescription
// copyDebugDesc
290 static CFTypeID __kBondInterfaceTypeID
= _kCFRuntimeNotATypeID
;
293 static pthread_once_t bondInterface_init
= PTHREAD_ONCE_INIT
;
297 __BondInterfaceCopyDescription(CFTypeRef cf
)
299 CFAllocatorRef allocator
= CFGetAllocator(cf
);
300 CFMutableStringRef result
;
301 BondInterfacePrivateRef bondPrivate
= (BondInterfacePrivateRef
)cf
;
303 result
= CFStringCreateMutable(allocator
, 0);
304 CFStringAppendFormat(result
, NULL
, CFSTR("<BondInterface %p [%p]> {"), cf
, allocator
);
305 CFStringAppendFormat(result
, NULL
, CFSTR(" if = %@"), bondPrivate
->ifname
);
306 if (bondPrivate
->devices
!= NULL
) {
310 CFStringAppendFormat(result
, NULL
, CFSTR(", devices ="));
312 n
= CFArrayGetCount(bondPrivate
->devices
);
313 for (i
= 0; i
< n
; i
++) {
314 CFStringAppendFormat(result
,
317 CFArrayGetValueAtIndex(bondPrivate
->devices
, i
));
320 if (bondPrivate
->options
!= NULL
) {
321 CFStringAppendFormat(result
, NULL
, CFSTR(", options = %@"), bondPrivate
->options
);
323 CFStringAppendFormat(result
, NULL
, CFSTR(" }"));
330 __BondInterfaceDeallocate(CFTypeRef cf
)
332 BondInterfacePrivateRef bondPrivate
= (BondInterfacePrivateRef
)cf
;
334 /* release resources */
336 CFRelease(bondPrivate
->ifname
);
337 if (bondPrivate
->devices
) CFRelease(bondPrivate
->devices
);
338 if (bondPrivate
->options
) CFRelease(bondPrivate
->options
);
345 __BondInterfaceEquiv(CFTypeRef cf1
, CFTypeRef cf2
)
347 BondInterfacePrivateRef bond1
= (BondInterfacePrivateRef
)cf1
;
348 BondInterfacePrivateRef bond2
= (BondInterfacePrivateRef
)cf2
;
353 if (!CFEqual(bond1
->ifname
, bond2
->ifname
))
354 return FALSE
; // if not the same interface
356 if (!CFEqual(bond1
->devices
, bond2
->devices
))
357 return FALSE
; // if not the same device
364 __BondInterfaceEqual(CFTypeRef cf1
, CFTypeRef cf2
)
366 BondInterfacePrivateRef bond1
= (BondInterfacePrivateRef
)cf1
;
367 BondInterfacePrivateRef bond2
= (BondInterfacePrivateRef
)cf2
;
369 if (!__BondInterfaceEquiv(bond1
, bond2
))
370 return FALSE
; // if not the same Bond interface/devices
372 if (bond1
->options
!= bond2
->options
) {
373 // if the options may differ
374 if ((bond1
->options
!= NULL
) && (bond2
->options
!= NULL
)) {
375 // if both Bonds have options
376 if (!CFEqual(bond1
->options
, bond2
->options
)) {
377 // if the options are not equal
381 // if only one Bond has options
391 __BondInterfaceInitialize(void)
393 __kBondInterfaceTypeID
= _CFRuntimeRegisterClass(&__BondInterfaceClass
);
398 static __inline__ CFTypeRef
399 isA_BondInterface(CFTypeRef obj
)
401 return (isA_CFType(obj
, BondInterfaceGetTypeID()));
406 BondInterfaceGetTypeID(void)
408 pthread_once(&bondInterface_init
, __BondInterfaceInitialize
); /* initialize runtime */
409 return __kBondInterfaceTypeID
;
413 static BondInterfaceRef
414 __BondInterfaceCreatePrivate(CFAllocatorRef allocator
,
417 BondInterfacePrivateRef bondPrivate
;
420 /* initialize runtime */
421 pthread_once(&bondInterface_init
, __BondInterfaceInitialize
);
424 size
= sizeof(BondInterfacePrivate
) - sizeof(CFRuntimeBase
);
425 bondPrivate
= (BondInterfacePrivateRef
)_CFRuntimeCreateInstance(allocator
,
426 __kBondInterfaceTypeID
,
429 if (bondPrivate
== NULL
) {
433 /* establish the bond */
435 bondPrivate
->ifname
= CFStringCreateCopy(allocator
, ifname
);
436 bondPrivate
->devices
= NULL
;
437 bondPrivate
->options
= NULL
;
439 return (BondInterfaceRef
)bondPrivate
;
444 BondInterfaceGetInterface(BondInterfaceRef bond
)
446 BondInterfacePrivateRef bondPrivate
= (BondInterfacePrivateRef
)bond
;
447 CFStringRef bond_if
= NULL
;
449 if (isA_BondInterface(bond
)) {
450 bond_if
= bondPrivate
->ifname
;
458 BondInterfaceGetDevices(BondInterfaceRef bond
)
460 BondInterfacePrivateRef bondPrivate
= (BondInterfacePrivateRef
)bond
;
461 CFArrayRef bond_devices
= NULL
;
463 if (isA_BondInterface(bond
)) {
464 bond_devices
= bondPrivate
->devices
;
472 BondInterfaceGetOptions(BondInterfaceRef bond
)
474 BondInterfacePrivateRef bondPrivate
= (BondInterfacePrivateRef
)bond
;
475 CFDictionaryRef bond_options
= NULL
;
477 if (isA_BondInterface(bond
)) {
478 bond_options
= bondPrivate
->options
;
486 BondInterfaceSetDevices(BondInterfaceRef bond
, CFArrayRef newDevices
)
488 BondInterfacePrivateRef bondPrivate
= (BondInterfacePrivateRef
)bond
;
490 if (isA_BondInterface(bond
)) {
491 CFAllocatorRef allocator
= CFGetAllocator(bond
);
493 if (bondPrivate
->devices
!= NULL
) CFRelease(bondPrivate
->devices
);
494 if ((newDevices
!= NULL
) && (CFArrayGetCount(newDevices
) > 0)) {
495 bondPrivate
->devices
= CFArrayCreateCopy(allocator
, newDevices
);
497 bondPrivate
->devices
= NULL
;
506 BondInterfaceSetOptions(BondInterfaceRef bond
, CFDictionaryRef newOptions
)
508 BondInterfacePrivateRef bondPrivate
= (BondInterfacePrivateRef
)bond
;
510 if (isA_BondInterface(bond
)) {
511 CFAllocatorRef allocator
= CFGetAllocator(bond
);
513 if (bondPrivate
->options
) CFRelease(bondPrivate
->options
);
514 if (newOptions
!= NULL
) {
515 bondPrivate
->options
= CFDictionaryCreateCopy(allocator
, newOptions
);
517 bondPrivate
->options
= NULL
;
525 /* ---------- BondPreferences ---------- */
527 #define BOND_PREFERENCES_BONDS CFSTR("Bonds")
529 #define __kBondInterface_interface CFSTR("interface") // e.g. bond0, bond1, ...
530 #define __kBondInterface_devices CFSTR("devices") // e.g. en0, en1, ...
531 #define __kBondInterface_options CFSTR("options") // e.g. UserDefinedName
535 /* base CFType information */
536 CFRuntimeBase cfBase
;
539 pthread_mutex_t lock
;
541 /* underlying preferences */
542 SCPreferencesRef prefs
;
544 /* base Bonds (before any commits) */
547 } BondPreferencesPrivate
, * BondPreferencesPrivateRef
;
550 static CFStringRef
__BondPreferencesCopyDescription (CFTypeRef cf
);
551 static void __BondPreferencesDeallocate (CFTypeRef cf
);
554 static const CFRuntimeClass __BondPreferencesClass
= {
556 "BondPreferences", // className
559 __BondPreferencesDeallocate
, // dealloc
562 NULL
, // copyFormattingDesc
563 __BondPreferencesCopyDescription
// copyDebugDesc
567 static CFTypeID __kBondPreferencesTypeID
= _kCFRuntimeNotATypeID
;
570 static pthread_once_t bondPreferences_init
= PTHREAD_ONCE_INIT
;
574 __BondPreferencesCopyDescription(CFTypeRef cf
)
576 CFAllocatorRef allocator
= CFGetAllocator(cf
);
580 BondPreferencesPrivateRef prefsPrivate
= (BondPreferencesPrivateRef
)cf
;
581 CFMutableStringRef result
;
583 result
= CFStringCreateMutable(allocator
, 0);
584 CFStringAppendFormat(result
, NULL
, CFSTR("<BondPreferences %p [%p]> {"), cf
, allocator
);
586 keys
= SCPreferencesCopyKeyList(prefsPrivate
->prefs
);
587 n
= CFArrayGetCount(keys
);
588 for (i
= 0; i
< n
; i
++) {
590 CFPropertyListRef val
;
592 key
= CFArrayGetValueAtIndex(keys
, i
);
593 val
= SCPreferencesGetValue(prefsPrivate
->prefs
, key
);
595 CFStringAppendFormat(result
, NULL
, CFSTR("%@ : %@"), key
, val
);
599 CFStringAppendFormat(result
, NULL
, CFSTR(" }"));
606 __BondPreferencesDeallocate(CFTypeRef cf
)
608 BondPreferencesPrivateRef prefsPrivate
= (BondPreferencesPrivateRef
)cf
;
610 /* release resources */
612 pthread_mutex_destroy(&prefsPrivate
->lock
);
614 if (prefsPrivate
->prefs
) CFRelease(prefsPrivate
->prefs
);
615 if (prefsPrivate
->bBase
) CFRelease(prefsPrivate
->bBase
);
622 __BondPreferencesInitialize(void)
624 __kBondPreferencesTypeID
= _CFRuntimeRegisterClass(&__BondPreferencesClass
);
629 static __inline__ CFTypeRef
630 isA_BondPreferences(CFTypeRef obj
)
632 return (isA_CFType(obj
, BondPreferencesGetTypeID()));
637 _BondPreferencesCopyActiveInterfaces()
639 CFArrayCallBacks callbacks
;
640 struct ifaddrs
*ifap
;
643 CFMutableArrayRef bonds
= NULL
;
645 if (getifaddrs(&ifap
) == -1) {
646 SCLog(TRUE
, LOG_ERR
, CFSTR("getifaddrs() failed: %s"), strerror(errno
));
647 _SCErrorSet(kSCStatusFailed
);
651 s
= inet_dgram_socket();
653 SCLog(TRUE
, LOG_ERR
, CFSTR("socket() failed: %s"), strerror(errno
));
654 _SCErrorSet(kSCStatusFailed
);
658 callbacks
= kCFTypeArrayCallBacks
;
659 callbacks
.equal
= __BondInterfaceEquiv
;
660 bonds
= CFArrayCreateMutable(NULL
, 0, &callbacks
);
662 for (ifp
= ifap
; ifp
!= NULL
; ifp
= ifp
->ifa_next
) {
663 BondInterfaceRef bond
;
665 CFMutableArrayRef devices
= NULL
;
666 struct if_bond_status_req
*ibsr_p
;
667 struct if_data
*if_data
;
669 if_data
= (struct if_data
*)ifp
->ifa_data
;
671 || ifp
->ifa_addr
->sa_family
!= AF_LINK
672 || if_data
->ifi_type
!= IFT_IEEE8023ADLAG
) {
675 ibsr_p
= if_bond_status_req_copy(s
, ifp
->ifa_name
);
676 if (ibsr_p
== NULL
) {
677 SCLog(TRUE
, LOG_ERR
, CFSTR("if_bond_status_req_copy(%s) failed: %s"),
678 ifp
->ifa_name
, strerror(errno
));
679 _SCErrorSet(kSCStatusFailed
);
683 if (ibsr_p
->ibsr_total
> 0) {
685 struct if_bond_status
* ibs_p
;
686 devices
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
688 // iterate over each member device
689 ibs_p
= (struct if_bond_status
*)ibsr_p
->ibsr_buffer
;
690 for (i
= 0; i
< ibsr_p
->ibsr_total
; i
++) {
692 char if_name
[IFNAMSIZ
+1];
694 strlcpy(if_name
, ibs_p
[i
].ibs_if_name
, sizeof(if_name
));
695 device
= CFStringCreateWithCString(NULL
, if_name
, kCFStringEncodingASCII
);
696 CFArrayAppendValue(devices
, device
);
701 bond_if
= CFStringCreateWithCString(NULL
, ifp
->ifa_name
, kCFStringEncodingASCII
);
702 bond
= __BondInterfaceCreatePrivate(NULL
, bond_if
);
705 if (devices
!= NULL
) {
706 BondInterfaceSetDevices(bond
, devices
);
709 CFArrayAppendValue(bonds
, bond
);
722 findBond(CFArrayRef bonds
, CFStringRef interface
)
724 CFIndex found
= kCFNotFound
;
728 n
= isA_CFArray(bonds
) ? CFArrayGetCount(bonds
) : 0;
729 for (i
= 0; i
< n
; i
++) {
730 CFDictionaryRef bond_dict
;
733 bond_dict
= CFArrayGetValueAtIndex(bonds
, i
);
734 if (!isA_CFDictionary(bond_dict
)) {
735 break; // if the prefs are confused
738 bond_if
= CFDictionaryGetValue(bond_dict
, __kBondInterface_interface
);
739 if (!isA_CFString(bond_if
)) {
740 break; // if the prefs are confused
743 if (!CFEqual(bond_if
, interface
)) {
744 continue; // if not a match
747 // if we have found a match
757 setConfigurationChanged(BondPreferencesRef prefs
)
759 BondPreferencesPrivateRef prefsPrivate
= (BondPreferencesPrivateRef
)prefs
;
762 * to facilitate device configuration we will take
763 * a snapshot of the Bond preferences before any
764 * changes are made. Then, when the changes are
765 * applied we can compare what we had to what we
766 * want and configured the system accordingly.
768 if (prefsPrivate
->bBase
== NULL
) {
769 prefsPrivate
->bBase
= BondPreferencesCopyInterfaces(prefs
);
777 BondPreferencesGetTypeID(void)
779 pthread_once(&bondPreferences_init
, __BondPreferencesInitialize
); /* initialize runtime */
780 return __kBondPreferencesTypeID
;
785 BondPreferencesCreate(CFAllocatorRef allocator
)
788 CFStringRef bundleID
= NULL
;
789 CFStringRef name
= CFSTR("BondConfiguration");
790 BondPreferencesPrivateRef prefsPrivate
;
793 /* initialize runtime */
794 pthread_once(&bondPreferences_init
, __BondPreferencesInitialize
);
796 /* allocate preferences */
797 size
= sizeof(BondPreferencesPrivate
) - sizeof(CFRuntimeBase
);
798 prefsPrivate
= (BondPreferencesPrivateRef
)_CFRuntimeCreateInstance(allocator
,
799 __kBondPreferencesTypeID
,
802 if (prefsPrivate
== NULL
) {
806 /* establish the prefs */
808 pthread_mutex_init(&prefsPrivate
->lock
, NULL
);
810 bundle
= CFBundleGetMainBundle();
812 bundleID
= CFBundleGetIdentifier(bundle
);
818 url
= CFBundleCopyExecutableURL(bundle
);
820 bundleID
= CFURLCopyPath(url
);
827 CFStringRef fullName
;
829 if (CFEqual(bundleID
, CFSTR("/"))) {
831 bundleID
= CFStringCreateWithFormat(allocator
, NULL
, CFSTR("(%d)"), getpid());
834 fullName
= CFStringCreateWithFormat(allocator
, NULL
, CFSTR("%@:%@"), bundleID
, name
);
841 prefsPrivate
->prefs
= SCPreferencesCreate(allocator
, name
, BOND_PREFERENCES_ID
);
844 prefsPrivate
->bBase
= NULL
;
846 return (BondPreferencesRef
)prefsPrivate
;
851 BondPreferencesCopyInterfaces(BondPreferencesRef prefs
)
853 CFAllocatorRef allocator
;
854 CFArrayCallBacks callbacks
;
857 BondPreferencesPrivateRef prefsPrivate
= (BondPreferencesPrivateRef
)prefs
;
858 CFMutableArrayRef result
;
861 if (!isA_BondPreferences(prefs
)) {
862 _SCErrorSet(kSCStatusInvalidArgument
);
866 allocator
= CFGetAllocator(prefs
);
867 callbacks
= kCFTypeArrayCallBacks
;
868 callbacks
.equal
= __BondInterfaceEquiv
;
869 result
= CFArrayCreateMutable(allocator
, 0, &callbacks
);
871 bonds
= SCPreferencesGetValue(prefsPrivate
->prefs
, BOND_PREFERENCES_BONDS
);
872 if ((bonds
!= NULL
) && !isA_CFArray(bonds
)) {
873 goto error
; // if the prefs are confused
876 n
= (bonds
!= NULL
) ? CFArrayGetCount(bonds
) : 0;
877 for (i
= 0; i
< n
; i
++) {
878 BondInterfaceRef bond
;
879 CFDictionaryRef bond_dict
;
882 CFDictionaryRef options
;
884 bond_dict
= CFArrayGetValueAtIndex(bonds
, i
);
885 if (!isA_CFDictionary(bond_dict
)) {
886 goto error
; // if the prefs are confused
889 bond_if
= CFDictionaryGetValue(bond_dict
, __kBondInterface_interface
);
890 if (!isA_CFString(bond_if
)) {
891 goto error
; // if the prefs are confused
895 devices
= CFDictionaryGetValue(bond_dict
, __kBondInterface_devices
);
896 if ((devices
!= NULL
) && !isA_CFArray(devices
)) {
897 goto error
; // if the prefs are confused
900 options
= CFDictionaryGetValue(bond_dict
, __kBondInterface_options
);
901 if ((options
!= NULL
) && !isA_CFDictionary(options
)) {
902 goto error
; // if the prefs are confused
905 bond
= __BondInterfaceCreatePrivate(allocator
, bond_if
);
906 BondInterfaceSetDevices(bond
, devices
);
907 BondInterfaceSetOptions(bond
, options
);
908 CFArrayAppendValue(result
, bond
);
916 _SCErrorSet(kSCStatusFailed
);
923 BondPreferencesCreateInterface(BondPreferencesRef prefs
)
925 CFArrayRef active_bonds
= NULL
;
926 CFAllocatorRef allocator
;
927 CFArrayRef config_bonds
;
931 BondInterfaceRef newBond
= NULL
;
932 BondPreferencesPrivateRef prefsPrivate
= (BondPreferencesPrivateRef
)prefs
;
934 if (!isA_BondPreferences(prefs
)) {
935 _SCErrorSet(kSCStatusInvalidArgument
);
939 pthread_mutex_lock(&prefsPrivate
->lock
);
941 /* get "configured" Bonds (and check to ensure the device is available) */
942 config_bonds
= SCPreferencesGetValue(prefsPrivate
->prefs
, BOND_PREFERENCES_BONDS
);
943 if ((config_bonds
!= NULL
) && !isA_CFArray(config_bonds
)) {
944 // if the prefs are confused
945 _SCErrorSet(kSCStatusFailed
);
949 nConfig
= (config_bonds
!= NULL
) ? CFArrayGetCount(config_bonds
) : 0;
951 /* get "active" Bonds */
952 active_bonds
= _BondPreferencesCopyActiveInterfaces();
953 nActive
= isA_CFArray(active_bonds
) ? CFArrayGetCount(active_bonds
) : 0;
955 /* create a new bond using an unused interface name */
956 allocator
= CFGetAllocator(prefs
);
958 for (i
= 0; newBond
== NULL
; i
++) {
960 CFMutableDictionaryRef newDict
;
961 CFMutableArrayRef newBonds
;
964 bond_if
= CFStringCreateWithFormat(allocator
, NULL
, CFSTR("bond%d"), i
);
966 for (j
= 0; j
< nActive
; j
++) {
967 CFStringRef active_if
;
968 BondInterfaceRef active_bond
;
970 active_bond
= CFArrayGetValueAtIndex(active_bonds
, j
);
971 active_if
= BondInterfaceGetInterface(active_bond
);
973 if (CFEqual(bond_if
, active_if
)) {
974 goto next_if
; // if bond interface name not available
978 for (j
= 0; j
< nConfig
; j
++) {
979 CFDictionaryRef config
;
980 CFStringRef config_if
;
982 config
= CFArrayGetValueAtIndex(config_bonds
, j
);
983 if (!isA_CFDictionary(config
)) {
984 // if the prefs are confused
985 _SCErrorSet(kSCStatusFailed
);
990 config_if
= CFDictionaryGetValue(config
, __kBondInterface_interface
);
991 if (!isA_CFString(config_if
)) {
992 // if the prefs are confused
993 _SCErrorSet(kSCStatusFailed
);
998 if (CFEqual(bond_if
, config_if
)) {
999 goto next_if
; // if bond interface name not available
1003 /* create the bond */
1005 newDict
= CFDictionaryCreateMutable(allocator
,
1007 &kCFTypeDictionaryKeyCallBacks
,
1008 &kCFTypeDictionaryValueCallBacks
);
1009 CFDictionaryAddValue(newDict
, __kBondInterface_interface
, bond_if
);
1011 /* create the accessor handle to be returned */
1013 newBond
= __BondInterfaceCreatePrivate(allocator
, bond_if
);
1015 /* save in the prefs */
1018 newBonds
= CFArrayCreateMutableCopy(allocator
, 0, config_bonds
);
1020 newBonds
= CFArrayCreateMutable(allocator
, 0, &kCFTypeArrayCallBacks
);
1022 CFArrayAppendValue(newBonds
, newDict
);
1025 /* yes, we're going to be changing the configuration */
1026 setConfigurationChanged(prefs
);
1028 (void) SCPreferencesSetValue(prefsPrivate
->prefs
, BOND_PREFERENCES_BONDS
, newBonds
);
1029 CFRelease(newBonds
);
1037 if (active_bonds
!= NULL
) CFRelease(active_bonds
);
1039 pthread_mutex_unlock(&prefsPrivate
->lock
);
1041 return (BondInterfaceRef
) newBond
;
1046 _BondPreferencesUpdate(BondPreferencesRef prefs
, BondInterfaceRef bond
)
1048 CFAllocatorRef allocator
;
1051 CFStringRef interface
;
1052 CFMutableDictionaryRef newDict
;
1053 CFMutableArrayRef newBonds
;
1054 CFDictionaryRef options
;
1055 BondPreferencesPrivateRef prefsPrivate
= (BondPreferencesPrivateRef
)prefs
;
1058 bonds
= SCPreferencesGetValue(prefsPrivate
->prefs
, BOND_PREFERENCES_BONDS
);
1059 if ((bonds
!= NULL
) && !isA_CFArray(bonds
)) {
1060 // if the prefs are confused
1061 _SCErrorSet(kSCStatusFailed
);
1065 interface
= BondInterfaceGetInterface(bond
);
1066 bond_index
= findBond(bonds
, interface
);
1067 if (bond_index
== kCFNotFound
) {
1068 _SCErrorSet(kSCStatusNoKey
);
1072 /* create the bond dictionary */
1074 allocator
= CFGetAllocator(prefs
);
1075 newDict
= CFDictionaryCreateMutable(allocator
,
1077 &kCFTypeDictionaryKeyCallBacks
,
1078 &kCFTypeDictionaryValueCallBacks
);
1079 CFDictionaryAddValue(newDict
, __kBondInterface_interface
, interface
);
1081 devices
= BondInterfaceGetDevices(bond
);
1082 if (devices
!= NULL
) {
1083 CFDictionaryAddValue(newDict
, __kBondInterface_devices
, devices
);
1086 options
= BondInterfaceGetOptions(bond
);
1087 if (options
!= NULL
) {
1088 CFDictionaryAddValue(newDict
, __kBondInterface_options
, options
);
1091 /* yes, we're going to be changing the configuration */
1092 setConfigurationChanged(prefs
);
1094 /* update the prefs */
1096 newBonds
= CFArrayCreateMutableCopy(allocator
, 0, bonds
);
1097 CFArraySetValueAtIndex(newBonds
, bond_index
, newDict
);
1099 (void) SCPreferencesSetValue(prefsPrivate
->prefs
, BOND_PREFERENCES_BONDS
, newBonds
);
1100 CFRelease(newBonds
);
1107 BondPreferencesAddDevice(BondPreferencesRef prefs
,
1108 BondInterfaceRef bond
,
1111 CFArrayRef config_bonds
;
1115 BondPreferencesPrivateRef prefsPrivate
= (BondPreferencesPrivateRef
)prefs
;
1117 if (!isA_BondPreferences(prefs
)) {
1118 _SCErrorSet(kSCStatusInvalidArgument
);
1122 if (!isA_BondInterface(bond
)) {
1123 _SCErrorSet(kSCStatusInvalidArgument
);
1127 if (!isA_CFString(device
)) {
1128 _SCErrorSet(kSCStatusInvalidArgument
);
1132 if (!IsBondSupported(device
)) {
1133 _SCErrorSet(kSCStatusInvalidArgument
);
1137 pthread_mutex_lock(&prefsPrivate
->lock
);
1139 /* get "configured" bonds */
1140 config_bonds
= SCPreferencesGetValue(prefsPrivate
->prefs
, BOND_PREFERENCES_BONDS
);
1141 if ((config_bonds
!= NULL
) && !isA_CFArray(config_bonds
)) {
1142 _SCErrorSet(kSCStatusFailed
);
1147 nConfig
= (config_bonds
!= NULL
) ? CFArrayGetCount(config_bonds
) : 0;
1149 /* check to ensure the requested device is available */
1150 for (i
= 0; ok
&& (i
< nConfig
); i
++) {
1151 CFDictionaryRef config_bond
;
1154 config_bond
= CFArrayGetValueAtIndex(config_bonds
, i
);
1155 if (!isA_CFDictionary(config_bond
)) {
1156 ok
= FALSE
; // if the prefs are confused
1160 devices
= CFDictionaryGetValue(config_bond
, __kBondInterface_devices
);
1161 if ((devices
!= NULL
) && !isA_CFArray(devices
)) {
1162 ok
= FALSE
; // if the prefs are confused
1166 if (devices
== NULL
) {
1167 continue; // if no devices
1170 ok
= !CFArrayContainsValue(devices
,
1171 CFRangeMake(0, CFArrayGetCount(devices
)),
1177 CFMutableArrayRef newDevices
;
1179 devices
= BondInterfaceGetDevices(bond
);
1180 if (devices
!= NULL
) {
1181 devices
= CFArrayCreateCopy(NULL
, devices
);
1182 newDevices
= CFArrayCreateMutableCopy(NULL
, 0, devices
);
1184 newDevices
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1186 CFArrayAppendValue(newDevices
, device
);
1187 BondInterfaceSetDevices(bond
, newDevices
);
1188 CFRelease(newDevices
);
1190 ok
= _BondPreferencesUpdate(prefs
, bond
);
1192 BondInterfaceSetDevices(bond
, devices
);
1195 if (devices
!= NULL
) {
1199 _SCErrorSet(kSCStatusKeyExists
);
1204 pthread_mutex_unlock(&prefsPrivate
->lock
);
1211 BondPreferencesRemoveDevice(BondPreferencesRef prefs
,
1212 BondInterfaceRef bond
,
1218 BondPreferencesPrivateRef prefsPrivate
= (BondPreferencesPrivateRef
)prefs
;
1220 if (!isA_BondPreferences(prefs
)) {
1221 _SCErrorSet(kSCStatusInvalidArgument
);
1225 if (!isA_BondInterface(bond
)) {
1226 _SCErrorSet(kSCStatusInvalidArgument
);
1230 if (!isA_CFString(device
)) {
1231 _SCErrorSet(kSCStatusInvalidArgument
);
1235 pthread_mutex_lock(&prefsPrivate
->lock
);
1237 devices
= BondInterfaceGetDevices(bond
);
1238 if (devices
!= NULL
) {
1239 bond_index
= CFArrayGetFirstIndexOfValue(devices
,
1240 CFRangeMake(0, CFArrayGetCount(devices
)),
1242 if (bond_index
!= kCFNotFound
) {
1243 CFMutableArrayRef newDevices
;
1245 devices
= CFArrayCreateCopy(NULL
, devices
);
1246 newDevices
= CFArrayCreateMutableCopy(NULL
, 0, devices
);
1247 CFArrayRemoveValueAtIndex(newDevices
, bond_index
);
1248 BondInterfaceSetDevices(bond
, newDevices
);
1249 CFRelease(newDevices
);
1251 ok
= _BondPreferencesUpdate(prefs
, bond
);
1253 BondInterfaceSetDevices(bond
, devices
);
1258 _SCErrorSet(kSCStatusNoKey
);
1262 pthread_mutex_unlock(&prefsPrivate
->lock
);
1269 BondPreferencesSetOptions(BondPreferencesRef prefs
, BondInterfaceRef bond
, CFDictionaryRef newOptions
)
1272 CFDictionaryRef options
;
1273 BondPreferencesPrivateRef prefsPrivate
= (BondPreferencesPrivateRef
)prefs
;
1275 if (!isA_BondPreferences(prefs
)) {
1276 _SCErrorSet(kSCStatusInvalidArgument
);
1280 if (!isA_BondInterface(bond
)) {
1281 _SCErrorSet(kSCStatusInvalidArgument
);
1285 pthread_mutex_lock(&prefsPrivate
->lock
);
1287 options
= BondInterfaceGetOptions(bond
);
1288 if (options
!= NULL
) {
1289 options
= CFDictionaryCreateCopy(NULL
, options
);
1292 BondInterfaceSetOptions(bond
, newOptions
);
1293 ok
= _BondPreferencesUpdate(prefs
, bond
);
1295 BondInterfaceSetOptions(bond
, options
);
1298 if (options
!= NULL
) {
1302 pthread_mutex_unlock(&prefsPrivate
->lock
);
1309 BondPreferencesRemoveInterface(BondPreferencesRef prefs
,
1310 BondInterfaceRef bond
)
1314 BondPreferencesPrivateRef prefsPrivate
= (BondPreferencesPrivateRef
)prefs
;
1317 if (!isA_BondPreferences(prefs
)) {
1318 _SCErrorSet(kSCStatusInvalidArgument
);
1322 if (!isA_BondInterface(bond
)) {
1323 _SCErrorSet(kSCStatusInvalidArgument
);
1327 pthread_mutex_lock(&prefsPrivate
->lock
);
1329 bonds
= SCPreferencesGetValue(prefsPrivate
->prefs
, BOND_PREFERENCES_BONDS
);
1330 if (!isA_CFArray(bonds
)) {
1331 // if the prefs are confused
1332 _SCErrorSet(kSCStatusFailed
);
1336 bond_index
= findBond(bonds
, BondInterfaceGetInterface(bond
));
1337 if (bond_index
== kCFNotFound
) {
1338 _SCErrorSet(kSCStatusNoKey
);
1342 /* yes, we're going to be changing the configuration */
1343 setConfigurationChanged(prefs
);
1345 /* remove the bond */
1347 if (CFArrayGetCount(bonds
) > 1) {
1348 CFAllocatorRef allocator
;
1349 CFMutableArrayRef newBonds
;
1351 allocator
= CFGetAllocator(prefs
);
1352 newBonds
= CFArrayCreateMutableCopy(allocator
, 0, bonds
);
1353 CFArrayRemoveValueAtIndex(newBonds
, bond_index
);
1354 (void) SCPreferencesSetValue(prefsPrivate
->prefs
, BOND_PREFERENCES_BONDS
, newBonds
);
1355 CFRelease(newBonds
);
1357 (void) SCPreferencesRemoveValue(prefsPrivate
->prefs
, BOND_PREFERENCES_BONDS
);
1364 pthread_mutex_unlock(&prefsPrivate
->lock
);
1371 BondPreferencesCommitChanges(BondPreferencesRef prefs
)
1374 BondPreferencesPrivateRef prefsPrivate
= (BondPreferencesPrivateRef
)prefs
;
1376 if (!isA_BondPreferences(prefs
)) {
1377 _SCErrorSet(kSCStatusInvalidArgument
);
1381 ok
= SCPreferencesCommitChanges(prefsPrivate
->prefs
);
1386 if (prefsPrivate
->bBase
!= NULL
) {
1387 CFRelease(prefsPrivate
->bBase
);
1388 prefsPrivate
->bBase
= NULL
;
1396 _BondPreferencesUpdateConfiguration(BondPreferencesRef prefs
)
1398 CFArrayRef active
= NULL
;
1399 CFArrayRef config
= NULL
;
1404 BondPreferencesPrivateRef prefsPrivate
= (BondPreferencesPrivateRef
)prefs
;
1407 if (!isA_BondPreferences(prefs
)) {
1408 _SCErrorSet(kSCStatusInvalidArgument
);
1412 /* configured Bonds */
1413 if (prefsPrivate
->bBase
!= NULL
) {
1415 * updated Bond preferences have not been committed
1416 * so we ignore any in-progress changes and apply the
1417 * saved preferences.
1419 config
= CFRetain(prefsPrivate
->bBase
);
1422 * apply the saved preferences
1424 config
= BondPreferencesCopyInterfaces(prefs
);
1426 nConfig
= CFArrayGetCount(config
);
1429 active
= _BondPreferencesCopyActiveInterfaces();
1430 nActive
= CFArrayGetCount(active
);
1433 * remove any no-longer-configured bond interfaces and
1434 * any devices associated with a bond that are no longer
1435 * associated with a bond.
1437 for (i
= 0; i
< nActive
; i
++) {
1438 BondInterfaceRef a_bond
;
1439 CFStringRef a_bond_if
;
1441 Boolean found
= FALSE
;
1443 a_bond
= CFArrayGetValueAtIndex(active
, i
);
1444 a_bond_if
= BondInterfaceGetInterface(a_bond
);
1446 for (j
= 0; j
< nConfig
; j
++) {
1447 BondInterfaceRef c_bond
;
1448 CFStringRef c_bond_if
;
1450 c_bond
= CFArrayGetValueAtIndex(config
, j
);
1451 c_bond_if
= BondInterfaceGetInterface(c_bond
);
1453 if (CFEqual(a_bond_if
, c_bond_if
)) {
1456 CFArrayRef a_bond_devices
;
1458 CFArrayRef c_bond_devices
;
1460 c_bond_devices
= BondInterfaceGetDevices(c_bond
);
1461 c_count
= (c_bond_devices
!= NULL
) ? CFArrayGetCount(c_bond_devices
) : 0;
1463 a_bond_devices
= BondInterfaceGetDevices(a_bond
);
1464 a_count
= (a_bond_devices
!= NULL
) ? CFArrayGetCount(a_bond_devices
) : 0;
1466 for (a
= 0; a
< a_count
; a
++) {
1467 CFStringRef a_device
;
1469 a_device
= CFArrayGetValueAtIndex(a_bond_devices
, a
);
1470 if ((c_count
== 0) ||
1471 !CFArrayContainsValue(c_bond_devices
,
1472 CFRangeMake(0, c_count
),
1475 * if this device is no longer part
1479 s
= inet_dgram_socket();
1482 ok
= _Bond_removeDevice(s
, a_bond_if
, a_device
);
1496 * if this interface is no longer configured
1499 s
= inet_dgram_socket();
1502 ok
= __destroyInterface(s
, a_bond_if
);
1504 _SCErrorSet(kSCStatusFailed
);
1511 * add any newly-configured bond interfaces and add any
1512 * devices that should now be associated with the bond.
1514 for (i
= 0; i
< nConfig
; i
++) {
1515 BondInterfaceRef c_bond
;
1516 CFArrayRef c_bond_devices
;
1517 CFStringRef c_bond_if
;
1519 Boolean found
= FALSE
;
1522 c_bond
= CFArrayGetValueAtIndex(config
, i
);
1523 c_bond_if
= BondInterfaceGetInterface(c_bond
);
1524 c_bond_devices
= BondInterfaceGetDevices(c_bond
);
1525 c_count
= (c_bond_devices
!= NULL
) ? CFArrayGetCount(c_bond_devices
) : 0;
1527 for (j
= 0; j
< nActive
; j
++) {
1528 BondInterfaceRef a_bond
;
1529 CFArrayRef a_bond_devices
;
1530 CFStringRef a_bond_if
;
1533 a_bond
= CFArrayGetValueAtIndex(active
, j
);
1534 a_bond_if
= BondInterfaceGetInterface(a_bond
);
1535 a_bond_devices
= BondInterfaceGetDevices(a_bond
);
1536 a_count
= (a_bond_devices
!= NULL
) ? CFArrayGetCount(a_bond_devices
) : 0;
1538 if (CFEqual(c_bond_if
, a_bond_if
)) {
1543 if ((c_bond_devices
== NULL
) &&
1544 (a_bond_devices
== NULL
)) {
1545 break; // if no change
1548 if ((c_bond_devices
!= NULL
) &&
1549 (a_bond_devices
!= NULL
) &&
1550 CFEqual(c_bond_devices
, a_bond_devices
)) {
1551 break; // if no change
1555 s
= inet_dgram_socket();
1559 * ensure that the first device of the bond matches, if
1560 * not then we remove all current devices and add them
1561 * back in the preferred order.
1563 if ((c_count
> 0) &&
1565 !CFEqual(CFArrayGetValueAtIndex(c_bond_devices
, 0),
1566 CFArrayGetValueAtIndex(a_bond_devices
, 0))) {
1569 for (a
= 0; a
< a_count
; a
++) {
1570 CFStringRef a_device
;
1572 a_device
= CFArrayGetValueAtIndex(a_bond_devices
, a
);
1574 if (!CFArrayContainsValue(c_bond_devices
,
1575 CFRangeMake(0, c_count
),
1577 continue; // if already removed
1580 ok
= _Bond_removeDevice(s
, a_bond_if
, a_device
);
1586 a_count
= 0; // all active devices have been removed
1590 * add any devices which are not currently associated
1591 * with the bond interface.
1593 for (c
= 0; c
< c_count
; c
++) {
1594 CFStringRef c_device
;
1596 c_device
= CFArrayGetValueAtIndex(c_bond_devices
, c
);
1597 if ((a_count
== 0) ||
1598 !CFArrayContainsValue(a_bond_devices
,
1599 CFRangeMake(0, a_count
),
1602 * check if this device can be added to
1605 if (!IsBondSupported(c_device
)) {
1611 * if this device is not currently part
1615 ok
= _Bond_addDevice(s
, c_bond_if
, c_device
);
1630 s
= inet_dgram_socket();
1634 * establish the new bond interface.
1636 ok
= __createInterface(s
, c_bond_if
);
1638 _SCErrorSet(kSCStatusFailed
);
1643 * add any devices which are not currently associated
1644 * with the bond interface.
1646 for (c
= 0; c
< c_count
; c
++) {
1647 CFStringRef c_device
;
1649 c_device
= CFArrayGetValueAtIndex(c_bond_devices
, c
);
1651 if (!IsBondSupported(c_device
)) {
1656 ok
= _Bond_addDevice(s
, c_bond_if
, c_device
);
1669 if (active
!= NULL
) CFRelease(active
);
1670 if (config
!= NULL
) CFRelease(config
);
1671 if (s
!= -1) (void) close(s
);
1678 BondPreferencesApplyChanges(BondPreferencesRef prefs
)
1681 BondPreferencesPrivateRef prefsPrivate
= (BondPreferencesPrivateRef
)prefs
;
1683 if (!isA_BondPreferences(prefs
)) {
1684 _SCErrorSet(kSCStatusInvalidArgument
);
1688 pthread_mutex_lock(&prefsPrivate
->lock
);
1690 /* apply the preferences */
1691 ok
= SCPreferencesApplyChanges(prefsPrivate
->prefs
);
1696 /* apply the Bond configuration */
1697 ok
= _BondPreferencesUpdateConfiguration(prefs
);
1704 pthread_mutex_unlock(&prefsPrivate
->lock
);
1710 /* ---------- BondStatus ---------- */
1714 /* base CFType information */
1715 CFRuntimeBase cfBase
;
1717 /* bond interface */
1718 BondInterfaceRef bond
;
1721 CFDictionaryRef status_interface
; // interface status
1722 CFArrayRef devices
; // per-device status
1723 CFDictionaryRef status_devices
;
1725 } BondStatusPrivate
, * BondStatusPrivateRef
;
1728 const CFStringRef kSCBondStatusDeviceAggregationStatus
= CFSTR("AggregationStatus");
1729 const CFStringRef kSCBondStatusDeviceCollecting
= CFSTR("Collecting");
1730 const CFStringRef kSCBondStatusDeviceDistributing
= CFSTR("Distributing");
1733 static CFStringRef
__BondStatusCopyDescription (CFTypeRef cf
);
1734 static void __BondStatusDeallocate (CFTypeRef cf
);
1735 static Boolean
__BondStatusEqual (CFTypeRef cf1
, CFTypeRef cf2
);
1738 static const CFRuntimeClass __BondStatusClass
= {
1740 "BondStatus", // className
1743 __BondStatusDeallocate
, // dealloc
1744 __BondStatusEqual
, // equal
1746 NULL
, // copyFormattingDesc
1747 __BondStatusCopyDescription
// copyDebugDesc
1751 static CFTypeID __kBondStatusTypeID
= _kCFRuntimeNotATypeID
;
1754 static pthread_once_t bondStatus_init
= PTHREAD_ONCE_INIT
;
1758 __BondStatusCopyDescription(CFTypeRef cf
)
1760 CFAllocatorRef allocator
= CFGetAllocator(cf
);
1761 CFMutableStringRef result
;
1762 BondStatusPrivateRef statusPrivate
= (BondStatusPrivateRef
)cf
;
1764 result
= CFStringCreateMutable(allocator
, 0);
1765 CFStringAppendFormat(result
, NULL
, CFSTR("<BondStatus %p [%p]> {"), cf
, allocator
);
1766 CFStringAppendFormat(result
, NULL
, CFSTR(" bond = %@"), statusPrivate
->bond
);
1767 CFStringAppendFormat(result
, NULL
, CFSTR(" interface = %@"), statusPrivate
->status_interface
);
1768 CFStringAppendFormat(result
, NULL
, CFSTR(" devices = %@"), statusPrivate
->status_devices
);
1769 CFStringAppendFormat(result
, NULL
, CFSTR(" }"));
1776 __BondStatusDeallocate(CFTypeRef cf
)
1778 BondStatusPrivateRef statusPrivate
= (BondStatusPrivateRef
)cf
;
1780 /* release resources */
1782 CFRelease(statusPrivate
->bond
);
1783 CFRelease(statusPrivate
->status_interface
);
1784 if (statusPrivate
->devices
!= NULL
) CFRelease(statusPrivate
->devices
);
1785 CFRelease(statusPrivate
->status_devices
);
1791 __BondStatusEqual(CFTypeRef cf1
, CFTypeRef cf2
)
1793 BondStatusPrivateRef status1
= (BondStatusPrivateRef
)cf1
;
1794 BondStatusPrivateRef status2
= (BondStatusPrivateRef
)cf2
;
1796 if (status1
== status2
)
1799 if (!CFEqual(status1
->bond
, status2
->bond
))
1800 return FALSE
; // if not the same bond
1802 if (!CFEqual(status1
->status_interface
, status2
->status_interface
))
1803 return FALSE
; // if not the same interface status
1805 if (!CFEqual(status1
->status_devices
, status2
->status_devices
))
1806 return FALSE
; // if not the same device status
1813 __BondStatusInitialize(void)
1815 __kBondStatusTypeID
= _CFRuntimeRegisterClass(&__BondStatusClass
);
1820 static __inline__ CFTypeRef
1821 isA_BondStatus(CFTypeRef obj
)
1823 return (isA_CFType(obj
, BondStatusGetTypeID()));
1828 BondStatusGetTypeID(void)
1830 pthread_once(&bondStatus_init
, __BondStatusInitialize
); /* initialize runtime */
1831 return __kBondStatusTypeID
;
1835 static BondStatusRef
1836 __BondStatusCreatePrivate(CFAllocatorRef allocator
,
1837 BondInterfaceRef bond
,
1838 CFDictionaryRef status_interface
,
1839 CFDictionaryRef status_devices
)
1841 BondStatusPrivateRef statusPrivate
;
1844 /* initialize runtime */
1845 pthread_once(&bondStatus_init
, __BondStatusInitialize
);
1848 size
= sizeof(BondStatusPrivate
) - sizeof(CFRuntimeBase
);
1849 statusPrivate
= (BondStatusPrivateRef
)_CFRuntimeCreateInstance(allocator
,
1850 __kBondStatusTypeID
,
1853 if (statusPrivate
== NULL
) {
1857 /* establish the bond status */
1859 statusPrivate
->bond
= CFRetain(bond
);
1860 statusPrivate
->status_interface
= CFDictionaryCreateCopy(allocator
, status_interface
);
1861 statusPrivate
->devices
= NULL
;
1862 statusPrivate
->status_devices
= CFDictionaryCreateCopy(allocator
, status_devices
);
1864 return (BondStatusRef
)statusPrivate
;
1869 BondInterfaceCopyStatus(BondInterfaceRef bond
)
1871 BondInterfacePrivateRef bondPrivate
= (BondInterfacePrivateRef
)bond
;
1874 char bond_ifname
[IFNAMSIZ
+ 1];
1876 struct if_bond_status_req
*ibsr_p
= NULL
;
1880 struct if_bond_status
* scan_p
;
1881 BondStatusRef status
= NULL
;
1882 CFMutableDictionaryRef status_devices
;
1883 CFMutableDictionaryRef status_interface
;
1885 if (!isA_BondInterface(bond
)) {
1889 s
= inet_dgram_socket();
1893 _SC_cfstring_to_cstring(bondPrivate
->ifname
, bond_ifname
,
1894 sizeof(bond_ifname
), kCFStringEncodingASCII
);
1895 (void)siocgifmedia(s
, bond_ifname
, &bond_if_status
, &bond_if_active
);
1896 ibsr_p
= if_bond_status_req_copy(s
, bond_ifname
);
1897 if (ibsr_p
== NULL
) {
1900 status_interface
= CFDictionaryCreateMutable(NULL
,
1902 &kCFTypeDictionaryKeyCallBacks
,
1903 &kCFTypeDictionaryValueCallBacks
);
1905 status_devices
= CFDictionaryCreateMutable(NULL
,
1907 &kCFTypeDictionaryKeyCallBacks
,
1908 &kCFTypeDictionaryValueCallBacks
);
1909 n
= ibsr_p
->ibsr_total
;
1910 for (i
= 0, scan_p
= (struct if_bond_status
*)ibsr_p
->ibsr_buffer
; i
< n
; i
++, scan_p
++) {
1911 CFStringRef bond_if
;
1913 int distributing
= 0;
1914 struct if_bond_partner_state
* ps
;
1915 CFMutableDictionaryRef status_device
;
1918 ps
= &scan_p
->ibs_partner_state
;
1920 status_device
= CFDictionaryCreateMutable(NULL
,
1922 &kCFTypeDictionaryKeyCallBacks
,
1923 &kCFTypeDictionaryValueCallBacks
);
1924 if (lacp_actor_partner_state_in_sync(scan_p
->ibs_state
)) {
1926 status_val
= kSCBondStatusOK
;
1927 if (lacp_actor_partner_state_in_sync(ps
->ibps_state
)) {
1928 /* partner is also in-sync */
1929 if (lacp_actor_partner_state_collecting(scan_p
->ibs_state
)
1930 && lacp_actor_partner_state_distributing(ps
->ibps_state
)) {
1931 /* we're able to collect (receive) frames */
1934 if (lacp_actor_partner_state_distributing(scan_p
->ibs_state
)
1935 && lacp_actor_partner_state_collecting(ps
->ibps_state
)) {
1936 /* we're able to distribute (transmit) frames */
1944 lacp_system zeroes
= {{0,0,0,0,0,0}};
1946 (void)siocgifmedia(s
, scan_p
->ibs_if_name
, &status
, &active
);
1947 if ((status
& IFM_AVALID
) == 0 || (status
& IFM_ACTIVE
) == 0
1948 || (active
& IFM_FDX
) == 0) {
1949 /* link down or not full-duplex */
1950 status_val
= kSCBondStatusLinkInvalid
;
1952 else if (ps
->ibps_system_priority
== 0
1953 && bcmp(&zeroes
, &ps
->ibps_system
, sizeof(zeroes
)) == 0) {
1954 /* no one on the other end of the link */
1955 status_val
= kSCBondStatusNoPartner
;
1957 else if (active
!= bond_if_active
) {
1958 /* the link speed was different */
1959 status_val
= kSCBondStatusLinkInvalid
;
1962 /* partner is not in the active group */
1963 status_val
= kSCBondStatusNotInActiveGroup
;
1966 num
= CFNumberCreate(NULL
, kCFNumberIntType
, &status_val
);
1967 CFDictionarySetValue(status_device
, kSCBondStatusDeviceAggregationStatus
, num
);
1969 num
= CFNumberCreate(NULL
, kCFNumberIntType
, &collecting
);
1970 CFDictionarySetValue(status_device
, kSCBondStatusDeviceCollecting
, num
);
1972 num
= CFNumberCreate(NULL
, kCFNumberIntType
, &distributing
);
1973 CFDictionarySetValue(status_device
, kSCBondStatusDeviceDistributing
, num
);
1975 bond_if
= CFArrayGetValueAtIndex(bondPrivate
->devices
, i
);
1976 CFDictionarySetValue(status_devices
, bond_if
, status_device
);
1977 CFRelease(status_device
);
1980 status
= __BondStatusCreatePrivate(NULL
, bond
, status_interface
, status_devices
);
1982 CFRelease(status_interface
);
1983 CFRelease(status_devices
);
1988 if (ibsr_p
!= NULL
) {
1999 BondStatusGetDevices(BondStatusRef bondStatus
)
2001 BondStatusPrivateRef statusPrivate
= (BondStatusPrivateRef
)bondStatus
;
2003 if (!isA_BondStatus(bondStatus
)) {
2007 if (statusPrivate
->devices
== NULL
) {
2008 const void * keys_q
[N_QUICK
];
2009 const void ** keys
= keys_q
;
2012 n
= CFDictionaryGetCount(statusPrivate
->status_devices
);
2013 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
2014 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
2016 CFDictionaryGetKeysAndValues(statusPrivate
->status_devices
, keys
, NULL
);
2017 statusPrivate
->devices
= CFArrayCreate(NULL
, keys
, n
, &kCFTypeArrayCallBacks
);
2018 if (keys
!= keys_q
) {
2019 CFAllocatorDeallocate(NULL
, keys
);
2023 return statusPrivate
->devices
;
2028 BondStatusGetInterfaceStatus(BondStatusRef bondStatus
)
2030 BondStatusPrivateRef statusPrivate
= (BondStatusPrivateRef
)bondStatus
;
2032 if (!isA_BondStatus(bondStatus
)) {
2036 return statusPrivate
->status_interface
;
2041 BondStatusGetDeviceStatus(BondStatusRef bondStatus
, CFStringRef device
)
2043 BondStatusPrivateRef statusPrivate
= (BondStatusPrivateRef
)bondStatus
;
2045 if (!isA_BondStatus(bondStatus
)) {
2049 return CFDictionaryGetValue(statusPrivate
->status_devices
, device
);