2 * Copyright (c) 2004-2014 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 SCLog(TRUE
, LOG_ERR
, CFSTR("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 SCLog(TRUE
, LOG_ERR
, CFSTR("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
) {
451 CFSTR("if_bond_status_req_copy(%s) failed: %s"),
459 // create the bond interface
460 bond_if
= CFStringCreateWithCString(NULL
, ifp
->ifa_name
, kCFStringEncodingASCII
);
461 bond
= (SCBondInterfaceRef
)_SCBondInterfaceCreatePrivate(NULL
, bond_if
);
465 int_val
= ibsr_p
->ibsr_mode
;
466 mode
= CFNumberCreate(NULL
, kCFNumberIntType
, &int_val
);
467 assert(mode
!= NULL
);
468 _SCBondInterfaceSetMode(bond
, mode
);
471 // add member interfaces
472 if (ibsr_p
->ibsr_total
> 0) {
474 struct if_bond_status
* ibs_p
;
476 // iterate over each member interface
477 ibs_p
= (struct if_bond_status
*)ibsr_p
->ibsr_buffer
;
478 for (i
= 0; i
< ibsr_p
->ibsr_total
; i
++) {
481 member
= CFStringCreateWithCString(NULL
, ibs_p
[i
].ibs_if_name
, kCFStringEncodingASCII
);
482 add_interface(&members
, member
, NULL
);
488 if (members
!= NULL
) {
489 __SCBondInterfaceSetMemberInterfaces(bond
, members
);
494 CFArrayAppendValue(bonds
, bond
);
509 SCBondInterfaceCreate(SCPreferencesRef prefs
)
511 CFAllocatorRef allocator
;
512 SCBondInterfaceRef bond
= NULL
;
516 _SCErrorSet(kSCStatusInvalidArgument
);
520 allocator
= CFGetAllocator(prefs
);
522 // create a new bond using an unused interface name
523 for (i
= 0; bond
== NULL
; i
++) {
524 CFDictionaryRef dict
;
526 SCNetworkInterfacePrivateRef interfacePrivate
;
527 CFMutableDictionaryRef newDict
;
528 CFArrayRef newInterfaces
;
532 bond_if
= CFStringCreateWithFormat(allocator
, NULL
, CFSTR("bond%ld"), i
);
533 path
= CFStringCreateWithFormat(allocator
,
536 kSCPrefVirtualNetworkInterfaces
,
537 kSCNetworkInterfaceTypeBond
,
539 dict
= SCPreferencesPathGetValue(prefs
, path
);
541 // if bond interface name not available
547 // add the bond to the stored preferences
548 newDict
= CFDictionaryCreateMutable(allocator
,
550 &kCFTypeDictionaryKeyCallBacks
,
551 &kCFTypeDictionaryValueCallBacks
);
552 newInterfaces
= CFArrayCreate(allocator
, NULL
, 0, &kCFTypeArrayCallBacks
);
553 CFDictionaryAddValue(newDict
, kSCPropVirtualNetworkInterfacesBondInterfaces
, newInterfaces
);
554 CFRelease(newInterfaces
);
555 ok
= SCPreferencesPathSetValue(prefs
, path
, newDict
);
559 // if the bond could not be saved
564 // create the SCBondInterfaceRef
565 bond
= (SCBondInterfaceRef
)_SCBondInterfaceCreatePrivate(allocator
, bond_if
);
568 // estabish link to the stored configuration
569 interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
570 interfacePrivate
->prefs
= CFRetain(prefs
);
578 SCBondInterfaceRemove(SCBondInterfaceRef bond
)
581 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
585 if (!isA_SCBondInterface(bond
)) {
586 _SCErrorSet(kSCStatusInvalidArgument
);
590 if (interfacePrivate
->prefs
== NULL
) {
591 _SCErrorSet(kSCStatusInvalidArgument
);
595 bond_if
= SCNetworkInterfaceGetBSDName(bond
);
596 path
= CFStringCreateWithFormat(NULL
,
599 kSCPrefVirtualNetworkInterfaces
,
600 kSCNetworkInterfaceTypeBond
,
602 ok
= SCPreferencesPathRemoveValue(interfacePrivate
->prefs
, path
);
610 SCBondInterfaceGetMemberInterfaces(SCBondInterfaceRef bond
)
612 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
614 if (!isA_SCBondInterface(bond
)) {
615 _SCErrorSet(kSCStatusInvalidArgument
);
619 return interfacePrivate
->bond
.interfaces
;
624 SCBondInterfaceGetOptions(SCBondInterfaceRef bond
)
626 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
628 if (!isA_SCBondInterface(bond
)) {
629 _SCErrorSet(kSCStatusInvalidArgument
);
633 return interfacePrivate
->bond
.options
;
639 __SCBondInterfaceSetMemberInterfaces(SCBondInterfaceRef bond
, CFArrayRef members
)
642 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
644 CFMutableArrayRef newMembers
;
647 n
= (members
!= NULL
) ? CFArrayGetCount(members
) : 0;
649 // set member interfaces in the stored preferences
650 if (interfacePrivate
->prefs
!= NULL
) {
651 CFDictionaryRef dict
;
652 CFMutableDictionaryRef newDict
;
655 path
= CFStringCreateWithFormat(NULL
,
658 kSCPrefVirtualNetworkInterfaces
,
659 kSCNetworkInterfaceTypeBond
,
660 interfacePrivate
->entity_device
);
661 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
662 if (!isA_CFDictionary(dict
)) {
663 // if the prefs are confused
665 _SCErrorSet(kSCStatusFailed
);
669 newMembers
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
670 for (i
= 0; i
< n
; i
++) {
671 SCNetworkInterfaceRef interface
;
672 CFStringRef memberName
;
674 interface
= CFArrayGetValueAtIndex(members
, i
);
675 memberName
= SCNetworkInterfaceGetBSDName(interface
);
676 CFArrayAppendValue(newMembers
, memberName
);
679 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
680 CFDictionarySetValue(newDict
, kSCPropVirtualNetworkInterfacesBondInterfaces
, newMembers
);
681 CFRelease(newMembers
);
682 if (!CFEqual(dict
, newDict
)) {
683 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
690 newMembers
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
691 for (i
= 0; i
< n
; i
++) {
692 SCNetworkInterfaceRef member
;
693 SCNetworkInterfacePrivateRef newMember
;
695 member
= CFArrayGetValueAtIndex(members
, i
);
696 newMember
= __SCNetworkInterfaceCreateCopy(NULL
,
698 interfacePrivate
->prefs
,
699 interfacePrivate
->serviceID
);
700 CFArrayAppendValue(newMembers
, newMember
);
701 CFRelease(newMember
);
703 CFRelease(interfacePrivate
->bond
.interfaces
);
704 interfacePrivate
->bond
.interfaces
= newMembers
;
712 SCBondInterfaceSetMemberInterfaces(SCBondInterfaceRef bond
, CFArrayRef members
)
714 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
716 int sc_status
= kSCStatusOK
;
718 if (!isA_SCBondInterface(bond
)) {
719 _SCErrorSet(kSCStatusInvalidArgument
);
723 if ((members
!= NULL
) && !isA_CFArray(members
)) {
724 _SCErrorSet(kSCStatusInvalidArgument
);
728 if (interfacePrivate
->prefs
!= NULL
) {
729 CFArrayRef available
;
735 CFArrayRef services
= NULL
;
737 current
= SCBondInterfaceGetMemberInterfaces(bond
);
738 n_current
= (current
!= NULL
) ? CFArrayGetCount(current
) : 0;
740 available
= SCBondInterfaceCopyAvailableMemberInterfaces(interfacePrivate
->prefs
);
741 n_available
= (available
!= NULL
) ? CFArrayGetCount(available
) : 0;
743 n_members
= (members
!= NULL
) ? CFArrayGetCount(members
) : 0;
744 for (i
= 0; i
< n_members
; i
++) {
745 SCNetworkInterfaceRef member
;
747 member
= CFArrayGetValueAtIndex(members
, i
);
749 if ((current
!= NULL
) &&
750 CFArrayContainsValue(current
, CFRangeMake(0, n_current
), member
)) {
751 // current members are allowed
755 if ((available
!= NULL
) &&
756 CFArrayContainsValue(available
, CFRangeMake(0, n_available
), member
)) {
757 // available members are allowed but cannot be associated
758 // with any other network services.
760 if (services
== NULL
) {
761 services
= __SCNetworkServiceCopyAllEnabled(interfacePrivate
->prefs
);
763 if ((services
!= NULL
) &&
764 __SCNetworkServiceExistsForInterface(services
, member
)) {
765 sc_status
= kSCStatusKeyExists
;
773 // if member not allowed
774 sc_status
= kSCStatusInvalidArgument
;
778 if (available
!= NULL
) CFRelease(available
);
779 if (services
!= NULL
) CFRelease(services
);
782 if (sc_status
!= kSCStatusOK
) {
783 _SCErrorSet(sc_status
);
787 ok
= __SCBondInterfaceSetMemberInterfaces(bond
, members
);
793 SCBondInterfaceSetLocalizedDisplayName(SCBondInterfaceRef bond
, CFStringRef newName
)
795 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
798 if (!isA_SCBondInterface(bond
)) {
799 _SCErrorSet(kSCStatusInvalidArgument
);
803 if ((newName
!= NULL
) && !isA_CFString(newName
)) {
804 _SCErrorSet(kSCStatusInvalidArgument
);
808 // set name in the stored preferences
809 if (interfacePrivate
->prefs
!= NULL
) {
810 CFDictionaryRef dict
;
811 CFMutableDictionaryRef newDict
;
814 path
= CFStringCreateWithFormat(NULL
,
817 kSCPrefVirtualNetworkInterfaces
,
818 kSCNetworkInterfaceTypeBond
,
819 interfacePrivate
->entity_device
);
820 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
821 if (!isA_CFDictionary(dict
)) {
822 // if the prefs are confused
824 _SCErrorSet(kSCStatusFailed
);
828 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
829 if (newName
!= NULL
) {
830 CFDictionarySetValue(newDict
, kSCPropUserDefinedName
, newName
);
832 CFDictionaryRemoveValue(newDict
, kSCPropUserDefinedName
);
834 if (!CFEqual(dict
, newDict
)) {
835 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
841 // set name in the SCBondInterfaceRef
843 if (interfacePrivate
->localized_name
!= NULL
) {
844 CFRelease(interfacePrivate
->localized_name
);
845 interfacePrivate
->localized_name
= NULL
;
847 if (newName
!= NULL
) {
848 interfacePrivate
->localized_name
= CFStringCreateCopy(NULL
, newName
);
857 SCBondInterfaceSetOptions(SCBondInterfaceRef bond
, CFDictionaryRef newOptions
)
859 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
862 if (!isA_SCBondInterface(bond
)) {
863 _SCErrorSet(kSCStatusInvalidArgument
);
867 if ((newOptions
!= NULL
) && !isA_CFDictionary(newOptions
)) {
868 _SCErrorSet(kSCStatusInvalidArgument
);
872 // set options in the stored preferences
873 if (interfacePrivate
->prefs
!= NULL
) {
874 CFDictionaryRef dict
;
875 CFMutableDictionaryRef newDict
;
878 path
= CFStringCreateWithFormat(NULL
,
881 kSCPrefVirtualNetworkInterfaces
,
882 kSCNetworkInterfaceTypeBond
,
883 interfacePrivate
->entity_device
);
884 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
885 if (!isA_CFDictionary(dict
)) {
886 // if the prefs are confused
888 _SCErrorSet(kSCStatusFailed
);
892 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
893 if (newOptions
!= NULL
) {
894 CFDictionarySetValue(newDict
, kSCPropVirtualNetworkInterfacesBondOptions
, newOptions
);
896 CFDictionaryRemoveValue(newDict
, kSCPropVirtualNetworkInterfacesBondOptions
);
898 if (!CFEqual(dict
, newDict
)) {
899 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
905 // set options in the SCBondInterfaceRef
907 if (interfacePrivate
->bond
.options
!= NULL
) {
908 CFRelease(interfacePrivate
->bond
.options
);
909 interfacePrivate
->bond
.options
= NULL
;
911 if (newOptions
!= NULL
) {
912 interfacePrivate
->bond
.options
= CFDictionaryCreateCopy(NULL
, newOptions
);
921 _SCBondInterfaceSetMode(SCBondInterfaceRef bond
, CFNumberRef mode
)
923 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
924 Boolean needs_release
= FALSE
;
927 assert(bond
!= NULL
);
930 int mode_num
= IF_BOND_MODE_LACP
;
932 mode
= CFNumberCreate(NULL
, kCFNumberIntType
, &mode_num
);
933 needs_release
= TRUE
;
936 // set mode in the stored preferences
937 if (interfacePrivate
->prefs
!= NULL
) {
938 CFDictionaryRef dict
;
939 CFMutableDictionaryRef newDict
;
942 path
= CFStringCreateWithFormat(NULL
,
945 kSCPrefVirtualNetworkInterfaces
,
946 kSCNetworkInterfaceTypeBond
,
947 interfacePrivate
->entity_device
);
948 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
949 if (!isA_CFDictionary(dict
)) {
950 // if the prefs are confused
952 _SCErrorSet(kSCStatusFailed
);
956 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
957 CFDictionarySetValue(newDict
, kSCPropVirtualNetworkInterfacesBondMode
, mode
);
958 if (!CFEqual(dict
, newDict
)) {
959 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
967 if (interfacePrivate
->bond
.mode
!= NULL
) {
968 CFRelease(interfacePrivate
->bond
.mode
);
970 interfacePrivate
->bond
.mode
= mode
;
975 if (needs_release
) CFRelease(mode
);
980 SCBondInterfaceSetMode(SCBondInterfaceRef bond
, CFNumberRef mode
)
984 if (!isA_SCBondInterface(bond
) || !isA_CFNumber(mode
)) {
985 _SCErrorSet(kSCStatusInvalidArgument
);
989 if (CFNumberGetValue(mode
, kCFNumberIntType
, &mode_num
) == FALSE
) {
990 _SCErrorSet(kSCStatusInvalidArgument
);
995 case IF_BOND_MODE_LACP
:
996 case IF_BOND_MODE_STATIC
:
999 _SCErrorSet(kSCStatusInvalidArgument
);
1003 return (_SCBondInterfaceSetMode(bond
, mode
));
1007 SCBondInterfaceGetMode(SCBondInterfaceRef bond
)
1009 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
1011 if (!isA_SCBondInterface(bond
)) {
1012 _SCErrorSet(kSCStatusInvalidArgument
);
1015 return (interfacePrivate
->bond
.mode
);
1020 #pragma mark SCBondStatus APIs
1025 // base CFType information
1026 CFRuntimeBase cfBase
;
1029 SCBondInterfaceRef bond
;
1030 CFDictionaryRef status_bond
;
1032 // member interfaces and status
1033 CFArrayRef interfaces
; // of SCNetworkInterfaceRef's
1034 CFDictionaryRef status_interfaces
; // key = interface, val = interface status)
1036 } SCBondStatusPrivate
, * SCBondStatusPrivateRef
;
1039 const CFStringRef kSCBondStatusDeviceAggregationStatus
= CFSTR("AggregationStatus");
1040 const CFStringRef kSCBondStatusDeviceCollecting
= CFSTR("Collecting");
1041 const CFStringRef kSCBondStatusDeviceDistributing
= CFSTR("Distributing");
1044 static CFStringRef
__SCBondStatusCopyDescription (CFTypeRef cf
);
1045 static void __SCBondStatusDeallocate (CFTypeRef cf
);
1046 static Boolean
__SCBondStatusEqual (CFTypeRef cf1
, CFTypeRef cf2
);
1049 static const CFRuntimeClass __SCBondStatusClass
= {
1051 "BondStatus", // className
1054 __SCBondStatusDeallocate
, // dealloc
1055 __SCBondStatusEqual
, // equal
1057 NULL
, // copyFormattingDesc
1058 __SCBondStatusCopyDescription
// copyDebugDesc
1062 static CFTypeID __kSCBondStatusTypeID
= _kCFRuntimeNotATypeID
;
1065 static pthread_once_t bondStatus_init
= PTHREAD_ONCE_INIT
;
1069 __SCBondStatusCopyDescription(CFTypeRef cf
)
1071 CFAllocatorRef allocator
= CFGetAllocator(cf
);
1072 CFMutableStringRef result
;
1073 SCBondStatusPrivateRef statusPrivate
= (SCBondStatusPrivateRef
)cf
;
1075 result
= CFStringCreateMutable(allocator
, 0);
1076 CFStringAppendFormat(result
, NULL
, CFSTR("<SCBondStatus %p [%p]> {"), cf
, allocator
);
1077 CFStringAppendFormat(result
, NULL
, CFSTR(" bond = %@"), statusPrivate
->bond
);
1078 CFStringAppendFormat(result
, NULL
, CFSTR(", interface = %@"), statusPrivate
->status_bond
);
1079 CFStringAppendFormat(result
, NULL
, CFSTR(", members = %@"), statusPrivate
->status_interfaces
);
1080 CFStringAppendFormat(result
, NULL
, CFSTR(" }"));
1087 __SCBondStatusDeallocate(CFTypeRef cf
)
1089 SCBondStatusPrivateRef statusPrivate
= (SCBondStatusPrivateRef
)cf
;
1091 /* release resources */
1093 CFRelease(statusPrivate
->bond
);
1094 CFRelease(statusPrivate
->status_bond
);
1095 if (statusPrivate
->interfaces
!= NULL
) CFRelease(statusPrivate
->interfaces
);
1096 CFRelease(statusPrivate
->status_interfaces
);
1102 __SCBondStatusEqual(CFTypeRef cf1
, CFTypeRef cf2
)
1104 SCBondStatusPrivateRef status1
= (SCBondStatusPrivateRef
)cf1
;
1105 SCBondStatusPrivateRef status2
= (SCBondStatusPrivateRef
)cf2
;
1107 if (status1
== status2
)
1110 if (!CFEqual(status1
->bond
, status2
->bond
))
1111 return FALSE
; // if not the same bond
1113 if (!CFEqual(status1
->status_bond
, status2
->status_bond
))
1114 return FALSE
; // if not the same interface status
1116 if (!CFEqual(status1
->status_interfaces
, status2
->status_interfaces
))
1117 return FALSE
; // if not the same status of the member interfaces
1124 __SCBondStatusInitialize(void)
1126 __kSCBondStatusTypeID
= _CFRuntimeRegisterClass(&__SCBondStatusClass
);
1131 static SCBondStatusRef
1132 __SCBondStatusCreatePrivate(CFAllocatorRef allocator
,
1133 SCBondInterfaceRef bond
,
1134 CFDictionaryRef status_bond
,
1135 CFDictionaryRef status_interfaces
)
1137 SCBondStatusPrivateRef statusPrivate
;
1140 /* initialize runtime */
1141 pthread_once(&bondStatus_init
, __SCBondStatusInitialize
);
1144 size
= sizeof(SCBondStatusPrivate
) - sizeof(CFRuntimeBase
);
1145 statusPrivate
= (SCBondStatusPrivateRef
)_CFRuntimeCreateInstance(allocator
,
1146 __kSCBondStatusTypeID
,
1149 if (statusPrivate
== NULL
) {
1153 /* establish the bond status */
1155 statusPrivate
->bond
= CFRetain(bond
);
1156 statusPrivate
->status_bond
= CFDictionaryCreateCopy(NULL
, status_bond
);
1158 statusPrivate
->interfaces
= NULL
;
1159 statusPrivate
->status_interfaces
= CFDictionaryCreateCopy(NULL
, status_interfaces
);
1161 return (SCBondStatusRef
)statusPrivate
;
1165 static __inline__ CFTypeRef
1166 isA_SCBondStatus(CFTypeRef obj
)
1168 return (isA_CFType(obj
, SCBondStatusGetTypeID()));
1173 SCBondStatusGetTypeID()
1175 pthread_once(&bondStatus_init
, __SCBondStatusInitialize
); /* initialize runtime */
1176 return __kSCBondStatusTypeID
;
1183 CFArrayRef
/* of SCNetworkInterfaceRef's */
1184 SCBondStatusGetMemberInterfaces(SCBondStatusRef bondStatus
)
1186 SCBondStatusPrivateRef statusPrivate
= (SCBondStatusPrivateRef
)bondStatus
;
1188 if (!isA_SCBondStatus(bondStatus
)) {
1192 if (statusPrivate
->interfaces
== NULL
) {
1193 const void * keys_q
[N_QUICK
];
1194 const void ** keys
= keys_q
;
1197 n
= CFDictionaryGetCount(statusPrivate
->status_interfaces
);
1198 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
1199 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
1201 CFDictionaryGetKeysAndValues(statusPrivate
->status_interfaces
, keys
, NULL
);
1202 statusPrivate
->interfaces
= CFArrayCreate(NULL
, keys
, n
, &kCFTypeArrayCallBacks
);
1203 if (keys
!= keys_q
) {
1204 CFAllocatorDeallocate(NULL
, keys
);
1208 return statusPrivate
->interfaces
;
1213 SCBondStatusGetInterfaceStatus(SCBondStatusRef bondStatus
, SCNetworkInterfaceRef interface
)
1215 CFDictionaryRef status
= NULL
;
1216 SCBondStatusPrivateRef statusPrivate
= (SCBondStatusPrivateRef
)bondStatus
;
1218 if (!isA_SCBondStatus(bondStatus
)) {
1222 if (interface
== NULL
) {
1223 // return status of the bond
1224 status
= statusPrivate
->status_bond
;
1226 // return status of the member interface
1227 status
= CFDictionaryGetValue(statusPrivate
->status_interfaces
, interface
);
1235 SCBondInterfaceCopyStatus(SCBondInterfaceRef bond
)
1240 struct if_bond_status_req
*ibsr_p
= NULL
;
1241 char if_name
[IFNAMSIZ
];
1245 struct if_bond_status
*scan_p
;
1246 SCBondStatusRef status
= NULL
;
1247 CFMutableDictionaryRef status_bond
;
1248 CFMutableDictionaryRef status_interfaces
;
1250 if (!isA_SCBondInterface(bond
)) {
1251 _SCErrorSet(kSCStatusInvalidArgument
);
1255 s
= inet_dgram_socket();
1261 _SC_cfstring_to_cstring(SCNetworkInterfaceGetBSDName(bond
),
1264 kCFStringEncodingASCII
);
1265 if (siocgifmedia(s
, if_name
, &bond_if_status
, &bond_if_active
) == -1) {
1272 SCLog(TRUE
, LOG_ERR
,
1273 CFSTR("siocgifmedia(%s) failed: %s"),
1279 ibsr_p
= if_bond_status_req_copy(s
, if_name
);
1280 if (ibsr_p
== NULL
) {
1285 status_bond
= CFDictionaryCreateMutable(NULL
,
1287 &kCFTypeDictionaryKeyCallBacks
,
1288 &kCFTypeDictionaryValueCallBacks
);
1290 status_interfaces
= CFDictionaryCreateMutable(NULL
,
1292 &kCFTypeDictionaryKeyCallBacks
,
1293 &kCFTypeDictionaryValueCallBacks
);
1294 n
= ibsr_p
->ibsr_total
;
1295 for (i
= 0, scan_p
= (struct if_bond_status
*)ibsr_p
->ibsr_buffer
; i
< n
; i
++, scan_p
++) {
1297 int distributing
= 0;
1298 SCNetworkInterfaceRef interface
;
1299 CFStringRef interface_name
;
1300 struct if_bond_partner_state
* ps
;
1301 CFMutableDictionaryRef status_interface
;
1304 ps
= &scan_p
->ibs_partner_state
;
1306 if (lacp_actor_partner_state_in_sync(scan_p
->ibs_state
)) {
1308 status_val
= kSCBondStatusOK
;
1309 if (lacp_actor_partner_state_in_sync(ps
->ibps_state
)) {
1310 /* partner is also in-sync */
1311 if (lacp_actor_partner_state_collecting(scan_p
->ibs_state
)
1312 && lacp_actor_partner_state_distributing(ps
->ibps_state
)) {
1313 /* we're able to collect (receive) frames */
1316 if (lacp_actor_partner_state_distributing(scan_p
->ibs_state
)
1317 && lacp_actor_partner_state_collecting(ps
->ibps_state
)) {
1318 /* we're able to distribute (transmit) frames */
1325 static lacp_system zeroes
= { {0, 0, 0, 0, 0, 0}};
1327 if (siocgifmedia(s
, scan_p
->ibs_if_name
, &status
, &active
) == -1) {
1333 SCLog(TRUE
, LOG_ERR
,
1334 CFSTR("siocgifmedia(%s) failed: %s"),
1340 if (((status
& IFM_AVALID
) == 0) ||
1341 ((status
& IFM_ACTIVE
) == 0) ||
1342 ((active
& IFM_FDX
) == 0)) {
1343 /* link down or not full-duplex */
1344 status_val
= kSCBondStatusLinkInvalid
;
1345 } else if ((ps
->ibps_system_priority
== 0) &&
1346 (bcmp(&zeroes
, &ps
->ibps_system
, sizeof(zeroes
)) == 0)) {
1347 /* no one on the other end of the link */
1348 status_val
= kSCBondStatusNoPartner
;
1349 } else if (active
!= bond_if_active
) {
1350 /* the link speed was different */
1351 status_val
= kSCBondStatusLinkInvalid
;
1353 /* partner is not in the active group */
1354 status_val
= kSCBondStatusNotInActiveGroup
;
1359 strlcpy(if_name
, scan_p
->ibs_if_name
, sizeof(if_name
));
1360 interface_name
= CFStringCreateWithCString(NULL
, if_name
, kCFStringEncodingASCII
);
1361 interface
= _SCNetworkInterfaceCreateWithBSDName(NULL
, interface_name
,
1362 kIncludeNoVirtualInterfaces
);
1363 CFRelease(interface_name
);
1366 status_interface
= CFDictionaryCreateMutable(NULL
,
1368 &kCFTypeDictionaryKeyCallBacks
,
1369 &kCFTypeDictionaryValueCallBacks
);
1370 num
= CFNumberCreate(NULL
, kCFNumberIntType
, &status_val
);
1371 CFDictionarySetValue(status_interface
, kSCBondStatusDeviceAggregationStatus
, num
);
1373 num
= CFNumberCreate(NULL
, kCFNumberIntType
, &collecting
);
1374 CFDictionarySetValue(status_interface
, kSCBondStatusDeviceCollecting
, num
);
1376 num
= CFNumberCreate(NULL
, kCFNumberIntType
, &distributing
);
1377 CFDictionarySetValue(status_interface
, kSCBondStatusDeviceDistributing
, num
);
1380 CFDictionarySetValue(status_interfaces
, interface
, status_interface
);
1381 CFRelease(interface
);
1382 CFRelease(status_interface
);
1385 status
= __SCBondStatusCreatePrivate(NULL
, bond
, status_bond
, status_interfaces
);
1386 CFRelease(status_bond
);
1387 CFRelease(status_interfaces
);
1394 if (ibsr_p
!= NULL
) {
1397 return (SCBondStatusRef
)status
;
1402 #pragma mark SCBondInterface management
1406 __bond_set_mode(int s
, CFStringRef bond_if
, CFNumberRef mode
)
1408 struct if_bond_req breq
;
1412 mode_num
= IF_BOND_MODE_LACP
;
1414 CFNumberGetValue(mode
, kCFNumberIntType
, &mode_num
);
1418 bzero(&ifr
, sizeof(ifr
));
1419 (void) _SC_cfstring_to_cstring(bond_if
,
1421 sizeof(ifr
.ifr_name
),
1422 kCFStringEncodingASCII
);
1423 ifr
.ifr_data
= (caddr_t
)&breq
;
1424 bzero(&breq
, sizeof(breq
));
1425 breq
.ibr_op
= IF_BOND_OP_SET_MODE
;
1426 breq
.ibr_ibru
.ibru_int_val
= mode_num
;
1427 if (ioctl(s
, SIOCSIFBOND
, (caddr_t
)&ifr
) == -1) {
1429 SCLog(TRUE
, LOG_ERR
,
1430 CFSTR("could not set mode to %@ on bond \"%@\": %s"),
1441 __bond_add_interface(int s
, CFStringRef bond_if
, CFStringRef interface_if
)
1443 struct if_bond_req breq
;
1447 bzero(&ifr
, sizeof(ifr
));
1448 (void) _SC_cfstring_to_cstring(bond_if
,
1450 sizeof(ifr
.ifr_name
),
1451 kCFStringEncodingASCII
);
1452 ifr
.ifr_data
= (caddr_t
)&breq
;
1455 bzero(&breq
, sizeof(breq
));
1456 breq
.ibr_op
= IF_BOND_OP_ADD_INTERFACE
;
1457 (void) _SC_cfstring_to_cstring(interface_if
,
1458 breq
.ibr_ibru
.ibru_if_name
,
1459 sizeof(breq
.ibr_ibru
.ibru_if_name
),
1460 kCFStringEncodingASCII
);
1462 // add new bond member
1463 if (ioctl(s
, SIOCSIFBOND
, (caddr_t
)&ifr
) == -1) {
1465 SCLog(TRUE
, LOG_ERR
,
1466 CFSTR("could not add interface \"%@\" to bond \"%@\": %s"),
1478 __bond_remove_interface(int s
, CFStringRef bond_if
, CFStringRef interface_if
)
1480 struct if_bond_req breq
;
1484 bzero(&ifr
, sizeof(ifr
));
1485 (void) _SC_cfstring_to_cstring(bond_if
,
1487 sizeof(ifr
.ifr_name
),
1488 kCFStringEncodingASCII
);
1489 ifr
.ifr_data
= (caddr_t
)&breq
;
1491 // bond member to remove
1492 bzero(&breq
, sizeof(breq
));
1493 breq
.ibr_op
= IF_BOND_OP_REMOVE_INTERFACE
;
1494 (void) _SC_cfstring_to_cstring(interface_if
,
1495 breq
.ibr_ibru
.ibru_if_name
,
1496 sizeof(breq
.ibr_ibru
.ibru_if_name
),
1497 kCFStringEncodingASCII
);
1499 // remove bond member
1500 if (ioctl(s
, SIOCSIFBOND
, (caddr_t
)&ifr
) == -1) {
1502 SCLog(TRUE
, LOG_ERR
,
1503 CFSTR("could not remove interface \"%@\" from bond \"%@\": %s"),
1515 _SCBondInterfaceUpdateConfiguration(SCPreferencesRef prefs
)
1517 CFArrayRef active
= NULL
;
1518 CFArrayRef config
= NULL
;
1525 if (prefs
== NULL
) {
1526 _SCErrorSet(kSCStatusInvalidArgument
);
1530 /* configured Bonds */
1531 config
= SCBondInterfaceCopyAll(prefs
);
1532 nConfig
= (config
!= NULL
) ? CFArrayGetCount(config
) : 0;
1535 active
= _SCBondInterfaceCopyActive();
1536 nActive
= (active
!= NULL
) ? CFArrayGetCount(active
) : 0;
1539 * remove any no-longer-configured bond interfaces and
1540 * any devices associated with a bond that are no longer
1541 * associated with a bond.
1543 for (i
= 0; i
< nActive
; i
++) {
1544 SCBondInterfaceRef a_bond
;
1545 CFStringRef a_bond_if
;
1547 Boolean found
= FALSE
;
1549 a_bond
= CFArrayGetValueAtIndex(active
, i
);
1550 a_bond_if
= SCNetworkInterfaceGetBSDName(a_bond
);
1552 for (j
= 0; j
< nConfig
; j
++) {
1553 SCBondInterfaceRef c_bond
;
1554 CFStringRef c_bond_if
;
1556 c_bond
= CFArrayGetValueAtIndex(config
, j
);
1557 c_bond_if
= SCNetworkInterfaceGetBSDName(c_bond
);
1559 if (CFEqual(a_bond_if
, c_bond_if
)) {
1561 CFArrayRef a_bond_interfaces
;
1563 CFArrayRef c_bond_interfaces
;
1566 c_bond_interfaces
= SCBondInterfaceGetMemberInterfaces(c_bond
);
1567 c_count
= (c_bond_interfaces
!= NULL
) ? CFArrayGetCount(c_bond_interfaces
) : 0;
1569 a_bond_interfaces
= SCBondInterfaceGetMemberInterfaces(a_bond
);
1570 a_count
= (a_bond_interfaces
!= NULL
) ? CFArrayGetCount(a_bond_interfaces
) : 0;
1572 for (a
= 0; a
< a_count
; a
++) {
1573 SCNetworkInterfaceRef a_interface
;
1574 CFStringRef a_interface_if
;
1576 a_interface
= CFArrayGetValueAtIndex(a_bond_interfaces
, a
);
1577 if ((c_count
== 0) ||
1578 !CFArrayContainsValue(c_bond_interfaces
,
1579 CFRangeMake(0, c_count
),
1582 * if this device is no longer part
1586 s
= inet_dgram_socket();
1594 a_interface_if
= SCNetworkInterfaceGetBSDName(a_interface
);
1595 if (!__bond_remove_interface(s
, a_bond_if
, a_interface_if
)) {
1608 * if this interface is no longer configured
1611 s
= inet_dgram_socket();
1619 if (!__destroyInterface(s
, a_bond_if
)) {
1627 * add any newly-configured bond interfaces and add any
1628 * devices that should now be associated with the bond.
1630 for (i
= 0; i
< nConfig
; i
++) {
1631 CFNumberRef c_bond_mode
;
1632 SCBondInterfaceRef c_bond
;
1633 CFArrayRef c_bond_interfaces
;
1634 CFStringRef c_bond_if
;
1636 Boolean found
= FALSE
;
1639 c_bond
= CFArrayGetValueAtIndex(config
, i
);
1640 c_bond_if
= SCNetworkInterfaceGetBSDName(c_bond
);
1641 c_bond_interfaces
= SCBondInterfaceGetMemberInterfaces(c_bond
);
1642 c_bond_mode
= SCBondInterfaceGetMode(c_bond
);
1643 c_count
= (c_bond_interfaces
!= NULL
) ? CFArrayGetCount(c_bond_interfaces
) : 0;
1645 for (j
= 0; j
< nActive
; j
++) {
1646 SCBondInterfaceRef a_bond
;
1647 CFArrayRef a_bond_interfaces
;
1648 CFNumberRef a_bond_mode
;
1649 CFStringRef a_bond_if
;
1652 a_bond
= CFArrayGetValueAtIndex(active
, j
);
1653 a_bond_if
= SCNetworkInterfaceGetBSDName(a_bond
);
1654 a_bond_interfaces
= SCBondInterfaceGetMemberInterfaces(a_bond
);
1655 a_bond_mode
= SCBondInterfaceGetMode(a_bond
);
1656 a_count
= (a_bond_interfaces
!= NULL
) ? CFArrayGetCount(a_bond_interfaces
) : 0;
1658 if (CFEqual(c_bond_if
, a_bond_if
)) {
1660 Boolean if_list_change
= FALSE
;
1661 Boolean mode_change
= FALSE
;
1665 if (!_SC_CFEqual(a_bond_mode
, c_bond_mode
)) {
1669 if (!_SC_CFEqual(c_bond_interfaces
, a_bond_interfaces
)) {
1670 if_list_change
= TRUE
;
1672 if (!mode_change
&& !if_list_change
) {
1673 break; // if no change
1676 s
= inet_dgram_socket();
1684 __bond_set_mode(s
, a_bond_if
, c_bond_mode
);
1686 if (!if_list_change
) {
1687 break; // no if list changes
1691 * ensure that the first device of the bond matches, if
1692 * not then we remove all current devices and add them
1693 * back in the preferred order.
1695 if ((c_count
> 0) &&
1697 !CFEqual(CFArrayGetValueAtIndex(c_bond_interfaces
, 0),
1698 CFArrayGetValueAtIndex(a_bond_interfaces
, 0))) {
1701 for (a
= 0; a
< a_count
; a
++) {
1702 SCNetworkInterfaceRef a_interface
;
1703 CFStringRef a_interface_if
;
1705 a_interface
= CFArrayGetValueAtIndex(a_bond_interfaces
, a
);
1706 if (!CFArrayContainsValue(c_bond_interfaces
,
1707 CFRangeMake(0, c_count
),
1709 continue; // if already removed
1712 a_interface_if
= SCNetworkInterfaceGetBSDName(a_interface
);
1713 if (!__bond_remove_interface(s
, a_bond_if
, a_interface_if
)) {
1718 a_count
= 0; // all active devices have been removed
1722 * add any devices which are not currently associated
1723 * with the bond interface.
1725 for (c
= 0; c
< c_count
; c
++) {
1726 SCNetworkInterfaceRef c_interface
;
1727 SCNetworkInterfacePrivateRef c_interfacePrivate
;
1728 CFStringRef c_interface_if
;
1730 c_interface
= CFArrayGetValueAtIndex(c_bond_interfaces
, c
);
1731 if ((a_count
== 0) ||
1732 !CFArrayContainsValue(a_bond_interfaces
,
1733 CFRangeMake(0, a_count
),
1736 * check if this member interface can be added to a bond.
1738 c_interfacePrivate
= (SCNetworkInterfacePrivateRef
)c_interface
;
1739 if (!c_interfacePrivate
->supportsBond
) {
1740 // if member not supported
1745 * if this member interface is not currently part of the bond.
1747 c_interface_if
= SCNetworkInterfaceGetBSDName(c_interface
);
1748 if (!__bond_add_interface(s
, c_bond_if
, c_interface_if
)) {
1749 // if member could not be added
1763 s
= inet_dgram_socket();
1772 * establish the new bond interface.
1774 if (!__createInterface(s
, c_bond_if
)) {
1781 __bond_set_mode(s
, c_bond_if
, c_bond_mode
);
1784 * add the member interfaces
1786 for (c
= 0; c
< c_count
; c
++) {
1787 SCNetworkInterfaceRef c_interface
;
1788 SCNetworkInterfacePrivateRef c_interfacePrivate
;
1789 CFStringRef c_interface_if
;
1791 c_interface
= CFArrayGetValueAtIndex(c_bond_interfaces
, c
);
1792 c_interfacePrivate
= (SCNetworkInterfacePrivateRef
)c_interface
;
1793 if (!c_interfacePrivate
->supportsBond
) {
1794 // if member not supported
1798 c_interface_if
= SCNetworkInterfaceGetBSDName(c_interface
);
1799 if (!__bond_add_interface(s
, c_bond_if
, c_interface_if
)) {
1800 // if member could not be added
1810 if (active
!= NULL
) CFRelease(active
);
1811 if (config
!= NULL
) CFRelease(config
);
1812 if (s
!= -1) (void) close(s
);