2 * Copyright (c) 2004-2019 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 "SCNetworkConfigurationInternal.h"
39 #include "SCPreferencesInternal.h"
44 #include <sys/types.h>
45 #include <sys/ioctl.h>
46 #include <sys/socket.h>
47 #include <sys/sysctl.h>
48 #include <net/ethernet.h>
49 #define KERNEL_PRIVATE
51 #include <net/if_var.h>
53 #include <net/if_bond_var.h>
54 #include <net/if_types.h>
55 #include <net/if_media.h>
56 #include <net/route.h>
58 /* ---------- Bond support ---------- */
65 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
67 SC_log(LOG_ERR
, "socket() failed: %s", strerror(errno
));
74 siocgifxmedia(int s
, const char * ifname
, int * status
, int * active
)
76 struct ifmediareq ifmr
;
80 memset(&ifmr
, 0, sizeof(ifmr
));
81 strlcpy(ifmr
.ifm_name
, ifname
, sizeof(ifmr
.ifm_name
));
82 if (ioctl(s
, SIOCGIFXMEDIA
, &ifmr
) == -1) {
85 if (ifmr
.ifm_count
!= 0) {
86 *status
= ifmr
.ifm_status
;
87 *active
= ifmr
.ifm_active
;
92 static struct if_bond_status_req
*
93 if_bond_status_req_copy(int s
, const char * ifname
)
96 struct if_bond_req ibr
;
97 struct if_bond_status_req
* ibsr_p
;
100 memset(&ifr
, 0, sizeof(ifr
));
101 strlcpy(ifr
.ifr_name
, ifname
, sizeof(ifr
.ifr_name
));
102 memset((char *)&ibr
, 0, sizeof(ibr
));
103 ibr
.ibr_op
= IF_BOND_OP_GET_STATUS
;
104 ibsr_p
= &ibr
.ibr_ibru
.ibru_status
;
105 ibsr_p
->ibsr_version
= IF_BOND_STATUS_REQ_VERSION
;
106 ifr
.ifr_data
= (caddr_t
)&ibr
;
108 /* how many of them are there? */
109 if (ioctl(s
, SIOCGIFBOND
, (caddr_t
)&ifr
) == -1) {
112 buf
= malloc(sizeof(struct if_bond_status
) * ibsr_p
->ibsr_total
+ sizeof(*ibsr_p
));
116 if (ibsr_p
->ibsr_total
== 0) {
119 ibsr_p
->ibsr_count
= ibsr_p
->ibsr_total
;
120 ibsr_p
->ibsr_buffer
= buf
+ sizeof(*ibsr_p
);
123 if (ioctl(s
, SIOCGIFBOND
, (caddr_t
)&ifr
) == -1) {
127 (*(struct if_bond_status_req
*)buf
) = *ibsr_p
;
128 return ((struct if_bond_status_req
*)buf
);
139 add_interface(CFMutableArrayRef
*interfaces
, CFStringRef if_name
, SCPreferencesRef ni_prefs
)
141 SCNetworkInterfaceRef interface
= NULL
;
143 if (*interfaces
== NULL
) {
144 *interfaces
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
146 if (ni_prefs
!= NULL
) {
147 interface
= __SCNetworkInterfaceCreateWithNIPreferencesUsingBSDName(NULL
, ni_prefs
, if_name
);
149 if (interface
== NULL
) {
150 interface
= _SCNetworkInterfaceCreateWithBSDName(NULL
, if_name
,
151 kIncludeNoVirtualInterfaces
);
154 if (interface
!= NULL
) {
155 CFArrayAppendValue(*interfaces
, interface
);
156 CFRelease(interface
);
162 _SCBondInterfaceSetMode(SCBondInterfaceRef bond
, CFNumberRef mode
);
166 CFMutableArrayRef bonds
;
167 SCPreferencesRef ni_prefs
;
168 SCPreferencesRef prefs
;
169 } addContext
, *addContextRef
;
173 add_configured_interface(const void *key
, const void *value
, void *context
)
175 SCBondInterfaceRef bond
;
176 CFStringRef bond_if
= (CFStringRef
)key
;
177 CFDictionaryRef bond_info
= (CFDictionaryRef
)value
;
178 CFDictionaryRef bond_options
;
180 CFArrayRef interfaces
;
181 SCNetworkInterfacePrivateRef interfacePrivate
;
182 CFMutableArrayRef members
= NULL
;
184 addContextRef myContext
= (addContextRef
)context
;
188 // create the bond interface
189 bond
= (SCBondInterfaceRef
)_SCBondInterfaceCreatePrivate(NULL
, bond_if
);
191 // add member interfaces
192 interfaces
= CFDictionaryGetValue(bond_info
, kSCPropVirtualNetworkInterfacesBondInterfaces
);
193 n
= isA_CFArray(interfaces
) ? CFArrayGetCount(interfaces
) : 0;
194 for (i
= 0; i
< n
; i
++) {
197 member
= CFArrayGetValueAtIndex(interfaces
, i
);
198 if (isA_CFString(member
)) {
199 add_interface(&members
, member
, myContext
->ni_prefs
);
202 if (members
!= NULL
) {
203 __SCBondInterfaceSetMemberInterfaces(bond
, members
);
208 name
= CFDictionaryGetValue(bond_info
, kSCPropUserDefinedName
);
209 if (isA_CFString(name
)) {
210 SCBondInterfaceSetLocalizedDisplayName(bond
, name
);
214 bond_options
= CFDictionaryGetValue(bond_info
, kSCPropVirtualNetworkInterfacesBondOptions
);
215 if (isA_CFDictionary(bond_options
)) {
216 SCBondInterfaceSetOptions(bond
, bond_options
);
220 mode
= CFDictionaryGetValue(bond_info
, kSCPropVirtualNetworkInterfacesBondMode
);
221 _SCBondInterfaceSetMode(bond
, isA_CFNumber(mode
));
223 // estabish link to the stored configuration
224 interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
225 interfacePrivate
->prefs
= CFRetain(myContext
->prefs
);
227 CFArrayAppendValue(myContext
->bonds
, bond
);
236 #pragma mark SCBondInterface APIs
239 static __inline__
void
240 my_CFDictionaryApplyFunction(CFDictionaryRef theDict
,
241 CFDictionaryApplierFunction applier
,
244 CFAllocatorRef myAllocator
;
245 CFDictionaryRef myDict
;
247 myAllocator
= CFGetAllocator(theDict
);
248 myDict
= CFDictionaryCreateCopy(myAllocator
, theDict
);
249 CFDictionaryApplyFunction(myDict
, applier
, context
);
256 SCBondInterfaceCopyAll(SCPreferencesRef prefs
)
259 CFDictionaryRef dict
;
260 SCPreferencesRef ni_prefs
;
263 if (__SCPreferencesUsingDefaultPrefs(prefs
)) {
266 ni_prefs
= __SCPreferencesCreateNIPrefsFromPrefs(prefs
);
269 context
.bonds
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
270 context
.prefs
= prefs
;
271 context
.ni_prefs
= ni_prefs
;
273 path
= CFStringCreateWithFormat(NULL
,
276 kSCPrefVirtualNetworkInterfaces
,
277 kSCNetworkInterfaceTypeBond
);
278 dict
= SCPreferencesPathGetValue(prefs
, path
);
280 if (isA_CFDictionary(dict
)) {
281 my_CFDictionaryApplyFunction(dict
, add_configured_interface
, &context
);
284 if (ni_prefs
!= NULL
) {
287 return context
.bonds
;
291 __private_extern__
void
292 __SCBondInterfaceListCollectMembers(CFArrayRef interfaces
, CFMutableSetRef set
)
297 n
= CFArrayGetCount(interfaces
);
298 for (i
= 0; i
< n
; i
++) {
299 SCBondInterfaceRef bondInterface
;
302 bondInterface
= CFArrayGetValueAtIndex(interfaces
, i
);
303 members
= SCBondInterfaceGetMemberInterfaces(bondInterface
);
304 if (members
!= NULL
) {
308 // exclude the member interfaces of this bond
309 n_members
= CFArrayGetCount(members
);
310 for (j
= 0; j
< n_members
; j
++) {
311 SCNetworkInterfaceRef member
;
313 member
= CFArrayGetValueAtIndex(members
, j
);
314 CFSetAddValue(set
, member
);
323 CFArrayRef
/* of SCNetworkInterfaceRef's */
324 SCBondInterfaceCopyAvailableMemberInterfaces(SCPreferencesRef prefs
)
326 CFMutableArrayRef available
;
327 CFMutableSetRef excluded
;
328 CFArrayRef interfaces
;
330 available
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
331 excluded
= CFSetCreateMutable (NULL
, 0, &kCFTypeSetCallBacks
);
333 // exclude Bond [member] interfaces
334 interfaces
= SCBondInterfaceCopyAll(prefs
);
335 if (interfaces
!= NULL
) {
336 __SCBondInterfaceListCollectMembers(interfaces
, excluded
);
337 CFRelease(interfaces
);
340 // exclude Bridge [member] interfaces
341 interfaces
= SCBridgeInterfaceCopyAll(prefs
);
342 if (interfaces
!= NULL
) {
343 __SCBridgeInterfaceListCollectMembers(interfaces
, excluded
);
344 CFRelease(interfaces
);
347 // exclude VLAN [physical] interfaces
348 interfaces
= SCVLANInterfaceCopyAll(prefs
);
349 if (interfaces
!= NULL
) {
353 n
= CFArrayGetCount(interfaces
);
354 for (i
= 0; i
< n
; i
++) {
355 SCVLANInterfaceRef vlanInterface
;
356 SCNetworkInterfaceRef physical
;
358 // exclude the physical interface of this VLAN
359 vlanInterface
= CFArrayGetValueAtIndex(interfaces
, i
);
360 physical
= SCVLANInterfaceGetPhysicalInterface(vlanInterface
);
361 CFSetAddValue(excluded
, physical
);
363 CFRelease(interfaces
);
366 // identify available interfaces
367 interfaces
= __SCNetworkInterfaceCopyAll_IONetworkInterface(FALSE
);
368 if (interfaces
!= NULL
) {
372 n
= CFArrayGetCount(interfaces
);
373 for (i
= 0; i
< n
; i
++) {
374 SCNetworkInterfaceRef interface
;
375 SCNetworkInterfacePrivateRef interfacePrivate
;
377 interface
= CFArrayGetValueAtIndex(interfaces
, i
);
378 interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
380 if (!interfacePrivate
->supportsBond
) {
381 // if this interface is not available
385 if (CFSetContainsValue(excluded
, interface
)) {
390 CFArrayAppendValue(available
, interface
);
392 CFRelease(interfaces
);
402 _SCBondInterfaceCopyActive(void)
404 struct ifaddrs
*ifap
;
407 CFMutableArrayRef bonds
= NULL
;
409 if (getifaddrs(&ifap
) == -1) {
411 SC_log(LOG_NOTICE
, "getifaddrs() failed: %s", strerror(errno
));
415 s
= inet_dgram_socket();
421 bonds
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
423 for (ifp
= ifap
; ifp
!= NULL
; ifp
= ifp
->ifa_next
) {
424 SCBondInterfaceRef bond
;
426 struct if_bond_status_req
*ibsr_p
;
427 struct if_data
*if_data
;
430 CFMutableArrayRef members
= NULL
;
432 if_data
= (struct if_data
*)ifp
->ifa_data
;
434 || ifp
->ifa_addr
->sa_family
!= AF_LINK
435 || if_data
->ifi_type
!= IFT_IEEE8023ADLAG
) {
439 ibsr_p
= if_bond_status_req_copy(s
, ifp
->ifa_name
);
440 if (ibsr_p
== NULL
) {
441 if (errno
== EBUSY
) {
445 SC_log(LOG_NOTICE
, "if_bond_status_req_copy(%s) failed: %s",
453 // create the bond interface
454 bond_if
= CFStringCreateWithCString(NULL
, ifp
->ifa_name
, kCFStringEncodingASCII
);
455 bond
= (SCBondInterfaceRef
)_SCBondInterfaceCreatePrivate(NULL
, bond_if
);
459 int_val
= ibsr_p
->ibsr_mode
;
460 mode
= CFNumberCreate(NULL
, kCFNumberIntType
, &int_val
);
461 assert(mode
!= NULL
);
462 _SCBondInterfaceSetMode(bond
, mode
);
465 // add member interfaces
466 if (ibsr_p
->ibsr_total
> 0) {
468 struct if_bond_status
* ibs_p
;
470 // iterate over each member interface
471 ibs_p
= (struct if_bond_status
*)ibsr_p
->ibsr_buffer
;
472 for (i
= 0; i
< ibsr_p
->ibsr_total
; i
++) {
475 member
= CFStringCreateWithCString(NULL
, ibs_p
[i
].ibs_if_name
, kCFStringEncodingASCII
);
476 add_interface(&members
, member
, NULL
);
482 if (members
!= NULL
) {
483 __SCBondInterfaceSetMemberInterfaces(bond
, members
);
488 CFArrayAppendValue(bonds
, bond
);
503 SCBondInterfaceCreate(SCPreferencesRef prefs
)
505 CFAllocatorRef allocator
;
506 SCBondInterfaceRef bond
= NULL
;
510 _SCErrorSet(kSCStatusInvalidArgument
);
514 allocator
= CFGetAllocator(prefs
);
516 // create a new bond using an unused interface name
517 for (i
= 0; bond
== NULL
; i
++) {
518 CFDictionaryRef dict
;
520 SCNetworkInterfacePrivateRef interfacePrivate
;
521 CFMutableDictionaryRef newDict
;
522 CFArrayRef newInterfaces
;
526 bond_if
= CFStringCreateWithFormat(allocator
, NULL
, CFSTR("bond%ld"), i
);
527 path
= CFStringCreateWithFormat(allocator
,
530 kSCPrefVirtualNetworkInterfaces
,
531 kSCNetworkInterfaceTypeBond
,
533 dict
= SCPreferencesPathGetValue(prefs
, path
);
535 // if bond interface name not available
541 // add the bond to the stored preferences
542 newDict
= CFDictionaryCreateMutable(allocator
,
544 &kCFTypeDictionaryKeyCallBacks
,
545 &kCFTypeDictionaryValueCallBacks
);
546 newInterfaces
= CFArrayCreate(allocator
, NULL
, 0, &kCFTypeArrayCallBacks
);
547 CFDictionaryAddValue(newDict
, kSCPropVirtualNetworkInterfacesBondInterfaces
, newInterfaces
);
548 CFRelease(newInterfaces
);
549 ok
= SCPreferencesPathSetValue(prefs
, path
, newDict
);
553 // if the bond could not be saved
558 // create the SCBondInterfaceRef
559 bond
= (SCBondInterfaceRef
)_SCBondInterfaceCreatePrivate(allocator
, bond_if
);
562 // estabish link to the stored configuration
563 interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
564 interfacePrivate
->prefs
= CFRetain(prefs
);
572 SCBondInterfaceRemove(SCBondInterfaceRef bond
)
575 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
579 if (!isA_SCBondInterface(bond
)) {
580 _SCErrorSet(kSCStatusInvalidArgument
);
584 if (interfacePrivate
->prefs
== NULL
) {
585 _SCErrorSet(kSCStatusInvalidArgument
);
589 bond_if
= SCNetworkInterfaceGetBSDName(bond
);
590 path
= CFStringCreateWithFormat(NULL
,
593 kSCPrefVirtualNetworkInterfaces
,
594 kSCNetworkInterfaceTypeBond
,
596 ok
= SCPreferencesPathRemoveValue(interfacePrivate
->prefs
, path
);
604 SCBondInterfaceGetMemberInterfaces(SCBondInterfaceRef bond
)
606 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
608 if (!isA_SCBondInterface(bond
)) {
609 _SCErrorSet(kSCStatusInvalidArgument
);
613 return interfacePrivate
->bond
.interfaces
;
618 SCBondInterfaceGetOptions(SCBondInterfaceRef bond
)
620 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
622 if (!isA_SCBondInterface(bond
)) {
623 _SCErrorSet(kSCStatusInvalidArgument
);
627 return interfacePrivate
->bond
.options
;
633 __SCBondInterfaceSetMemberInterfaces(SCBondInterfaceRef bond
, CFArrayRef members
)
636 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
638 CFMutableArrayRef newMembers
;
641 n
= (members
!= NULL
) ? CFArrayGetCount(members
) : 0;
643 // set member interfaces in the stored preferences
644 if (interfacePrivate
->prefs
!= NULL
) {
645 CFDictionaryRef dict
;
646 CFMutableDictionaryRef newDict
;
649 path
= CFStringCreateWithFormat(NULL
,
652 kSCPrefVirtualNetworkInterfaces
,
653 kSCNetworkInterfaceTypeBond
,
654 interfacePrivate
->entity_device
);
655 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
656 if (!isA_CFDictionary(dict
)) {
657 // if the prefs are confused
659 _SCErrorSet(kSCStatusFailed
);
663 newMembers
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
664 for (i
= 0; i
< n
; i
++) {
665 SCNetworkInterfaceRef interface
;
666 CFStringRef memberName
;
668 interface
= CFArrayGetValueAtIndex(members
, i
);
669 memberName
= SCNetworkInterfaceGetBSDName(interface
);
670 CFArrayAppendValue(newMembers
, memberName
);
673 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
674 CFDictionarySetValue(newDict
, kSCPropVirtualNetworkInterfacesBondInterfaces
, newMembers
);
675 CFRelease(newMembers
);
676 if (!CFEqual(dict
, newDict
)) {
677 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
684 newMembers
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
685 for (i
= 0; i
< n
; i
++) {
686 SCNetworkInterfaceRef member
;
687 SCNetworkInterfacePrivateRef newMember
;
689 member
= CFArrayGetValueAtIndex(members
, i
);
690 newMember
= __SCNetworkInterfaceCreateCopy(NULL
,
692 interfacePrivate
->prefs
,
693 interfacePrivate
->serviceID
);
694 CFArrayAppendValue(newMembers
, newMember
);
695 CFRelease(newMember
);
697 CFRelease(interfacePrivate
->bond
.interfaces
);
698 interfacePrivate
->bond
.interfaces
= newMembers
;
706 SCBondInterfaceSetMemberInterfaces(SCBondInterfaceRef bond
, CFArrayRef members
)
708 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
710 int sc_status
= kSCStatusOK
;
712 if (!isA_SCBondInterface(bond
)) {
713 _SCErrorSet(kSCStatusInvalidArgument
);
717 if ((members
!= NULL
) && !isA_CFArray(members
)) {
718 _SCErrorSet(kSCStatusInvalidArgument
);
722 if (interfacePrivate
->prefs
!= NULL
) {
723 CFArrayRef available
;
729 CFArrayRef services
= NULL
;
731 current
= SCBondInterfaceGetMemberInterfaces(bond
);
732 n_current
= (current
!= NULL
) ? CFArrayGetCount(current
) : 0;
734 available
= SCBondInterfaceCopyAvailableMemberInterfaces(interfacePrivate
->prefs
);
735 n_available
= (available
!= NULL
) ? CFArrayGetCount(available
) : 0;
737 n_members
= (members
!= NULL
) ? CFArrayGetCount(members
) : 0;
738 for (i
= 0; i
< n_members
; i
++) {
739 SCNetworkInterfaceRef member
;
741 member
= CFArrayGetValueAtIndex(members
, i
);
743 if ((current
!= NULL
) &&
744 CFArrayContainsValue(current
, CFRangeMake(0, n_current
), member
)) {
745 // current members are allowed
749 if ((available
!= NULL
) &&
750 CFArrayContainsValue(available
, CFRangeMake(0, n_available
), member
)) {
751 // available members are allowed but cannot be associated
752 // with any other network services.
754 if (services
== NULL
) {
755 services
= __SCNetworkServiceCopyAllEnabled(interfacePrivate
->prefs
);
757 if ((services
!= NULL
) &&
758 __SCNetworkServiceExistsForInterface(services
, member
)) {
759 sc_status
= kSCStatusKeyExists
;
767 // if member not allowed
768 sc_status
= kSCStatusInvalidArgument
;
772 if (available
!= NULL
) CFRelease(available
);
773 if (services
!= NULL
) CFRelease(services
);
776 if (sc_status
!= kSCStatusOK
) {
777 _SCErrorSet(sc_status
);
781 ok
= __SCBondInterfaceSetMemberInterfaces(bond
, members
);
787 SCBondInterfaceSetLocalizedDisplayName(SCBondInterfaceRef bond
, CFStringRef newName
)
789 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
792 if (!isA_SCBondInterface(bond
)) {
793 _SCErrorSet(kSCStatusInvalidArgument
);
797 if ((newName
!= NULL
) && !isA_CFString(newName
)) {
798 _SCErrorSet(kSCStatusInvalidArgument
);
802 // set name in the stored preferences
803 if (interfacePrivate
->prefs
!= NULL
) {
804 CFDictionaryRef dict
;
805 CFMutableDictionaryRef newDict
;
808 path
= CFStringCreateWithFormat(NULL
,
811 kSCPrefVirtualNetworkInterfaces
,
812 kSCNetworkInterfaceTypeBond
,
813 interfacePrivate
->entity_device
);
814 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
815 if (!isA_CFDictionary(dict
)) {
816 // if the prefs are confused
818 _SCErrorSet(kSCStatusFailed
);
822 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
823 if (newName
!= NULL
) {
824 CFDictionarySetValue(newDict
, kSCPropUserDefinedName
, newName
);
826 CFDictionaryRemoveValue(newDict
, kSCPropUserDefinedName
);
828 if (!CFEqual(dict
, newDict
)) {
829 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
835 // set name in the SCBondInterfaceRef
837 if (interfacePrivate
->localized_name
!= NULL
) {
838 CFRelease(interfacePrivate
->localized_name
);
839 interfacePrivate
->localized_name
= NULL
;
841 if (newName
!= NULL
) {
842 interfacePrivate
->localized_name
= CFStringCreateCopy(NULL
, newName
);
851 SCBondInterfaceSetOptions(SCBondInterfaceRef bond
, CFDictionaryRef newOptions
)
853 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
856 if (!isA_SCBondInterface(bond
)) {
857 _SCErrorSet(kSCStatusInvalidArgument
);
861 if ((newOptions
!= NULL
) && !isA_CFDictionary(newOptions
)) {
862 _SCErrorSet(kSCStatusInvalidArgument
);
866 // set options in the stored preferences
867 if (interfacePrivate
->prefs
!= NULL
) {
868 CFDictionaryRef dict
;
869 CFMutableDictionaryRef newDict
;
872 path
= CFStringCreateWithFormat(NULL
,
875 kSCPrefVirtualNetworkInterfaces
,
876 kSCNetworkInterfaceTypeBond
,
877 interfacePrivate
->entity_device
);
878 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
879 if (!isA_CFDictionary(dict
)) {
880 // if the prefs are confused
882 _SCErrorSet(kSCStatusFailed
);
886 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
887 if (newOptions
!= NULL
) {
888 CFDictionarySetValue(newDict
, kSCPropVirtualNetworkInterfacesBondOptions
, newOptions
);
890 CFDictionaryRemoveValue(newDict
, kSCPropVirtualNetworkInterfacesBondOptions
);
892 if (!CFEqual(dict
, newDict
)) {
893 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
899 // set options in the SCBondInterfaceRef
901 if (interfacePrivate
->bond
.options
!= NULL
) {
902 CFRelease(interfacePrivate
->bond
.options
);
903 interfacePrivate
->bond
.options
= NULL
;
905 if (newOptions
!= NULL
) {
906 interfacePrivate
->bond
.options
= CFDictionaryCreateCopy(NULL
, newOptions
);
915 _SCBondInterfaceSetMode(SCBondInterfaceRef bond
, CFNumberRef mode
)
917 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
918 Boolean needs_release
= FALSE
;
921 assert(bond
!= NULL
);
924 int mode_num
= IF_BOND_MODE_LACP
;
926 mode
= CFNumberCreate(NULL
, kCFNumberIntType
, &mode_num
);
927 needs_release
= TRUE
;
930 // set mode in the stored preferences
931 if (interfacePrivate
->prefs
!= NULL
) {
932 CFDictionaryRef dict
;
933 CFMutableDictionaryRef newDict
;
936 path
= CFStringCreateWithFormat(NULL
,
939 kSCPrefVirtualNetworkInterfaces
,
940 kSCNetworkInterfaceTypeBond
,
941 interfacePrivate
->entity_device
);
942 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
943 if (!isA_CFDictionary(dict
)) {
944 // if the prefs are confused
946 _SCErrorSet(kSCStatusFailed
);
950 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
951 CFDictionarySetValue(newDict
, kSCPropVirtualNetworkInterfacesBondMode
, mode
);
952 if (!CFEqual(dict
, newDict
)) {
953 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
961 if (interfacePrivate
->bond
.mode
!= NULL
) {
962 CFRelease(interfacePrivate
->bond
.mode
);
964 interfacePrivate
->bond
.mode
= mode
;
969 if (needs_release
) CFRelease(mode
);
974 SCBondInterfaceSetMode(SCBondInterfaceRef bond
, CFNumberRef mode
)
978 if (!isA_SCBondInterface(bond
) || !isA_CFNumber(mode
)) {
979 _SCErrorSet(kSCStatusInvalidArgument
);
983 if (!CFNumberGetValue(mode
, kCFNumberIntType
, &mode_num
)) {
984 _SCErrorSet(kSCStatusInvalidArgument
);
989 case IF_BOND_MODE_LACP
:
990 case IF_BOND_MODE_STATIC
:
993 _SCErrorSet(kSCStatusInvalidArgument
);
997 return (_SCBondInterfaceSetMode(bond
, mode
));
1001 SCBondInterfaceGetMode(SCBondInterfaceRef bond
)
1003 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
1005 if (!isA_SCBondInterface(bond
)) {
1006 _SCErrorSet(kSCStatusInvalidArgument
);
1009 return (interfacePrivate
->bond
.mode
);
1014 #pragma mark SCBondStatus APIs
1019 // base CFType information
1020 CFRuntimeBase cfBase
;
1023 SCBondInterfaceRef bond
;
1024 CFDictionaryRef status_bond
;
1026 // member interfaces and status
1027 CFArrayRef interfaces
; // of SCNetworkInterfaceRef's
1028 CFDictionaryRef status_interfaces
; // key = interface, val = interface status)
1030 } SCBondStatusPrivate
, * SCBondStatusPrivateRef
;
1033 const CFStringRef kSCBondStatusDeviceAggregationStatus
= CFSTR("AggregationStatus");
1034 const CFStringRef kSCBondStatusDeviceCollecting
= CFSTR("Collecting");
1035 const CFStringRef kSCBondStatusDeviceDistributing
= CFSTR("Distributing");
1038 static CFStringRef
__SCBondStatusCopyDescription (CFTypeRef cf
);
1039 static void __SCBondStatusDeallocate (CFTypeRef cf
);
1040 static Boolean
__SCBondStatusEqual (CFTypeRef cf1
, CFTypeRef cf2
);
1043 static const CFRuntimeClass __SCBondStatusClass
= {
1045 "BondStatus", // className
1048 __SCBondStatusDeallocate
, // dealloc
1049 __SCBondStatusEqual
, // equal
1051 NULL
, // copyFormattingDesc
1052 __SCBondStatusCopyDescription
// copyDebugDesc
1056 static CFTypeID __kSCBondStatusTypeID
= _kCFRuntimeNotATypeID
;
1059 static pthread_once_t bondStatus_init
= PTHREAD_ONCE_INIT
;
1063 __SCBondStatusCopyDescription(CFTypeRef cf
)
1065 CFAllocatorRef allocator
= CFGetAllocator(cf
);
1066 CFMutableStringRef result
;
1067 SCBondStatusPrivateRef statusPrivate
= (SCBondStatusPrivateRef
)cf
;
1069 result
= CFStringCreateMutable(allocator
, 0);
1070 CFStringAppendFormat(result
, NULL
, CFSTR("<SCBondStatus %p [%p]> {"), cf
, allocator
);
1071 CFStringAppendFormat(result
, NULL
, CFSTR(" bond = %@"), statusPrivate
->bond
);
1072 CFStringAppendFormat(result
, NULL
, CFSTR(", interface = %@"), statusPrivate
->status_bond
);
1073 CFStringAppendFormat(result
, NULL
, CFSTR(", members = %@"), statusPrivate
->status_interfaces
);
1074 CFStringAppendFormat(result
, NULL
, CFSTR(" }"));
1081 __SCBondStatusDeallocate(CFTypeRef cf
)
1083 SCBondStatusPrivateRef statusPrivate
= (SCBondStatusPrivateRef
)cf
;
1085 /* release resources */
1087 CFRelease(statusPrivate
->bond
);
1088 CFRelease(statusPrivate
->status_bond
);
1089 if (statusPrivate
->interfaces
!= NULL
) CFRelease(statusPrivate
->interfaces
);
1090 CFRelease(statusPrivate
->status_interfaces
);
1096 __SCBondStatusEqual(CFTypeRef cf1
, CFTypeRef cf2
)
1098 SCBondStatusPrivateRef status1
= (SCBondStatusPrivateRef
)cf1
;
1099 SCBondStatusPrivateRef status2
= (SCBondStatusPrivateRef
)cf2
;
1101 if (status1
== status2
)
1104 if (!CFEqual(status1
->bond
, status2
->bond
))
1105 return FALSE
; // if not the same bond
1107 if (!CFEqual(status1
->status_bond
, status2
->status_bond
))
1108 return FALSE
; // if not the same interface status
1110 if (!CFEqual(status1
->status_interfaces
, status2
->status_interfaces
))
1111 return FALSE
; // if not the same status of the member interfaces
1118 __SCBondStatusInitialize(void)
1120 __kSCBondStatusTypeID
= _CFRuntimeRegisterClass(&__SCBondStatusClass
);
1125 static SCBondStatusRef
1126 __SCBondStatusCreatePrivate(CFAllocatorRef __nullable allocator
,
1127 SCBondInterfaceRef bond
,
1128 CFDictionaryRef status_bond
,
1129 CFDictionaryRef status_interfaces
)
1131 SCBondStatusPrivateRef statusPrivate
;
1134 /* initialize runtime */
1135 pthread_once(&bondStatus_init
, __SCBondStatusInitialize
);
1138 size
= sizeof(SCBondStatusPrivate
) - sizeof(CFRuntimeBase
);
1139 statusPrivate
= (SCBondStatusPrivateRef
)_CFRuntimeCreateInstance(allocator
,
1140 __kSCBondStatusTypeID
,
1143 if (statusPrivate
== NULL
) {
1147 /* initialize non-zero/NULL members */
1148 statusPrivate
->bond
= CFRetain(bond
);
1149 statusPrivate
->status_bond
= CFDictionaryCreateCopy(NULL
, status_bond
);
1150 statusPrivate
->status_interfaces
= CFDictionaryCreateCopy(NULL
, status_interfaces
);
1152 return (SCBondStatusRef
)statusPrivate
;
1156 static __inline__ CFTypeRef
1157 isA_SCBondStatus(CFTypeRef obj
)
1159 return (isA_CFType(obj
, SCBondStatusGetTypeID()));
1164 SCBondStatusGetTypeID()
1166 pthread_once(&bondStatus_init
, __SCBondStatusInitialize
); /* initialize runtime */
1167 return __kSCBondStatusTypeID
;
1174 CFArrayRef
/* of SCNetworkInterfaceRef's */
1175 SCBondStatusGetMemberInterfaces(SCBondStatusRef bondStatus
)
1177 SCBondStatusPrivateRef statusPrivate
= (SCBondStatusPrivateRef
)bondStatus
;
1179 if (!isA_SCBondStatus(bondStatus
)) {
1183 if (statusPrivate
->interfaces
== NULL
) {
1184 const void * keys_q
[N_QUICK
];
1185 const void ** keys
= keys_q
;
1188 n
= CFDictionaryGetCount(statusPrivate
->status_interfaces
);
1189 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
1190 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
1192 CFDictionaryGetKeysAndValues(statusPrivate
->status_interfaces
, keys
, NULL
);
1193 statusPrivate
->interfaces
= CFArrayCreate(NULL
, keys
, n
, &kCFTypeArrayCallBacks
);
1194 if (keys
!= keys_q
) {
1195 CFAllocatorDeallocate(NULL
, keys
);
1199 return statusPrivate
->interfaces
;
1204 SCBondStatusGetInterfaceStatus(SCBondStatusRef bondStatus
, SCNetworkInterfaceRef interface
)
1206 CFDictionaryRef status
= NULL
;
1207 SCBondStatusPrivateRef statusPrivate
= (SCBondStatusPrivateRef
)bondStatus
;
1209 if (!isA_SCBondStatus(bondStatus
)) {
1213 if (interface
== NULL
) {
1214 // return status of the bond
1215 status
= statusPrivate
->status_bond
;
1217 // return status of the member interface
1218 status
= CFDictionaryGetValue(statusPrivate
->status_interfaces
, interface
);
1226 SCBondInterfaceCopyStatus(SCBondInterfaceRef bond
)
1231 struct if_bond_status_req
*ibsr_p
= NULL
;
1232 char if_name
[IFNAMSIZ
];
1236 struct if_bond_status
*scan_p
;
1237 SCBondStatusRef status
= NULL
;
1238 CFMutableDictionaryRef status_bond
;
1239 CFMutableDictionaryRef status_interfaces
;
1241 if (!isA_SCBondInterface(bond
)) {
1242 _SCErrorSet(kSCStatusInvalidArgument
);
1246 s
= inet_dgram_socket();
1252 _SC_cfstring_to_cstring(SCNetworkInterfaceGetBSDName(bond
),
1255 kCFStringEncodingASCII
);
1256 if (siocgifxmedia(s
, if_name
, &bond_if_status
, &bond_if_active
) == -1) {
1263 SC_log(LOG_NOTICE
, "siocgifxmedia(%s) failed: %s",
1269 ibsr_p
= if_bond_status_req_copy(s
, if_name
);
1270 if (ibsr_p
== NULL
) {
1275 status_bond
= CFDictionaryCreateMutable(NULL
,
1277 &kCFTypeDictionaryKeyCallBacks
,
1278 &kCFTypeDictionaryValueCallBacks
);
1280 status_interfaces
= CFDictionaryCreateMutable(NULL
,
1282 &kCFTypeDictionaryKeyCallBacks
,
1283 &kCFTypeDictionaryValueCallBacks
);
1284 n
= ibsr_p
->ibsr_total
;
1285 for (i
= 0, scan_p
= (struct if_bond_status
*)ibsr_p
->ibsr_buffer
; i
< n
; i
++, scan_p
++) {
1287 int distributing
= 0;
1288 SCNetworkInterfaceRef interface
;
1289 CFStringRef interface_name
;
1290 struct if_bond_partner_state
* ps
;
1291 CFMutableDictionaryRef status_interface
;
1294 ps
= &scan_p
->ibs_partner_state
;
1296 if (lacp_actor_partner_state_in_sync(scan_p
->ibs_state
)) {
1298 status_val
= kSCBondStatusOK
;
1299 if (lacp_actor_partner_state_in_sync(ps
->ibps_state
)) {
1300 /* partner is also in-sync */
1301 if (lacp_actor_partner_state_collecting(scan_p
->ibs_state
)
1302 && lacp_actor_partner_state_distributing(ps
->ibps_state
)) {
1303 /* we're able to collect (receive) frames */
1306 if (lacp_actor_partner_state_distributing(scan_p
->ibs_state
)
1307 && lacp_actor_partner_state_collecting(ps
->ibps_state
)) {
1308 /* we're able to distribute (transmit) frames */
1315 static lacp_system zeroes
= { {0, 0, 0, 0, 0, 0}};
1317 if (siocgifxmedia(s
, scan_p
->ibs_if_name
, &status
, &active
) == -1) {
1323 SC_log(LOG_NOTICE
, "siocgifxmedia(%s) failed: %s",
1329 if (((status
& IFM_AVALID
) == 0) ||
1330 ((status
& IFM_ACTIVE
) == 0) ||
1331 ((active
& IFM_FDX
) == 0)) {
1332 /* link down or not full-duplex */
1333 status_val
= kSCBondStatusLinkInvalid
;
1334 } else if ((ps
->ibps_system_priority
== 0) &&
1335 (bcmp(&zeroes
, &ps
->ibps_system
, sizeof(zeroes
)) == 0)) {
1336 /* no one on the other end of the link */
1337 status_val
= kSCBondStatusNoPartner
;
1338 } else if (active
!= bond_if_active
) {
1339 /* the link speed was different */
1340 status_val
= kSCBondStatusLinkInvalid
;
1342 /* partner is not in the active group */
1343 status_val
= kSCBondStatusNotInActiveGroup
;
1348 strlcpy(if_name
, scan_p
->ibs_if_name
, sizeof(if_name
));
1349 interface_name
= CFStringCreateWithCString(NULL
, if_name
, kCFStringEncodingASCII
);
1350 interface
= _SCNetworkInterfaceCreateWithBSDName(NULL
, interface_name
,
1351 kIncludeNoVirtualInterfaces
);
1352 CFRelease(interface_name
);
1355 status_interface
= CFDictionaryCreateMutable(NULL
,
1357 &kCFTypeDictionaryKeyCallBacks
,
1358 &kCFTypeDictionaryValueCallBacks
);
1359 num
= CFNumberCreate(NULL
, kCFNumberIntType
, &status_val
);
1360 CFDictionarySetValue(status_interface
, kSCBondStatusDeviceAggregationStatus
, num
);
1362 num
= CFNumberCreate(NULL
, kCFNumberIntType
, &collecting
);
1363 CFDictionarySetValue(status_interface
, kSCBondStatusDeviceCollecting
, num
);
1365 num
= CFNumberCreate(NULL
, kCFNumberIntType
, &distributing
);
1366 CFDictionarySetValue(status_interface
, kSCBondStatusDeviceDistributing
, num
);
1369 CFDictionarySetValue(status_interfaces
, interface
, status_interface
);
1370 CFRelease(interface
);
1371 CFRelease(status_interface
);
1374 status
= __SCBondStatusCreatePrivate(NULL
, bond
, status_bond
, status_interfaces
);
1375 CFRelease(status_bond
);
1376 CFRelease(status_interfaces
);
1383 if (ibsr_p
!= NULL
) {
1386 return (SCBondStatusRef
)status
;
1391 #pragma mark SCBondInterface management
1395 __bond_set_mode(int s
, CFStringRef bond_if
, CFNumberRef mode
)
1397 struct if_bond_req breq
;
1401 mode_num
= IF_BOND_MODE_LACP
;
1403 CFNumberGetValue(mode
, kCFNumberIntType
, &mode_num
);
1407 memset(&ifr
, 0, sizeof(ifr
));
1408 (void) _SC_cfstring_to_cstring(bond_if
,
1410 sizeof(ifr
.ifr_name
),
1411 kCFStringEncodingASCII
);
1412 ifr
.ifr_data
= (caddr_t
)&breq
;
1413 memset(&breq
, 0, sizeof(breq
));
1414 breq
.ibr_op
= IF_BOND_OP_SET_MODE
;
1415 breq
.ibr_ibru
.ibru_int_val
= mode_num
;
1416 if (ioctl(s
, SIOCSIFBOND
, (caddr_t
)&ifr
) == -1) {
1418 SC_log(LOG_ERR
, "could not set mode to %@ on bond \"%@\": %s",
1429 __bond_add_interface(int s
, CFStringRef bond_if
, CFStringRef interface_if
)
1431 struct if_bond_req breq
;
1435 memset(&ifr
, 0, sizeof(ifr
));
1436 (void) _SC_cfstring_to_cstring(bond_if
,
1438 sizeof(ifr
.ifr_name
),
1439 kCFStringEncodingASCII
);
1440 ifr
.ifr_data
= (caddr_t
)&breq
;
1443 memset(&breq
, 0, sizeof(breq
));
1444 breq
.ibr_op
= IF_BOND_OP_ADD_INTERFACE
;
1445 (void) _SC_cfstring_to_cstring(interface_if
,
1446 breq
.ibr_ibru
.ibru_if_name
,
1447 sizeof(breq
.ibr_ibru
.ibru_if_name
),
1448 kCFStringEncodingASCII
);
1450 // add new bond member
1451 if (ioctl(s
, SIOCSIFBOND
, (caddr_t
)&ifr
) == -1) {
1453 SC_log(LOG_ERR
, "could not add interface \"%@\" to bond \"%@\": %s",
1465 __bond_remove_interface(int s
, CFStringRef bond_if
, CFStringRef interface_if
)
1467 struct if_bond_req breq
;
1471 memset(&ifr
, 0, sizeof(ifr
));
1472 (void) _SC_cfstring_to_cstring(bond_if
,
1474 sizeof(ifr
.ifr_name
),
1475 kCFStringEncodingASCII
);
1476 ifr
.ifr_data
= (caddr_t
)&breq
;
1478 // bond member to remove
1479 memset(&breq
, 0, sizeof(breq
));
1480 breq
.ibr_op
= IF_BOND_OP_REMOVE_INTERFACE
;
1481 (void) _SC_cfstring_to_cstring(interface_if
,
1482 breq
.ibr_ibru
.ibru_if_name
,
1483 sizeof(breq
.ibr_ibru
.ibru_if_name
),
1484 kCFStringEncodingASCII
);
1486 // remove bond member
1487 if (ioctl(s
, SIOCSIFBOND
, (caddr_t
)&ifr
) == -1) {
1489 SC_log(LOG_ERR
, "could not remove interface \"%@\" from bond \"%@\": %s",
1501 _SCBondInterfaceUpdateConfiguration(SCPreferencesRef prefs
)
1503 CFArrayRef active
= NULL
;
1504 CFArrayRef config
= NULL
;
1511 if (prefs
== NULL
) {
1512 _SCErrorSet(kSCStatusInvalidArgument
);
1516 /* configured Bonds */
1517 config
= SCBondInterfaceCopyAll(prefs
);
1518 nConfig
= (config
!= NULL
) ? CFArrayGetCount(config
) : 0;
1521 active
= _SCBondInterfaceCopyActive();
1522 nActive
= (active
!= NULL
) ? CFArrayGetCount(active
) : 0;
1525 * remove any no-longer-configured bond interfaces and
1526 * any devices associated with a bond that are no longer
1527 * associated with a bond.
1529 for (i
= 0; i
< nActive
; i
++) {
1530 SCBondInterfaceRef a_bond
;
1531 CFStringRef a_bond_if
;
1533 Boolean found
= FALSE
;
1535 a_bond
= CFArrayGetValueAtIndex(active
, i
);
1536 a_bond_if
= SCNetworkInterfaceGetBSDName(a_bond
);
1538 for (j
= 0; j
< nConfig
; j
++) {
1539 SCBondInterfaceRef c_bond
;
1540 CFStringRef c_bond_if
;
1542 c_bond
= CFArrayGetValueAtIndex(config
, j
);
1543 c_bond_if
= SCNetworkInterfaceGetBSDName(c_bond
);
1545 if (CFEqual(a_bond_if
, c_bond_if
)) {
1547 CFArrayRef a_bond_interfaces
;
1549 CFArrayRef c_bond_interfaces
;
1552 c_bond_interfaces
= SCBondInterfaceGetMemberInterfaces(c_bond
);
1553 c_count
= (c_bond_interfaces
!= NULL
) ? CFArrayGetCount(c_bond_interfaces
) : 0;
1555 a_bond_interfaces
= SCBondInterfaceGetMemberInterfaces(a_bond
);
1556 a_count
= (a_bond_interfaces
!= NULL
) ? CFArrayGetCount(a_bond_interfaces
) : 0;
1558 for (a
= 0; a
< a_count
; a
++) {
1559 SCNetworkInterfaceRef a_interface
;
1560 CFStringRef a_interface_if
;
1562 a_interface
= CFArrayGetValueAtIndex(a_bond_interfaces
, a
);
1563 if ((c_count
== 0) ||
1564 !CFArrayContainsValue(c_bond_interfaces
,
1565 CFRangeMake(0, c_count
),
1568 * if this device is no longer part
1572 s
= inet_dgram_socket();
1580 a_interface_if
= SCNetworkInterfaceGetBSDName(a_interface
);
1581 if (!__bond_remove_interface(s
, a_bond_if
, a_interface_if
)) {
1594 * if this interface is no longer configured
1597 s
= inet_dgram_socket();
1605 if (!__destroyInterface(s
, a_bond_if
)) {
1613 * add any newly-configured bond interfaces and add any
1614 * devices that should now be associated with the bond.
1616 for (i
= 0; i
< nConfig
; i
++) {
1617 CFNumberRef c_bond_mode
;
1618 SCBondInterfaceRef c_bond
;
1619 CFArrayRef c_bond_interfaces
;
1620 CFStringRef c_bond_if
;
1622 Boolean found
= FALSE
;
1625 c_bond
= CFArrayGetValueAtIndex(config
, i
);
1626 c_bond_if
= SCNetworkInterfaceGetBSDName(c_bond
);
1627 c_bond_interfaces
= SCBondInterfaceGetMemberInterfaces(c_bond
);
1628 c_bond_mode
= SCBondInterfaceGetMode(c_bond
);
1629 c_count
= (c_bond_interfaces
!= NULL
) ? CFArrayGetCount(c_bond_interfaces
) : 0;
1631 for (j
= 0; j
< nActive
; j
++) {
1632 SCBondInterfaceRef a_bond
;
1633 CFArrayRef a_bond_interfaces
;
1634 CFNumberRef a_bond_mode
;
1635 CFStringRef a_bond_if
;
1638 a_bond
= CFArrayGetValueAtIndex(active
, j
);
1639 a_bond_if
= SCNetworkInterfaceGetBSDName(a_bond
);
1640 a_bond_interfaces
= SCBondInterfaceGetMemberInterfaces(a_bond
);
1641 a_bond_mode
= SCBondInterfaceGetMode(a_bond
);
1642 a_count
= (a_bond_interfaces
!= NULL
) ? CFArrayGetCount(a_bond_interfaces
) : 0;
1644 if (CFEqual(c_bond_if
, a_bond_if
)) {
1646 Boolean if_list_change
= FALSE
;
1647 Boolean mode_change
= FALSE
;
1651 if (!_SC_CFEqual(a_bond_mode
, c_bond_mode
)) {
1655 if (!_SC_CFEqual(c_bond_interfaces
, a_bond_interfaces
)) {
1656 if_list_change
= TRUE
;
1658 if (!mode_change
&& !if_list_change
) {
1659 break; // if no change
1662 s
= inet_dgram_socket();
1670 __bond_set_mode(s
, a_bond_if
, c_bond_mode
);
1672 if (!if_list_change
) {
1673 break; // no if list changes
1677 * ensure that the first device of the bond matches, if
1678 * not then we remove all current devices and add them
1679 * back in the preferred order.
1681 if ((c_count
> 0) &&
1683 !CFEqual(CFArrayGetValueAtIndex(c_bond_interfaces
, 0),
1684 CFArrayGetValueAtIndex(a_bond_interfaces
, 0))) {
1687 for (a
= 0; a
< a_count
; a
++) {
1688 SCNetworkInterfaceRef a_interface
;
1689 CFStringRef a_interface_if
;
1691 a_interface
= CFArrayGetValueAtIndex(a_bond_interfaces
, a
);
1692 if (!CFArrayContainsValue(c_bond_interfaces
,
1693 CFRangeMake(0, c_count
),
1695 continue; // if already removed
1698 a_interface_if
= SCNetworkInterfaceGetBSDName(a_interface
);
1699 if (!__bond_remove_interface(s
, a_bond_if
, a_interface_if
)) {
1704 a_count
= 0; // all active devices have been removed
1708 * add any devices which are not currently associated
1709 * with the bond interface.
1711 for (c
= 0; c
< c_count
; c
++) {
1712 SCNetworkInterfaceRef c_interface
;
1713 SCNetworkInterfacePrivateRef c_interfacePrivate
;
1714 CFStringRef c_interface_if
;
1716 c_interface
= CFArrayGetValueAtIndex(c_bond_interfaces
, c
);
1717 if ((a_count
== 0) ||
1718 !CFArrayContainsValue(a_bond_interfaces
,
1719 CFRangeMake(0, a_count
),
1722 * check if this member interface can be added to a bond.
1724 c_interfacePrivate
= (SCNetworkInterfacePrivateRef
)c_interface
;
1725 if (!c_interfacePrivate
->supportsBond
) {
1726 // if member not supported
1731 * if this member interface is not currently part of the bond.
1733 c_interface_if
= SCNetworkInterfaceGetBSDName(c_interface
);
1734 if (!__bond_add_interface(s
, c_bond_if
, c_interface_if
)) {
1735 // if member could not be added
1749 s
= inet_dgram_socket();
1758 * establish the new bond interface.
1760 if (!__createInterface(s
, c_bond_if
)) {
1767 __bond_set_mode(s
, c_bond_if
, c_bond_mode
);
1770 * add the member interfaces
1772 for (c
= 0; c
< c_count
; c
++) {
1773 SCNetworkInterfaceRef c_interface
;
1774 SCNetworkInterfacePrivateRef c_interfacePrivate
;
1775 CFStringRef c_interface_if
;
1777 c_interface
= CFArrayGetValueAtIndex(c_bond_interfaces
, c
);
1778 c_interfacePrivate
= (SCNetworkInterfacePrivateRef
)c_interface
;
1779 if (!c_interfacePrivate
->supportsBond
) {
1780 // if member not supported
1784 c_interface_if
= SCNetworkInterfaceGetBSDName(c_interface
);
1785 if (!__bond_add_interface(s
, c_bond_if
, c_interface_if
)) {
1786 // if member could not be added
1796 if (active
!= NULL
) CFRelease(active
);
1797 if (config
!= NULL
) CFRelease(config
);
1798 if (s
!= -1) (void) close(s
);