2 * Copyright (c) 2004-2015 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 28, 2005 Allan Nathanson <ajn@apple.com>
30 * July 22, 2004 Allan Nathanson <ajn@apple.com>
35 #include <CoreFoundation/CoreFoundation.h>
36 #include <CoreFoundation/CFRuntime.h>
38 #include <SystemConfiguration/SystemConfiguration.h>
39 #include "SCNetworkConfigurationInternal.h"
40 #include "SCPreferencesInternal.h"
41 #include <SystemConfiguration/SCValidation.h>
42 #include <SystemConfiguration/SCPrivate.h>
47 #include <sys/types.h>
48 #include <sys/ioctl.h>
49 #include <sys/socket.h>
50 #include <sys/sysctl.h>
51 #include <net/ethernet.h>
52 #define KERNEL_PRIVATE
54 #include <net/if_var.h>
56 #include <net/if_bond_var.h>
57 #include <net/if_types.h>
58 #include <net/if_media.h>
59 #include <net/route.h>
61 /* ---------- Bond support ---------- */
68 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
70 SC_log(LOG_ERR
, "socket() failed: %s", strerror(errno
));
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
) == -1) {
88 if (ifmr
.ifm_count
!= 0) {
89 *status
= ifmr
.ifm_status
;
90 *active
= ifmr
.ifm_active
;
95 static struct if_bond_status_req
*
96 if_bond_status_req_copy(int s
, const char * ifname
)
99 struct if_bond_req ibr
;
100 struct if_bond_status_req
* ibsr_p
;
103 bzero(&ifr
, sizeof(ifr
));
104 strlcpy(ifr
.ifr_name
, ifname
, sizeof(ifr
.ifr_name
));
105 bzero((char *)&ibr
, sizeof(ibr
));
106 ibr
.ibr_op
= IF_BOND_OP_GET_STATUS
;
107 ibsr_p
= &ibr
.ibr_ibru
.ibru_status
;
108 ibsr_p
->ibsr_version
= IF_BOND_STATUS_REQ_VERSION
;
109 ifr
.ifr_data
= (caddr_t
)&ibr
;
111 /* how many of them are there? */
112 if (ioctl(s
, SIOCGIFBOND
, (caddr_t
)&ifr
) == -1) {
115 buf
= malloc(sizeof(struct if_bond_status
) * ibsr_p
->ibsr_total
+ sizeof(*ibsr_p
));
119 if (ibsr_p
->ibsr_total
== 0) {
122 ibsr_p
->ibsr_count
= ibsr_p
->ibsr_total
;
123 ibsr_p
->ibsr_buffer
= buf
+ sizeof(*ibsr_p
);
126 if (ioctl(s
, SIOCGIFBOND
, (caddr_t
)&ifr
) == -1) {
130 (*(struct if_bond_status_req
*)buf
) = *ibsr_p
;
131 return ((struct if_bond_status_req
*)buf
);
142 add_interface(CFMutableArrayRef
*interfaces
, CFStringRef if_name
, SCPreferencesRef ni_prefs
)
144 SCNetworkInterfaceRef interface
= NULL
;
146 if (*interfaces
== NULL
) {
147 *interfaces
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
149 if (ni_prefs
!= NULL
) {
150 interface
= __SCNetworkInterfaceCreateWithNIPreferencesUsingBSDName(NULL
, ni_prefs
, if_name
);
152 if (interface
== NULL
) {
153 interface
= _SCNetworkInterfaceCreateWithBSDName(NULL
, if_name
,
154 kIncludeNoVirtualInterfaces
);
157 if (interface
!= NULL
) {
158 CFArrayAppendValue(*interfaces
, interface
);
159 CFRelease(interface
);
165 _SCBondInterfaceSetMode(SCBondInterfaceRef bond
, CFNumberRef mode
);
169 CFMutableArrayRef bonds
;
170 SCPreferencesRef ni_prefs
;
171 SCPreferencesRef prefs
;
172 } addContext
, *addContextRef
;
176 add_configured_interface(const void *key
, const void *value
, void *context
)
178 SCBondInterfaceRef bond
;
179 CFStringRef bond_if
= (CFStringRef
)key
;
180 CFDictionaryRef bond_info
= (CFDictionaryRef
)value
;
181 CFDictionaryRef bond_options
;
183 CFArrayRef interfaces
;
184 SCNetworkInterfacePrivateRef interfacePrivate
;
185 CFMutableArrayRef members
= NULL
;
187 addContextRef myContext
= (addContextRef
)context
;
191 // create the bond interface
192 bond
= (SCBondInterfaceRef
)_SCBondInterfaceCreatePrivate(NULL
, bond_if
);
194 // add member interfaces
195 interfaces
= CFDictionaryGetValue(bond_info
, kSCPropVirtualNetworkInterfacesBondInterfaces
);
196 n
= isA_CFArray(interfaces
) ? CFArrayGetCount(interfaces
) : 0;
197 for (i
= 0; i
< n
; i
++) {
200 member
= CFArrayGetValueAtIndex(interfaces
, i
);
201 if (isA_CFString(member
)) {
202 add_interface(&members
, member
, myContext
->ni_prefs
);
205 if (members
!= NULL
) {
206 __SCBondInterfaceSetMemberInterfaces(bond
, members
);
211 name
= CFDictionaryGetValue(bond_info
, kSCPropUserDefinedName
);
212 if (isA_CFString(name
)) {
213 SCBondInterfaceSetLocalizedDisplayName(bond
, name
);
217 bond_options
= CFDictionaryGetValue(bond_info
, kSCPropVirtualNetworkInterfacesBondOptions
);
218 if (isA_CFDictionary(bond_options
)) {
219 SCBondInterfaceSetOptions(bond
, bond_options
);
223 mode
= CFDictionaryGetValue(bond_info
, kSCPropVirtualNetworkInterfacesBondMode
);
224 _SCBondInterfaceSetMode(bond
, isA_CFNumber(mode
));
226 // estabish link to the stored configuration
227 interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
228 interfacePrivate
->prefs
= CFRetain(myContext
->prefs
);
230 CFArrayAppendValue(myContext
->bonds
, bond
);
239 #pragma mark SCBondInterface APIs
242 static __inline__
void
243 my_CFDictionaryApplyFunction(CFDictionaryRef theDict
,
244 CFDictionaryApplierFunction applier
,
247 CFAllocatorRef myAllocator
;
248 CFDictionaryRef myDict
;
250 myAllocator
= CFGetAllocator(theDict
);
251 myDict
= CFDictionaryCreateCopy(myAllocator
, theDict
);
252 CFDictionaryApplyFunction(myDict
, applier
, context
);
259 SCBondInterfaceCopyAll(SCPreferencesRef prefs
)
262 CFDictionaryRef dict
;
263 SCPreferencesRef ni_prefs
;
266 if ((prefs
== NULL
) ||
267 (__SCPreferencesUsingDefaultPrefs(prefs
) == TRUE
)) {
271 ni_prefs
= __SCPreferencesCreateNIPrefsFromPrefs(prefs
);
274 context
.bonds
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
275 context
.prefs
= prefs
;
276 context
.ni_prefs
= ni_prefs
;
278 path
= CFStringCreateWithFormat(NULL
,
281 kSCPrefVirtualNetworkInterfaces
,
282 kSCNetworkInterfaceTypeBond
);
283 dict
= SCPreferencesPathGetValue(prefs
, path
);
285 if (isA_CFDictionary(dict
)) {
286 my_CFDictionaryApplyFunction(dict
, add_configured_interface
, &context
);
289 if (ni_prefs
!= NULL
) {
292 return context
.bonds
;
296 __private_extern__
void
297 __SCBondInterfaceListCollectMembers(CFArrayRef interfaces
, CFMutableSetRef set
)
302 n
= CFArrayGetCount(interfaces
);
303 for (i
= 0; i
< n
; i
++) {
304 SCBondInterfaceRef bondInterface
;
307 bondInterface
= CFArrayGetValueAtIndex(interfaces
, i
);
308 members
= SCBondInterfaceGetMemberInterfaces(bondInterface
);
309 if (members
!= NULL
) {
313 // exclude the member interfaces of this bond
314 n_members
= CFArrayGetCount(members
);
315 for (j
= 0; j
< n_members
; j
++) {
316 SCNetworkInterfaceRef member
;
318 member
= CFArrayGetValueAtIndex(members
, j
);
319 CFSetAddValue(set
, member
);
328 CFArrayRef
/* of SCNetworkInterfaceRef's */
329 SCBondInterfaceCopyAvailableMemberInterfaces(SCPreferencesRef prefs
)
331 CFMutableArrayRef available
;
332 CFMutableSetRef excluded
;
333 CFArrayRef interfaces
;
335 available
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
336 excluded
= CFSetCreateMutable (NULL
, 0, &kCFTypeSetCallBacks
);
338 // exclude Bond [member] interfaces
339 interfaces
= SCBondInterfaceCopyAll(prefs
);
340 if (interfaces
!= NULL
) {
341 __SCBondInterfaceListCollectMembers(interfaces
, excluded
);
342 CFRelease(interfaces
);
345 // exclude Bridge [member] interfaces
346 interfaces
= SCBridgeInterfaceCopyAll(prefs
);
347 if (interfaces
!= NULL
) {
348 __SCBridgeInterfaceListCollectMembers(interfaces
, excluded
);
349 CFRelease(interfaces
);
352 // exclude VLAN [physical] interfaces
353 interfaces
= SCVLANInterfaceCopyAll(prefs
);
354 if (interfaces
!= NULL
) {
358 n
= CFArrayGetCount(interfaces
);
359 for (i
= 0; i
< n
; i
++) {
360 SCVLANInterfaceRef vlanInterface
;
361 SCNetworkInterfaceRef physical
;
363 // exclude the physical interface of this VLAN
364 vlanInterface
= CFArrayGetValueAtIndex(interfaces
, i
);
365 physical
= SCVLANInterfaceGetPhysicalInterface(vlanInterface
);
366 CFSetAddValue(excluded
, physical
);
368 CFRelease(interfaces
);
371 // identify available interfaces
372 interfaces
= __SCNetworkInterfaceCopyAll_IONetworkInterface();
373 if (interfaces
!= NULL
) {
377 n
= CFArrayGetCount(interfaces
);
378 for (i
= 0; i
< n
; i
++) {
379 SCNetworkInterfaceRef interface
;
380 SCNetworkInterfacePrivateRef interfacePrivate
;
382 interface
= CFArrayGetValueAtIndex(interfaces
, i
);
383 interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
385 if (!interfacePrivate
->supportsBond
) {
386 // if this interface is not available
390 if (CFSetContainsValue(excluded
, interface
)) {
395 CFArrayAppendValue(available
, interface
);
397 CFRelease(interfaces
);
407 _SCBondInterfaceCopyActive(void)
409 struct ifaddrs
*ifap
;
412 CFMutableArrayRef bonds
= NULL
;
414 if (getifaddrs(&ifap
) == -1) {
416 SC_log(LOG_NOTICE
, "getifaddrs() failed: %s", strerror(errno
));
420 s
= inet_dgram_socket();
426 bonds
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
428 for (ifp
= ifap
; ifp
!= NULL
; ifp
= ifp
->ifa_next
) {
429 SCBondInterfaceRef bond
;
431 struct if_bond_status_req
*ibsr_p
;
432 struct if_data
*if_data
;
435 CFMutableArrayRef members
= NULL
;
437 if_data
= (struct if_data
*)ifp
->ifa_data
;
439 || ifp
->ifa_addr
->sa_family
!= AF_LINK
440 || if_data
->ifi_type
!= IFT_IEEE8023ADLAG
) {
444 ibsr_p
= if_bond_status_req_copy(s
, ifp
->ifa_name
);
445 if (ibsr_p
== NULL
) {
446 if (errno
== EBUSY
) {
450 SC_log(LOG_NOTICE
, "if_bond_status_req_copy(%s) failed: %s",
458 // create the bond interface
459 bond_if
= CFStringCreateWithCString(NULL
, ifp
->ifa_name
, kCFStringEncodingASCII
);
460 bond
= (SCBondInterfaceRef
)_SCBondInterfaceCreatePrivate(NULL
, bond_if
);
464 int_val
= ibsr_p
->ibsr_mode
;
465 mode
= CFNumberCreate(NULL
, kCFNumberIntType
, &int_val
);
466 assert(mode
!= NULL
);
467 _SCBondInterfaceSetMode(bond
, mode
);
470 // add member interfaces
471 if (ibsr_p
->ibsr_total
> 0) {
473 struct if_bond_status
* ibs_p
;
475 // iterate over each member interface
476 ibs_p
= (struct if_bond_status
*)ibsr_p
->ibsr_buffer
;
477 for (i
= 0; i
< ibsr_p
->ibsr_total
; i
++) {
480 member
= CFStringCreateWithCString(NULL
, ibs_p
[i
].ibs_if_name
, kCFStringEncodingASCII
);
481 add_interface(&members
, member
, NULL
);
487 if (members
!= NULL
) {
488 __SCBondInterfaceSetMemberInterfaces(bond
, members
);
493 CFArrayAppendValue(bonds
, bond
);
508 SCBondInterfaceCreate(SCPreferencesRef prefs
)
510 CFAllocatorRef allocator
;
511 SCBondInterfaceRef bond
= NULL
;
515 _SCErrorSet(kSCStatusInvalidArgument
);
519 allocator
= CFGetAllocator(prefs
);
521 // create a new bond using an unused interface name
522 for (i
= 0; bond
== NULL
; i
++) {
523 CFDictionaryRef dict
;
525 SCNetworkInterfacePrivateRef interfacePrivate
;
526 CFMutableDictionaryRef newDict
;
527 CFArrayRef newInterfaces
;
531 bond_if
= CFStringCreateWithFormat(allocator
, NULL
, CFSTR("bond%ld"), i
);
532 path
= CFStringCreateWithFormat(allocator
,
535 kSCPrefVirtualNetworkInterfaces
,
536 kSCNetworkInterfaceTypeBond
,
538 dict
= SCPreferencesPathGetValue(prefs
, path
);
540 // if bond interface name not available
546 // add the bond to the stored preferences
547 newDict
= CFDictionaryCreateMutable(allocator
,
549 &kCFTypeDictionaryKeyCallBacks
,
550 &kCFTypeDictionaryValueCallBacks
);
551 newInterfaces
= CFArrayCreate(allocator
, NULL
, 0, &kCFTypeArrayCallBacks
);
552 CFDictionaryAddValue(newDict
, kSCPropVirtualNetworkInterfacesBondInterfaces
, newInterfaces
);
553 CFRelease(newInterfaces
);
554 ok
= SCPreferencesPathSetValue(prefs
, path
, newDict
);
558 // if the bond could not be saved
563 // create the SCBondInterfaceRef
564 bond
= (SCBondInterfaceRef
)_SCBondInterfaceCreatePrivate(allocator
, bond_if
);
567 // estabish link to the stored configuration
568 interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
569 interfacePrivate
->prefs
= CFRetain(prefs
);
577 SCBondInterfaceRemove(SCBondInterfaceRef bond
)
580 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
584 if (!isA_SCBondInterface(bond
)) {
585 _SCErrorSet(kSCStatusInvalidArgument
);
589 if (interfacePrivate
->prefs
== NULL
) {
590 _SCErrorSet(kSCStatusInvalidArgument
);
594 bond_if
= SCNetworkInterfaceGetBSDName(bond
);
595 path
= CFStringCreateWithFormat(NULL
,
598 kSCPrefVirtualNetworkInterfaces
,
599 kSCNetworkInterfaceTypeBond
,
601 ok
= SCPreferencesPathRemoveValue(interfacePrivate
->prefs
, path
);
609 SCBondInterfaceGetMemberInterfaces(SCBondInterfaceRef bond
)
611 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
613 if (!isA_SCBondInterface(bond
)) {
614 _SCErrorSet(kSCStatusInvalidArgument
);
618 return interfacePrivate
->bond
.interfaces
;
623 SCBondInterfaceGetOptions(SCBondInterfaceRef bond
)
625 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
627 if (!isA_SCBondInterface(bond
)) {
628 _SCErrorSet(kSCStatusInvalidArgument
);
632 return interfacePrivate
->bond
.options
;
638 __SCBondInterfaceSetMemberInterfaces(SCBondInterfaceRef bond
, CFArrayRef members
)
641 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
643 CFMutableArrayRef newMembers
;
646 n
= (members
!= NULL
) ? CFArrayGetCount(members
) : 0;
648 // set member interfaces in the stored preferences
649 if (interfacePrivate
->prefs
!= NULL
) {
650 CFDictionaryRef dict
;
651 CFMutableDictionaryRef newDict
;
654 path
= CFStringCreateWithFormat(NULL
,
657 kSCPrefVirtualNetworkInterfaces
,
658 kSCNetworkInterfaceTypeBond
,
659 interfacePrivate
->entity_device
);
660 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
661 if (!isA_CFDictionary(dict
)) {
662 // if the prefs are confused
664 _SCErrorSet(kSCStatusFailed
);
668 newMembers
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
669 for (i
= 0; i
< n
; i
++) {
670 SCNetworkInterfaceRef interface
;
671 CFStringRef memberName
;
673 interface
= CFArrayGetValueAtIndex(members
, i
);
674 memberName
= SCNetworkInterfaceGetBSDName(interface
);
675 CFArrayAppendValue(newMembers
, memberName
);
678 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
679 CFDictionarySetValue(newDict
, kSCPropVirtualNetworkInterfacesBondInterfaces
, newMembers
);
680 CFRelease(newMembers
);
681 if (!CFEqual(dict
, newDict
)) {
682 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
689 newMembers
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
690 for (i
= 0; i
< n
; i
++) {
691 SCNetworkInterfaceRef member
;
692 SCNetworkInterfacePrivateRef newMember
;
694 member
= CFArrayGetValueAtIndex(members
, i
);
695 newMember
= __SCNetworkInterfaceCreateCopy(NULL
,
697 interfacePrivate
->prefs
,
698 interfacePrivate
->serviceID
);
699 CFArrayAppendValue(newMembers
, newMember
);
700 CFRelease(newMember
);
702 CFRelease(interfacePrivate
->bond
.interfaces
);
703 interfacePrivate
->bond
.interfaces
= newMembers
;
711 SCBondInterfaceSetMemberInterfaces(SCBondInterfaceRef bond
, CFArrayRef members
)
713 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
715 int sc_status
= kSCStatusOK
;
717 if (!isA_SCBondInterface(bond
)) {
718 _SCErrorSet(kSCStatusInvalidArgument
);
722 if ((members
!= NULL
) && !isA_CFArray(members
)) {
723 _SCErrorSet(kSCStatusInvalidArgument
);
727 if (interfacePrivate
->prefs
!= NULL
) {
728 CFArrayRef available
;
734 CFArrayRef services
= NULL
;
736 current
= SCBondInterfaceGetMemberInterfaces(bond
);
737 n_current
= (current
!= NULL
) ? CFArrayGetCount(current
) : 0;
739 available
= SCBondInterfaceCopyAvailableMemberInterfaces(interfacePrivate
->prefs
);
740 n_available
= (available
!= NULL
) ? CFArrayGetCount(available
) : 0;
742 n_members
= (members
!= NULL
) ? CFArrayGetCount(members
) : 0;
743 for (i
= 0; i
< n_members
; i
++) {
744 SCNetworkInterfaceRef member
;
746 member
= CFArrayGetValueAtIndex(members
, i
);
748 if ((current
!= NULL
) &&
749 CFArrayContainsValue(current
, CFRangeMake(0, n_current
), member
)) {
750 // current members are allowed
754 if ((available
!= NULL
) &&
755 CFArrayContainsValue(available
, CFRangeMake(0, n_available
), member
)) {
756 // available members are allowed but cannot be associated
757 // with any other network services.
759 if (services
== NULL
) {
760 services
= __SCNetworkServiceCopyAllEnabled(interfacePrivate
->prefs
);
762 if ((services
!= NULL
) &&
763 __SCNetworkServiceExistsForInterface(services
, member
)) {
764 sc_status
= kSCStatusKeyExists
;
772 // if member not allowed
773 sc_status
= kSCStatusInvalidArgument
;
777 if (available
!= NULL
) CFRelease(available
);
778 if (services
!= NULL
) CFRelease(services
);
781 if (sc_status
!= kSCStatusOK
) {
782 _SCErrorSet(sc_status
);
786 ok
= __SCBondInterfaceSetMemberInterfaces(bond
, members
);
792 SCBondInterfaceSetLocalizedDisplayName(SCBondInterfaceRef bond
, CFStringRef newName
)
794 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
797 if (!isA_SCBondInterface(bond
)) {
798 _SCErrorSet(kSCStatusInvalidArgument
);
802 if ((newName
!= NULL
) && !isA_CFString(newName
)) {
803 _SCErrorSet(kSCStatusInvalidArgument
);
807 // set name in the stored preferences
808 if (interfacePrivate
->prefs
!= NULL
) {
809 CFDictionaryRef dict
;
810 CFMutableDictionaryRef newDict
;
813 path
= CFStringCreateWithFormat(NULL
,
816 kSCPrefVirtualNetworkInterfaces
,
817 kSCNetworkInterfaceTypeBond
,
818 interfacePrivate
->entity_device
);
819 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
820 if (!isA_CFDictionary(dict
)) {
821 // if the prefs are confused
823 _SCErrorSet(kSCStatusFailed
);
827 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
828 if (newName
!= NULL
) {
829 CFDictionarySetValue(newDict
, kSCPropUserDefinedName
, newName
);
831 CFDictionaryRemoveValue(newDict
, kSCPropUserDefinedName
);
833 if (!CFEqual(dict
, newDict
)) {
834 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
840 // set name in the SCBondInterfaceRef
842 if (interfacePrivate
->localized_name
!= NULL
) {
843 CFRelease(interfacePrivate
->localized_name
);
844 interfacePrivate
->localized_name
= NULL
;
846 if (newName
!= NULL
) {
847 interfacePrivate
->localized_name
= CFStringCreateCopy(NULL
, newName
);
856 SCBondInterfaceSetOptions(SCBondInterfaceRef bond
, CFDictionaryRef newOptions
)
858 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
861 if (!isA_SCBondInterface(bond
)) {
862 _SCErrorSet(kSCStatusInvalidArgument
);
866 if ((newOptions
!= NULL
) && !isA_CFDictionary(newOptions
)) {
867 _SCErrorSet(kSCStatusInvalidArgument
);
871 // set options in the stored preferences
872 if (interfacePrivate
->prefs
!= NULL
) {
873 CFDictionaryRef dict
;
874 CFMutableDictionaryRef newDict
;
877 path
= CFStringCreateWithFormat(NULL
,
880 kSCPrefVirtualNetworkInterfaces
,
881 kSCNetworkInterfaceTypeBond
,
882 interfacePrivate
->entity_device
);
883 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
884 if (!isA_CFDictionary(dict
)) {
885 // if the prefs are confused
887 _SCErrorSet(kSCStatusFailed
);
891 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
892 if (newOptions
!= NULL
) {
893 CFDictionarySetValue(newDict
, kSCPropVirtualNetworkInterfacesBondOptions
, newOptions
);
895 CFDictionaryRemoveValue(newDict
, kSCPropVirtualNetworkInterfacesBondOptions
);
897 if (!CFEqual(dict
, newDict
)) {
898 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
904 // set options in the SCBondInterfaceRef
906 if (interfacePrivate
->bond
.options
!= NULL
) {
907 CFRelease(interfacePrivate
->bond
.options
);
908 interfacePrivate
->bond
.options
= NULL
;
910 if (newOptions
!= NULL
) {
911 interfacePrivate
->bond
.options
= CFDictionaryCreateCopy(NULL
, newOptions
);
920 _SCBondInterfaceSetMode(SCBondInterfaceRef bond
, CFNumberRef mode
)
922 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
923 Boolean needs_release
= FALSE
;
926 assert(bond
!= NULL
);
929 int mode_num
= IF_BOND_MODE_LACP
;
931 mode
= CFNumberCreate(NULL
, kCFNumberIntType
, &mode_num
);
932 needs_release
= TRUE
;
935 // set mode in the stored preferences
936 if (interfacePrivate
->prefs
!= NULL
) {
937 CFDictionaryRef dict
;
938 CFMutableDictionaryRef newDict
;
941 path
= CFStringCreateWithFormat(NULL
,
944 kSCPrefVirtualNetworkInterfaces
,
945 kSCNetworkInterfaceTypeBond
,
946 interfacePrivate
->entity_device
);
947 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
948 if (!isA_CFDictionary(dict
)) {
949 // if the prefs are confused
951 _SCErrorSet(kSCStatusFailed
);
955 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
956 CFDictionarySetValue(newDict
, kSCPropVirtualNetworkInterfacesBondMode
, mode
);
957 if (!CFEqual(dict
, newDict
)) {
958 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
966 if (interfacePrivate
->bond
.mode
!= NULL
) {
967 CFRelease(interfacePrivate
->bond
.mode
);
969 interfacePrivate
->bond
.mode
= mode
;
974 if (needs_release
) CFRelease(mode
);
979 SCBondInterfaceSetMode(SCBondInterfaceRef bond
, CFNumberRef mode
)
983 if (!isA_SCBondInterface(bond
) || !isA_CFNumber(mode
)) {
984 _SCErrorSet(kSCStatusInvalidArgument
);
988 if (CFNumberGetValue(mode
, kCFNumberIntType
, &mode_num
) == FALSE
) {
989 _SCErrorSet(kSCStatusInvalidArgument
);
994 case IF_BOND_MODE_LACP
:
995 case IF_BOND_MODE_STATIC
:
998 _SCErrorSet(kSCStatusInvalidArgument
);
1002 return (_SCBondInterfaceSetMode(bond
, mode
));
1006 SCBondInterfaceGetMode(SCBondInterfaceRef bond
)
1008 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
1010 if (!isA_SCBondInterface(bond
)) {
1011 _SCErrorSet(kSCStatusInvalidArgument
);
1014 return (interfacePrivate
->bond
.mode
);
1019 #pragma mark SCBondStatus APIs
1024 // base CFType information
1025 CFRuntimeBase cfBase
;
1028 SCBondInterfaceRef bond
;
1029 CFDictionaryRef status_bond
;
1031 // member interfaces and status
1032 CFArrayRef interfaces
; // of SCNetworkInterfaceRef's
1033 CFDictionaryRef status_interfaces
; // key = interface, val = interface status)
1035 } SCBondStatusPrivate
, * SCBondStatusPrivateRef
;
1038 const CFStringRef kSCBondStatusDeviceAggregationStatus
= CFSTR("AggregationStatus");
1039 const CFStringRef kSCBondStatusDeviceCollecting
= CFSTR("Collecting");
1040 const CFStringRef kSCBondStatusDeviceDistributing
= CFSTR("Distributing");
1043 static CFStringRef
__SCBondStatusCopyDescription (CFTypeRef cf
);
1044 static void __SCBondStatusDeallocate (CFTypeRef cf
);
1045 static Boolean
__SCBondStatusEqual (CFTypeRef cf1
, CFTypeRef cf2
);
1048 static const CFRuntimeClass __SCBondStatusClass
= {
1050 "BondStatus", // className
1053 __SCBondStatusDeallocate
, // dealloc
1054 __SCBondStatusEqual
, // equal
1056 NULL
, // copyFormattingDesc
1057 __SCBondStatusCopyDescription
// copyDebugDesc
1061 static CFTypeID __kSCBondStatusTypeID
= _kCFRuntimeNotATypeID
;
1064 static pthread_once_t bondStatus_init
= PTHREAD_ONCE_INIT
;
1068 __SCBondStatusCopyDescription(CFTypeRef cf
)
1070 CFAllocatorRef allocator
= CFGetAllocator(cf
);
1071 CFMutableStringRef result
;
1072 SCBondStatusPrivateRef statusPrivate
= (SCBondStatusPrivateRef
)cf
;
1074 result
= CFStringCreateMutable(allocator
, 0);
1075 CFStringAppendFormat(result
, NULL
, CFSTR("<SCBondStatus %p [%p]> {"), cf
, allocator
);
1076 CFStringAppendFormat(result
, NULL
, CFSTR(" bond = %@"), statusPrivate
->bond
);
1077 CFStringAppendFormat(result
, NULL
, CFSTR(", interface = %@"), statusPrivate
->status_bond
);
1078 CFStringAppendFormat(result
, NULL
, CFSTR(", members = %@"), statusPrivate
->status_interfaces
);
1079 CFStringAppendFormat(result
, NULL
, CFSTR(" }"));
1086 __SCBondStatusDeallocate(CFTypeRef cf
)
1088 SCBondStatusPrivateRef statusPrivate
= (SCBondStatusPrivateRef
)cf
;
1090 /* release resources */
1092 CFRelease(statusPrivate
->bond
);
1093 CFRelease(statusPrivate
->status_bond
);
1094 if (statusPrivate
->interfaces
!= NULL
) CFRelease(statusPrivate
->interfaces
);
1095 CFRelease(statusPrivate
->status_interfaces
);
1101 __SCBondStatusEqual(CFTypeRef cf1
, CFTypeRef cf2
)
1103 SCBondStatusPrivateRef status1
= (SCBondStatusPrivateRef
)cf1
;
1104 SCBondStatusPrivateRef status2
= (SCBondStatusPrivateRef
)cf2
;
1106 if (status1
== status2
)
1109 if (!CFEqual(status1
->bond
, status2
->bond
))
1110 return FALSE
; // if not the same bond
1112 if (!CFEqual(status1
->status_bond
, status2
->status_bond
))
1113 return FALSE
; // if not the same interface status
1115 if (!CFEqual(status1
->status_interfaces
, status2
->status_interfaces
))
1116 return FALSE
; // if not the same status of the member interfaces
1123 __SCBondStatusInitialize(void)
1125 __kSCBondStatusTypeID
= _CFRuntimeRegisterClass(&__SCBondStatusClass
);
1130 static SCBondStatusRef
1131 __SCBondStatusCreatePrivate(CFAllocatorRef allocator
,
1132 SCBondInterfaceRef bond
,
1133 CFDictionaryRef status_bond
,
1134 CFDictionaryRef status_interfaces
)
1136 SCBondStatusPrivateRef statusPrivate
;
1139 /* initialize runtime */
1140 pthread_once(&bondStatus_init
, __SCBondStatusInitialize
);
1143 size
= sizeof(SCBondStatusPrivate
) - sizeof(CFRuntimeBase
);
1144 statusPrivate
= (SCBondStatusPrivateRef
)_CFRuntimeCreateInstance(allocator
,
1145 __kSCBondStatusTypeID
,
1148 if (statusPrivate
== NULL
) {
1152 /* establish the bond status */
1154 statusPrivate
->bond
= CFRetain(bond
);
1155 statusPrivate
->status_bond
= CFDictionaryCreateCopy(NULL
, status_bond
);
1157 statusPrivate
->interfaces
= NULL
;
1158 statusPrivate
->status_interfaces
= CFDictionaryCreateCopy(NULL
, status_interfaces
);
1160 return (SCBondStatusRef
)statusPrivate
;
1164 static __inline__ CFTypeRef
1165 isA_SCBondStatus(CFTypeRef obj
)
1167 return (isA_CFType(obj
, SCBondStatusGetTypeID()));
1172 SCBondStatusGetTypeID()
1174 pthread_once(&bondStatus_init
, __SCBondStatusInitialize
); /* initialize runtime */
1175 return __kSCBondStatusTypeID
;
1182 CFArrayRef
/* of SCNetworkInterfaceRef's */
1183 SCBondStatusGetMemberInterfaces(SCBondStatusRef bondStatus
)
1185 SCBondStatusPrivateRef statusPrivate
= (SCBondStatusPrivateRef
)bondStatus
;
1187 if (!isA_SCBondStatus(bondStatus
)) {
1191 if (statusPrivate
->interfaces
== NULL
) {
1192 const void * keys_q
[N_QUICK
];
1193 const void ** keys
= keys_q
;
1196 n
= CFDictionaryGetCount(statusPrivate
->status_interfaces
);
1197 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
1198 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
1200 CFDictionaryGetKeysAndValues(statusPrivate
->status_interfaces
, keys
, NULL
);
1201 statusPrivate
->interfaces
= CFArrayCreate(NULL
, keys
, n
, &kCFTypeArrayCallBacks
);
1202 if (keys
!= keys_q
) {
1203 CFAllocatorDeallocate(NULL
, keys
);
1207 return statusPrivate
->interfaces
;
1212 SCBondStatusGetInterfaceStatus(SCBondStatusRef bondStatus
, SCNetworkInterfaceRef interface
)
1214 CFDictionaryRef status
= NULL
;
1215 SCBondStatusPrivateRef statusPrivate
= (SCBondStatusPrivateRef
)bondStatus
;
1217 if (!isA_SCBondStatus(bondStatus
)) {
1221 if (interface
== NULL
) {
1222 // return status of the bond
1223 status
= statusPrivate
->status_bond
;
1225 // return status of the member interface
1226 status
= CFDictionaryGetValue(statusPrivate
->status_interfaces
, interface
);
1234 SCBondInterfaceCopyStatus(SCBondInterfaceRef bond
)
1239 struct if_bond_status_req
*ibsr_p
= NULL
;
1240 char if_name
[IFNAMSIZ
];
1244 struct if_bond_status
*scan_p
;
1245 SCBondStatusRef status
= NULL
;
1246 CFMutableDictionaryRef status_bond
;
1247 CFMutableDictionaryRef status_interfaces
;
1249 if (!isA_SCBondInterface(bond
)) {
1250 _SCErrorSet(kSCStatusInvalidArgument
);
1254 s
= inet_dgram_socket();
1260 _SC_cfstring_to_cstring(SCNetworkInterfaceGetBSDName(bond
),
1263 kCFStringEncodingASCII
);
1264 if (siocgifmedia(s
, if_name
, &bond_if_status
, &bond_if_active
) == -1) {
1271 SC_log(LOG_NOTICE
, "siocgifmedia(%s) failed: %s",
1277 ibsr_p
= if_bond_status_req_copy(s
, if_name
);
1278 if (ibsr_p
== NULL
) {
1283 status_bond
= CFDictionaryCreateMutable(NULL
,
1285 &kCFTypeDictionaryKeyCallBacks
,
1286 &kCFTypeDictionaryValueCallBacks
);
1288 status_interfaces
= CFDictionaryCreateMutable(NULL
,
1290 &kCFTypeDictionaryKeyCallBacks
,
1291 &kCFTypeDictionaryValueCallBacks
);
1292 n
= ibsr_p
->ibsr_total
;
1293 for (i
= 0, scan_p
= (struct if_bond_status
*)ibsr_p
->ibsr_buffer
; i
< n
; i
++, scan_p
++) {
1295 int distributing
= 0;
1296 SCNetworkInterfaceRef interface
;
1297 CFStringRef interface_name
;
1298 struct if_bond_partner_state
* ps
;
1299 CFMutableDictionaryRef status_interface
;
1302 ps
= &scan_p
->ibs_partner_state
;
1304 if (lacp_actor_partner_state_in_sync(scan_p
->ibs_state
)) {
1306 status_val
= kSCBondStatusOK
;
1307 if (lacp_actor_partner_state_in_sync(ps
->ibps_state
)) {
1308 /* partner is also in-sync */
1309 if (lacp_actor_partner_state_collecting(scan_p
->ibs_state
)
1310 && lacp_actor_partner_state_distributing(ps
->ibps_state
)) {
1311 /* we're able to collect (receive) frames */
1314 if (lacp_actor_partner_state_distributing(scan_p
->ibs_state
)
1315 && lacp_actor_partner_state_collecting(ps
->ibps_state
)) {
1316 /* we're able to distribute (transmit) frames */
1323 static lacp_system zeroes
= { {0, 0, 0, 0, 0, 0}};
1325 if (siocgifmedia(s
, scan_p
->ibs_if_name
, &status
, &active
) == -1) {
1331 SC_log(LOG_NOTICE
, "siocgifmedia(%s) failed: %s",
1337 if (((status
& IFM_AVALID
) == 0) ||
1338 ((status
& IFM_ACTIVE
) == 0) ||
1339 ((active
& IFM_FDX
) == 0)) {
1340 /* link down or not full-duplex */
1341 status_val
= kSCBondStatusLinkInvalid
;
1342 } else if ((ps
->ibps_system_priority
== 0) &&
1343 (bcmp(&zeroes
, &ps
->ibps_system
, sizeof(zeroes
)) == 0)) {
1344 /* no one on the other end of the link */
1345 status_val
= kSCBondStatusNoPartner
;
1346 } else if (active
!= bond_if_active
) {
1347 /* the link speed was different */
1348 status_val
= kSCBondStatusLinkInvalid
;
1350 /* partner is not in the active group */
1351 status_val
= kSCBondStatusNotInActiveGroup
;
1356 strlcpy(if_name
, scan_p
->ibs_if_name
, sizeof(if_name
));
1357 interface_name
= CFStringCreateWithCString(NULL
, if_name
, kCFStringEncodingASCII
);
1358 interface
= _SCNetworkInterfaceCreateWithBSDName(NULL
, interface_name
,
1359 kIncludeNoVirtualInterfaces
);
1360 CFRelease(interface_name
);
1363 status_interface
= CFDictionaryCreateMutable(NULL
,
1365 &kCFTypeDictionaryKeyCallBacks
,
1366 &kCFTypeDictionaryValueCallBacks
);
1367 num
= CFNumberCreate(NULL
, kCFNumberIntType
, &status_val
);
1368 CFDictionarySetValue(status_interface
, kSCBondStatusDeviceAggregationStatus
, num
);
1370 num
= CFNumberCreate(NULL
, kCFNumberIntType
, &collecting
);
1371 CFDictionarySetValue(status_interface
, kSCBondStatusDeviceCollecting
, num
);
1373 num
= CFNumberCreate(NULL
, kCFNumberIntType
, &distributing
);
1374 CFDictionarySetValue(status_interface
, kSCBondStatusDeviceDistributing
, num
);
1377 CFDictionarySetValue(status_interfaces
, interface
, status_interface
);
1378 CFRelease(interface
);
1379 CFRelease(status_interface
);
1382 status
= __SCBondStatusCreatePrivate(NULL
, bond
, status_bond
, status_interfaces
);
1383 CFRelease(status_bond
);
1384 CFRelease(status_interfaces
);
1391 if (ibsr_p
!= NULL
) {
1394 return (SCBondStatusRef
)status
;
1399 #pragma mark SCBondInterface management
1403 __bond_set_mode(int s
, CFStringRef bond_if
, CFNumberRef mode
)
1405 struct if_bond_req breq
;
1409 mode_num
= IF_BOND_MODE_LACP
;
1411 CFNumberGetValue(mode
, kCFNumberIntType
, &mode_num
);
1415 bzero(&ifr
, sizeof(ifr
));
1416 (void) _SC_cfstring_to_cstring(bond_if
,
1418 sizeof(ifr
.ifr_name
),
1419 kCFStringEncodingASCII
);
1420 ifr
.ifr_data
= (caddr_t
)&breq
;
1421 bzero(&breq
, sizeof(breq
));
1422 breq
.ibr_op
= IF_BOND_OP_SET_MODE
;
1423 breq
.ibr_ibru
.ibru_int_val
= mode_num
;
1424 if (ioctl(s
, SIOCSIFBOND
, (caddr_t
)&ifr
) == -1) {
1426 SC_log(LOG_ERR
, "could not set mode to %@ on bond \"%@\": %s",
1437 __bond_add_interface(int s
, CFStringRef bond_if
, CFStringRef interface_if
)
1439 struct if_bond_req breq
;
1443 bzero(&ifr
, sizeof(ifr
));
1444 (void) _SC_cfstring_to_cstring(bond_if
,
1446 sizeof(ifr
.ifr_name
),
1447 kCFStringEncodingASCII
);
1448 ifr
.ifr_data
= (caddr_t
)&breq
;
1451 bzero(&breq
, sizeof(breq
));
1452 breq
.ibr_op
= IF_BOND_OP_ADD_INTERFACE
;
1453 (void) _SC_cfstring_to_cstring(interface_if
,
1454 breq
.ibr_ibru
.ibru_if_name
,
1455 sizeof(breq
.ibr_ibru
.ibru_if_name
),
1456 kCFStringEncodingASCII
);
1458 // add new bond member
1459 if (ioctl(s
, SIOCSIFBOND
, (caddr_t
)&ifr
) == -1) {
1461 SC_log(LOG_ERR
, "could not add interface \"%@\" to bond \"%@\": %s",
1473 __bond_remove_interface(int s
, CFStringRef bond_if
, CFStringRef interface_if
)
1475 struct if_bond_req breq
;
1479 bzero(&ifr
, sizeof(ifr
));
1480 (void) _SC_cfstring_to_cstring(bond_if
,
1482 sizeof(ifr
.ifr_name
),
1483 kCFStringEncodingASCII
);
1484 ifr
.ifr_data
= (caddr_t
)&breq
;
1486 // bond member to remove
1487 bzero(&breq
, sizeof(breq
));
1488 breq
.ibr_op
= IF_BOND_OP_REMOVE_INTERFACE
;
1489 (void) _SC_cfstring_to_cstring(interface_if
,
1490 breq
.ibr_ibru
.ibru_if_name
,
1491 sizeof(breq
.ibr_ibru
.ibru_if_name
),
1492 kCFStringEncodingASCII
);
1494 // remove bond member
1495 if (ioctl(s
, SIOCSIFBOND
, (caddr_t
)&ifr
) == -1) {
1497 SC_log(LOG_ERR
, "could not remove interface \"%@\" from bond \"%@\": %s",
1509 _SCBondInterfaceUpdateConfiguration(SCPreferencesRef prefs
)
1511 CFArrayRef active
= NULL
;
1512 CFArrayRef config
= NULL
;
1519 if (prefs
== NULL
) {
1520 _SCErrorSet(kSCStatusInvalidArgument
);
1524 /* configured Bonds */
1525 config
= SCBondInterfaceCopyAll(prefs
);
1526 nConfig
= (config
!= NULL
) ? CFArrayGetCount(config
) : 0;
1529 active
= _SCBondInterfaceCopyActive();
1530 nActive
= (active
!= NULL
) ? CFArrayGetCount(active
) : 0;
1533 * remove any no-longer-configured bond interfaces and
1534 * any devices associated with a bond that are no longer
1535 * associated with a bond.
1537 for (i
= 0; i
< nActive
; i
++) {
1538 SCBondInterfaceRef a_bond
;
1539 CFStringRef a_bond_if
;
1541 Boolean found
= FALSE
;
1543 a_bond
= CFArrayGetValueAtIndex(active
, i
);
1544 a_bond_if
= SCNetworkInterfaceGetBSDName(a_bond
);
1546 for (j
= 0; j
< nConfig
; j
++) {
1547 SCBondInterfaceRef c_bond
;
1548 CFStringRef c_bond_if
;
1550 c_bond
= CFArrayGetValueAtIndex(config
, j
);
1551 c_bond_if
= SCNetworkInterfaceGetBSDName(c_bond
);
1553 if (CFEqual(a_bond_if
, c_bond_if
)) {
1555 CFArrayRef a_bond_interfaces
;
1557 CFArrayRef c_bond_interfaces
;
1560 c_bond_interfaces
= SCBondInterfaceGetMemberInterfaces(c_bond
);
1561 c_count
= (c_bond_interfaces
!= NULL
) ? CFArrayGetCount(c_bond_interfaces
) : 0;
1563 a_bond_interfaces
= SCBondInterfaceGetMemberInterfaces(a_bond
);
1564 a_count
= (a_bond_interfaces
!= NULL
) ? CFArrayGetCount(a_bond_interfaces
) : 0;
1566 for (a
= 0; a
< a_count
; a
++) {
1567 SCNetworkInterfaceRef a_interface
;
1568 CFStringRef a_interface_if
;
1570 a_interface
= CFArrayGetValueAtIndex(a_bond_interfaces
, a
);
1571 if ((c_count
== 0) ||
1572 !CFArrayContainsValue(c_bond_interfaces
,
1573 CFRangeMake(0, c_count
),
1576 * if this device is no longer part
1580 s
= inet_dgram_socket();
1588 a_interface_if
= SCNetworkInterfaceGetBSDName(a_interface
);
1589 if (!__bond_remove_interface(s
, a_bond_if
, a_interface_if
)) {
1602 * if this interface is no longer configured
1605 s
= inet_dgram_socket();
1613 if (!__destroyInterface(s
, a_bond_if
)) {
1621 * add any newly-configured bond interfaces and add any
1622 * devices that should now be associated with the bond.
1624 for (i
= 0; i
< nConfig
; i
++) {
1625 CFNumberRef c_bond_mode
;
1626 SCBondInterfaceRef c_bond
;
1627 CFArrayRef c_bond_interfaces
;
1628 CFStringRef c_bond_if
;
1630 Boolean found
= FALSE
;
1633 c_bond
= CFArrayGetValueAtIndex(config
, i
);
1634 c_bond_if
= SCNetworkInterfaceGetBSDName(c_bond
);
1635 c_bond_interfaces
= SCBondInterfaceGetMemberInterfaces(c_bond
);
1636 c_bond_mode
= SCBondInterfaceGetMode(c_bond
);
1637 c_count
= (c_bond_interfaces
!= NULL
) ? CFArrayGetCount(c_bond_interfaces
) : 0;
1639 for (j
= 0; j
< nActive
; j
++) {
1640 SCBondInterfaceRef a_bond
;
1641 CFArrayRef a_bond_interfaces
;
1642 CFNumberRef a_bond_mode
;
1643 CFStringRef a_bond_if
;
1646 a_bond
= CFArrayGetValueAtIndex(active
, j
);
1647 a_bond_if
= SCNetworkInterfaceGetBSDName(a_bond
);
1648 a_bond_interfaces
= SCBondInterfaceGetMemberInterfaces(a_bond
);
1649 a_bond_mode
= SCBondInterfaceGetMode(a_bond
);
1650 a_count
= (a_bond_interfaces
!= NULL
) ? CFArrayGetCount(a_bond_interfaces
) : 0;
1652 if (CFEqual(c_bond_if
, a_bond_if
)) {
1654 Boolean if_list_change
= FALSE
;
1655 Boolean mode_change
= FALSE
;
1659 if (!_SC_CFEqual(a_bond_mode
, c_bond_mode
)) {
1663 if (!_SC_CFEqual(c_bond_interfaces
, a_bond_interfaces
)) {
1664 if_list_change
= TRUE
;
1666 if (!mode_change
&& !if_list_change
) {
1667 break; // if no change
1670 s
= inet_dgram_socket();
1678 __bond_set_mode(s
, a_bond_if
, c_bond_mode
);
1680 if (!if_list_change
) {
1681 break; // no if list changes
1685 * ensure that the first device of the bond matches, if
1686 * not then we remove all current devices and add them
1687 * back in the preferred order.
1689 if ((c_count
> 0) &&
1691 !CFEqual(CFArrayGetValueAtIndex(c_bond_interfaces
, 0),
1692 CFArrayGetValueAtIndex(a_bond_interfaces
, 0))) {
1695 for (a
= 0; a
< a_count
; a
++) {
1696 SCNetworkInterfaceRef a_interface
;
1697 CFStringRef a_interface_if
;
1699 a_interface
= CFArrayGetValueAtIndex(a_bond_interfaces
, a
);
1700 if (!CFArrayContainsValue(c_bond_interfaces
,
1701 CFRangeMake(0, c_count
),
1703 continue; // if already removed
1706 a_interface_if
= SCNetworkInterfaceGetBSDName(a_interface
);
1707 if (!__bond_remove_interface(s
, a_bond_if
, a_interface_if
)) {
1712 a_count
= 0; // all active devices have been removed
1716 * add any devices which are not currently associated
1717 * with the bond interface.
1719 for (c
= 0; c
< c_count
; c
++) {
1720 SCNetworkInterfaceRef c_interface
;
1721 SCNetworkInterfacePrivateRef c_interfacePrivate
;
1722 CFStringRef c_interface_if
;
1724 c_interface
= CFArrayGetValueAtIndex(c_bond_interfaces
, c
);
1725 if ((a_count
== 0) ||
1726 !CFArrayContainsValue(a_bond_interfaces
,
1727 CFRangeMake(0, a_count
),
1730 * check if this member interface can be added to a bond.
1732 c_interfacePrivate
= (SCNetworkInterfacePrivateRef
)c_interface
;
1733 if (!c_interfacePrivate
->supportsBond
) {
1734 // if member not supported
1739 * if this member interface is not currently part of the bond.
1741 c_interface_if
= SCNetworkInterfaceGetBSDName(c_interface
);
1742 if (!__bond_add_interface(s
, c_bond_if
, c_interface_if
)) {
1743 // if member could not be added
1757 s
= inet_dgram_socket();
1766 * establish the new bond interface.
1768 if (!__createInterface(s
, c_bond_if
)) {
1775 __bond_set_mode(s
, c_bond_if
, c_bond_mode
);
1778 * add the member interfaces
1780 for (c
= 0; c
< c_count
; c
++) {
1781 SCNetworkInterfaceRef c_interface
;
1782 SCNetworkInterfacePrivateRef c_interfacePrivate
;
1783 CFStringRef c_interface_if
;
1785 c_interface
= CFArrayGetValueAtIndex(c_bond_interfaces
, c
);
1786 c_interfacePrivate
= (SCNetworkInterfacePrivateRef
)c_interface
;
1787 if (!c_interfacePrivate
->supportsBond
) {
1788 // if member not supported
1792 c_interface_if
= SCNetworkInterfaceGetBSDName(c_interface
);
1793 if (!__bond_add_interface(s
, c_bond_if
, c_interface_if
)) {
1794 // if member could not be added
1804 if (active
!= NULL
) CFRelease(active
);
1805 if (config
!= NULL
) CFRelease(config
);
1806 if (s
!= -1) (void) close(s
);