2 * Copyright (c) 2004-2011 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 <SystemConfiguration/SCValidation.h>
41 #include <SystemConfiguration/SCPrivate.h>
46 #include <sys/types.h>
47 #include <sys/ioctl.h>
48 #include <sys/socket.h>
49 #include <sys/sysctl.h>
50 #include <net/ethernet.h>
51 #define KERNEL_PRIVATE
53 #include <net/if_var.h>
55 #include <net/if_bond_var.h>
56 #include <net/if_types.h>
57 #include <net/if_media.h>
58 #include <net/route.h>
60 /* ---------- Bond support ---------- */
67 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
69 SCLog(TRUE
, LOG_ERR
, CFSTR("socket() failed: %s"), strerror(errno
));
76 siocgifmedia(int s
, const char * ifname
, int * status
, int * active
)
78 struct ifmediareq ifmr
;
82 bzero(&ifmr
, sizeof(ifmr
));
83 strncpy(ifmr
.ifm_name
, ifname
, sizeof(ifmr
.ifm_name
));
84 if (ioctl(s
, SIOCGIFMEDIA
, &ifmr
) == -1) {
87 if (ifmr
.ifm_count
!= 0) {
88 *status
= ifmr
.ifm_status
;
89 *active
= ifmr
.ifm_active
;
94 static struct if_bond_status_req
*
95 if_bond_status_req_copy(int s
, const char * ifname
)
98 struct if_bond_req ibr
;
99 struct if_bond_status_req
* ibsr_p
;
102 bzero(&ifr
, sizeof(ifr
));
103 strlcpy(ifr
.ifr_name
, ifname
, sizeof(ifr
.ifr_name
));
104 bzero((char *)&ibr
, sizeof(ibr
));
105 ibr
.ibr_op
= IF_BOND_OP_GET_STATUS
;
106 ibsr_p
= &ibr
.ibr_ibru
.ibru_status
;
107 ibsr_p
->ibsr_version
= IF_BOND_STATUS_REQ_VERSION
;
108 ifr
.ifr_data
= (caddr_t
)&ibr
;
110 /* how many of them are there? */
111 if (ioctl(s
, SIOCGIFBOND
, (caddr_t
)&ifr
) == -1) {
114 buf
= malloc(sizeof(struct if_bond_status
) * ibsr_p
->ibsr_total
+ sizeof(*ibsr_p
));
118 if (ibsr_p
->ibsr_total
== 0) {
121 ibsr_p
->ibsr_count
= ibsr_p
->ibsr_total
;
122 ibsr_p
->ibsr_buffer
= buf
+ sizeof(*ibsr_p
);
125 if (ioctl(s
, SIOCGIFBOND
, (caddr_t
)&ifr
) == -1) {
129 (*(struct if_bond_status_req
*)buf
) = *ibsr_p
;
130 return ((struct if_bond_status_req
*)buf
);
141 add_interface(CFMutableArrayRef
*interfaces
, CFStringRef if_name
)
143 SCNetworkInterfaceRef interface
;
145 if (*interfaces
== NULL
) {
146 *interfaces
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
149 interface
= _SCNetworkInterfaceCreateWithBSDName(NULL
, if_name
,
150 kIncludeNoVirtualInterfaces
);
151 CFArrayAppendValue(*interfaces
, interface
);
152 CFRelease(interface
);
157 _SCBondInterfaceSetMemberInterfaces(SCBondInterfaceRef bond
, CFArrayRef members
);
160 _SCBondInterfaceSetMode(SCBondInterfaceRef bond
, CFNumberRef mode
);
164 CFMutableArrayRef bonds
;
165 SCPreferencesRef prefs
;
166 } addContext
, *addContextRef
;
170 add_configured_interface(const void *key
, const void *value
, void *context
)
172 SCBondInterfaceRef bond
;
173 CFStringRef bond_if
= (CFStringRef
)key
;
174 CFDictionaryRef bond_info
= (CFDictionaryRef
)value
;
175 CFDictionaryRef bond_options
;
177 CFArrayRef interfaces
;
178 SCNetworkInterfacePrivateRef interfacePrivate
;
179 CFMutableArrayRef members
= NULL
;
181 addContextRef myContext
= (addContextRef
)context
;
185 // create the bond interface
186 bond
= (SCBondInterfaceRef
)_SCBondInterfaceCreatePrivate(NULL
, bond_if
);
188 // add member interfaces
189 interfaces
= CFDictionaryGetValue(bond_info
, kSCPropVirtualNetworkInterfacesBondInterfaces
);
190 n
= isA_CFArray(interfaces
) ? CFArrayGetCount(interfaces
) : 0;
191 for (i
= 0; i
< n
; i
++) {
194 member
= CFArrayGetValueAtIndex(interfaces
, i
);
195 if (isA_CFString(member
)) {
196 add_interface(&members
, member
);
199 if (members
!= NULL
) {
200 _SCBondInterfaceSetMemberInterfaces(bond
, members
);
205 name
= CFDictionaryGetValue(bond_info
, kSCPropUserDefinedName
);
206 if (isA_CFString(name
)) {
207 SCBondInterfaceSetLocalizedDisplayName(bond
, name
);
211 bond_options
= CFDictionaryGetValue(bond_info
, kSCPropVirtualNetworkInterfacesBondOptions
);
212 if (isA_CFDictionary(bond_options
)) {
213 SCBondInterfaceSetOptions(bond
, bond_options
);
217 mode
= CFDictionaryGetValue(bond_info
, kSCPropVirtualNetworkInterfacesBondMode
);
218 _SCBondInterfaceSetMode(bond
, isA_CFNumber(mode
));
220 // estabish link to the stored configuration
221 interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
222 interfacePrivate
->prefs
= CFRetain(myContext
->prefs
);
224 CFArrayAppendValue(myContext
->bonds
, bond
);
232 add_legacy_configuration(addContextRef myContext
)
237 SCPreferencesRef prefs
;
239 #define BOND_PREFERENCES_ID CFSTR("VirtualNetworkInterfaces.plist")
240 #define BOND_PREFERENCES_BONDS CFSTR("Bonds")
241 #define __kBondInterface_interface CFSTR("interface") // e.g. bond0, bond1, ...
242 #define __kBondInterface_devices CFSTR("devices") // e.g. en0, en1, ...
243 #define __kBondInterface_options CFSTR("options") // e.g. UserDefinedName
245 prefs
= SCPreferencesCreate(NULL
, CFSTR("SCBondInterfaceCopyAll"), BOND_PREFERENCES_ID
);
250 bonds
= SCPreferencesGetValue(prefs
, BOND_PREFERENCES_BONDS
);
251 if ((bonds
!= NULL
) && !isA_CFArray(bonds
)) {
252 CFRelease(prefs
); // if the prefs are confused
256 n_bonds
= (bonds
!= NULL
) ? CFArrayGetCount(bonds
) : 0;
257 for (i
= 0; i
< n_bonds
; i
++) {
258 SCBondInterfaceRef bond
;
259 CFDictionaryRef bond_dict
;
261 CFDictionaryRef dict
;
262 CFArrayRef interfaces
;
263 SCNetworkInterfacePrivateRef interfacePrivate
;
265 CFMutableArrayRef members
= NULL
;
266 CFMutableDictionaryRef newDict
;
267 CFArrayRef newInterfaces
;
268 CFIndex n_interfaces
;
270 CFDictionaryRef options
;
273 bond_dict
= CFArrayGetValueAtIndex(bonds
, i
);
274 if (!isA_CFDictionary(bond_dict
)) {
275 continue; // if the prefs are confused
278 bond_if
= CFDictionaryGetValue(bond_dict
, __kBondInterface_interface
);
279 if (!isA_CFString(bond_if
)) {
280 continue; // if the prefs are confused
283 // check if this bond has already been allocated
284 path
= CFStringCreateWithFormat(NULL
,
287 kSCPrefVirtualNetworkInterfaces
,
288 kSCNetworkInterfaceTypeBond
,
290 dict
= SCPreferencesPathGetValue(myContext
->prefs
, path
);
292 // if bond interface name not available
297 // add a placeholder for the bond in the stored preferences
298 newDict
= CFDictionaryCreateMutable(NULL
,
300 &kCFTypeDictionaryKeyCallBacks
,
301 &kCFTypeDictionaryValueCallBacks
);
302 newInterfaces
= CFArrayCreate(NULL
, NULL
, 0, &kCFTypeArrayCallBacks
);
303 CFDictionaryAddValue(newDict
, kSCPropVirtualNetworkInterfacesBondInterfaces
, newInterfaces
);
304 CFRelease(newInterfaces
);
305 ok
= SCPreferencesPathSetValue(myContext
->prefs
, path
, newDict
);
309 // if the bond could not be saved
313 // create the bond interface
314 bond
= (SCBondInterfaceRef
)_SCBondInterfaceCreatePrivate(NULL
, bond_if
);
316 // estabish link to the stored configuration
317 interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
318 interfacePrivate
->prefs
= CFRetain(myContext
->prefs
);
320 // add member interfaces
321 interfaces
= CFDictionaryGetValue(bond_dict
, __kBondInterface_devices
);
322 n_interfaces
= isA_CFArray(interfaces
) ? CFArrayGetCount(interfaces
) : 0;
323 for (j
= 0; j
< n_interfaces
; j
++) {
326 member
= CFArrayGetValueAtIndex(interfaces
, j
);
327 if (isA_CFString(member
)) {
328 add_interface(&members
, member
);
331 if (members
!= NULL
) {
332 _SCBondInterfaceSetMemberInterfaces(bond
, members
);
337 options
= CFDictionaryGetValue(bond_dict
, __kBondInterface_options
);
338 if (isA_CFDictionary(options
)) {
341 name
= CFDictionaryGetValue(options
, kSCPropUserDefinedName
);
342 if (isA_CFString(name
)) {
343 SCBondInterfaceSetLocalizedDisplayName(bond
, name
);
347 CFArrayAppendValue(myContext
->bonds
, bond
);
357 #pragma mark SCBondInterface APIs
361 SCBondInterfaceCopyAll(SCPreferencesRef prefs
)
364 CFDictionaryRef dict
;
367 context
.bonds
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
368 context
.prefs
= prefs
;
370 path
= CFStringCreateWithFormat(NULL
,
373 kSCPrefVirtualNetworkInterfaces
,
374 kSCNetworkInterfaceTypeBond
);
375 dict
= SCPreferencesPathGetValue(prefs
, path
);
376 if (isA_CFDictionary(dict
)) {
377 CFDictionaryApplyFunction(dict
, add_configured_interface
, &context
);
379 // no bond configuration, upgrade from legacy configuration
380 dict
= CFDictionaryCreate(NULL
,
382 &kCFTypeDictionaryKeyCallBacks
,
383 &kCFTypeDictionaryValueCallBacks
);
384 (void) SCPreferencesPathSetValue(prefs
, path
, dict
);
387 add_legacy_configuration(&context
);
391 return context
.bonds
;
395 __private_extern__
void
396 __SCBondInterfaceListCollectMembers(CFArrayRef interfaces
, CFMutableSetRef set
)
401 n
= CFArrayGetCount(interfaces
);
402 for (i
= 0; i
< n
; i
++) {
403 SCBondInterfaceRef bondInterface
;
406 bondInterface
= CFArrayGetValueAtIndex(interfaces
, i
);
407 members
= SCBondInterfaceGetMemberInterfaces(bondInterface
);
408 if (members
!= NULL
) {
412 // exclude the member interfaces of this bond
413 n_members
= CFArrayGetCount(members
);
414 for (j
= 0; j
< n_members
; j
++) {
415 SCNetworkInterfaceRef member
;
417 member
= CFArrayGetValueAtIndex(members
, j
);
418 CFSetAddValue(set
, member
);
427 CFArrayRef
/* of SCNetworkInterfaceRef's */
428 SCBondInterfaceCopyAvailableMemberInterfaces(SCPreferencesRef prefs
)
430 CFMutableArrayRef available
;
431 CFMutableSetRef excluded
;
432 CFArrayRef interfaces
;
434 available
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
435 excluded
= CFSetCreateMutable (NULL
, 0, &kCFTypeSetCallBacks
);
437 // exclude Bond [member] interfaces
438 interfaces
= SCBondInterfaceCopyAll(prefs
);
439 if (interfaces
!= NULL
) {
440 __SCBondInterfaceListCollectMembers(interfaces
, excluded
);
441 CFRelease(interfaces
);
444 // exclude Bridge [member] interfaces
445 interfaces
= SCBridgeInterfaceCopyAll(prefs
);
446 if (interfaces
!= NULL
) {
447 __SCBridgeInterfaceListCollectMembers(interfaces
, excluded
);
448 CFRelease(interfaces
);
451 // exclude VLAN [physical] interfaces
452 interfaces
= SCVLANInterfaceCopyAll(prefs
);
453 if (interfaces
!= NULL
) {
457 n
= CFArrayGetCount(interfaces
);
458 for (i
= 0; i
< n
; i
++) {
459 SCVLANInterfaceRef vlanInterface
;
460 SCNetworkInterfaceRef physical
;
462 // exclude the physical interface of this VLAN
463 vlanInterface
= CFArrayGetValueAtIndex(interfaces
, i
);
464 physical
= SCVLANInterfaceGetPhysicalInterface(vlanInterface
);
465 CFSetAddValue(excluded
, physical
);
467 CFRelease(interfaces
);
470 // identify available interfaces
471 interfaces
= __SCNetworkInterfaceCopyAll_IONetworkInterface();
472 if (interfaces
!= NULL
) {
476 n
= CFArrayGetCount(interfaces
);
477 for (i
= 0; i
< n
; i
++) {
478 SCNetworkInterfaceRef interface
;
479 SCNetworkInterfacePrivateRef interfacePrivate
;
481 interface
= CFArrayGetValueAtIndex(interfaces
, i
);
482 interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
484 if (!interfacePrivate
->supportsBond
) {
485 // if this interface is not available
489 if (CFSetContainsValue(excluded
, interface
)) {
494 CFArrayAppendValue(available
, interface
);
496 CFRelease(interfaces
);
506 _SCBondInterfaceCopyActive(void)
508 struct ifaddrs
*ifap
;
511 CFMutableArrayRef bonds
= NULL
;
513 if (getifaddrs(&ifap
) == -1) {
515 SCLog(TRUE
, LOG_ERR
, CFSTR("getifaddrs() failed: %s"), strerror(errno
));
519 s
= inet_dgram_socket();
525 bonds
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
527 for (ifp
= ifap
; ifp
!= NULL
; ifp
= ifp
->ifa_next
) {
528 SCBondInterfaceRef bond
;
530 struct if_bond_status_req
*ibsr_p
;
531 struct if_data
*if_data
;
534 CFMutableArrayRef members
= NULL
;
536 if_data
= (struct if_data
*)ifp
->ifa_data
;
538 || ifp
->ifa_addr
->sa_family
!= AF_LINK
539 || if_data
->ifi_type
!= IFT_IEEE8023ADLAG
) {
543 ibsr_p
= if_bond_status_req_copy(s
, ifp
->ifa_name
);
544 if (ibsr_p
== NULL
) {
545 if (errno
== EBUSY
) {
550 CFSTR("if_bond_status_req_copy(%s) failed: %s"),
558 // create the bond interface
559 bond_if
= CFStringCreateWithCString(NULL
, ifp
->ifa_name
, kCFStringEncodingASCII
);
560 bond
= (SCBondInterfaceRef
)_SCBondInterfaceCreatePrivate(NULL
, bond_if
);
564 int_val
= ibsr_p
->ibsr_mode
;
565 mode
= CFNumberCreate(NULL
, kCFNumberIntType
, &int_val
);
566 _SCBondInterfaceSetMode(bond
, mode
);
569 // add member interfaces
570 if (ibsr_p
->ibsr_total
> 0) {
572 struct if_bond_status
* ibs_p
;
574 // iterate over each member interface
575 ibs_p
= (struct if_bond_status
*)ibsr_p
->ibsr_buffer
;
576 for (i
= 0; i
< ibsr_p
->ibsr_total
; i
++) {
579 member
= CFStringCreateWithCString(NULL
, ibs_p
[i
].ibs_if_name
, kCFStringEncodingASCII
);
580 add_interface(&members
, member
);
586 if (members
!= NULL
) {
587 _SCBondInterfaceSetMemberInterfaces(bond
, members
);
592 CFArrayAppendValue(bonds
, bond
);
605 SCBondInterfaceCreate(SCPreferencesRef prefs
)
607 CFAllocatorRef allocator
;
608 SCBondInterfaceRef bond
= NULL
;
612 _SCErrorSet(kSCStatusInvalidArgument
);
616 allocator
= CFGetAllocator(prefs
);
618 // create a new bond using an unused interface name
619 for (i
= 0; bond
== NULL
; i
++) {
620 CFDictionaryRef dict
;
622 SCNetworkInterfacePrivateRef interfacePrivate
;
623 CFMutableDictionaryRef newDict
;
624 CFArrayRef newInterfaces
;
628 bond_if
= CFStringCreateWithFormat(allocator
, NULL
, CFSTR("bond%d"), i
);
629 path
= CFStringCreateWithFormat(allocator
,
632 kSCPrefVirtualNetworkInterfaces
,
633 kSCNetworkInterfaceTypeBond
,
635 dict
= SCPreferencesPathGetValue(prefs
, path
);
637 // if bond interface name not available
643 // add the bond to the stored preferences
644 newDict
= CFDictionaryCreateMutable(allocator
,
646 &kCFTypeDictionaryKeyCallBacks
,
647 &kCFTypeDictionaryValueCallBacks
);
648 newInterfaces
= CFArrayCreate(allocator
, NULL
, 0, &kCFTypeArrayCallBacks
);
649 CFDictionaryAddValue(newDict
, kSCPropVirtualNetworkInterfacesBondInterfaces
, newInterfaces
);
650 CFRelease(newInterfaces
);
651 ok
= SCPreferencesPathSetValue(prefs
, path
, newDict
);
655 // if the bond could not be saved
660 // create the SCBondInterfaceRef
661 bond
= (SCBondInterfaceRef
)_SCBondInterfaceCreatePrivate(allocator
, bond_if
);
664 // estabish link to the stored configuration
665 interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
666 interfacePrivate
->prefs
= CFRetain(prefs
);
674 SCBondInterfaceRemove(SCBondInterfaceRef bond
)
677 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
681 if (!isA_SCBondInterface(bond
)) {
682 _SCErrorSet(kSCStatusInvalidArgument
);
686 if (interfacePrivate
->prefs
== NULL
) {
687 _SCErrorSet(kSCStatusInvalidArgument
);
691 bond_if
= SCNetworkInterfaceGetBSDName(bond
);
692 path
= CFStringCreateWithFormat(NULL
,
695 kSCPrefVirtualNetworkInterfaces
,
696 kSCNetworkInterfaceTypeBond
,
698 ok
= SCPreferencesPathRemoveValue(interfacePrivate
->prefs
, path
);
706 SCBondInterfaceGetMemberInterfaces(SCBondInterfaceRef bond
)
708 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
710 if (!isA_SCBondInterface(bond
)) {
711 _SCErrorSet(kSCStatusInvalidArgument
);
715 return interfacePrivate
->bond
.interfaces
;
720 SCBondInterfaceGetOptions(SCBondInterfaceRef bond
)
722 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
724 if (!isA_SCBondInterface(bond
)) {
725 _SCErrorSet(kSCStatusInvalidArgument
);
729 return interfacePrivate
->bond
.options
;
734 _SCBondInterfaceSetMemberInterfaces(SCBondInterfaceRef bond
, CFArrayRef members
)
737 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
739 CFMutableArrayRef newMembers
;
742 n
= (members
!= NULL
) ? CFArrayGetCount(members
) : 0;
744 // set member interfaces in the stored preferences
745 if (interfacePrivate
->prefs
!= NULL
) {
746 CFDictionaryRef dict
;
747 CFMutableDictionaryRef newDict
;
750 path
= CFStringCreateWithFormat(NULL
,
753 kSCPrefVirtualNetworkInterfaces
,
754 kSCNetworkInterfaceTypeBond
,
755 interfacePrivate
->entity_device
);
756 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
757 if (!isA_CFDictionary(dict
)) {
758 // if the prefs are confused
760 _SCErrorSet(kSCStatusFailed
);
764 newMembers
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
765 for (i
= 0; i
< n
; i
++) {
766 SCNetworkInterfaceRef interface
;
767 CFStringRef memberName
;
769 interface
= CFArrayGetValueAtIndex(members
, i
);
770 memberName
= SCNetworkInterfaceGetBSDName(interface
);
771 CFArrayAppendValue(newMembers
, memberName
);
774 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
775 CFDictionarySetValue(newDict
, kSCPropVirtualNetworkInterfacesBondInterfaces
, newMembers
);
776 CFRelease(newMembers
);
778 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
784 newMembers
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
785 for (i
= 0; i
< n
; i
++) {
786 SCNetworkInterfaceRef member
;
787 SCNetworkInterfacePrivateRef newMember
;
789 member
= CFArrayGetValueAtIndex(members
, i
);
790 newMember
= __SCNetworkInterfaceCreateCopy(NULL
,
792 interfacePrivate
->prefs
,
793 interfacePrivate
->serviceID
);
794 CFArrayAppendValue(newMembers
, newMember
);
795 CFRelease(newMember
);
797 CFRelease(interfacePrivate
->bond
.interfaces
);
798 interfacePrivate
->bond
.interfaces
= newMembers
;
806 SCBondInterfaceSetMemberInterfaces(SCBondInterfaceRef bond
, CFArrayRef members
)
808 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
810 int sc_status
= kSCStatusOK
;
812 if (!isA_SCBondInterface(bond
)) {
813 _SCErrorSet(kSCStatusInvalidArgument
);
817 if ((members
!= NULL
) && !isA_CFArray(members
)) {
818 _SCErrorSet(kSCStatusInvalidArgument
);
822 if (interfacePrivate
->prefs
!= NULL
) {
823 CFArrayRef available
;
829 CFArrayRef services
= NULL
;
831 current
= SCBondInterfaceGetMemberInterfaces(bond
);
832 n_current
= (current
!= NULL
) ? CFArrayGetCount(current
) : 0;
834 available
= SCBondInterfaceCopyAvailableMemberInterfaces(interfacePrivate
->prefs
);
835 n_available
= (available
!= NULL
) ? CFArrayGetCount(available
) : 0;
837 n_members
= (members
!= NULL
) ? CFArrayGetCount(members
) : 0;
838 for (i
= 0; i
< n_members
; i
++) {
839 SCNetworkInterfaceRef member
;
841 member
= CFArrayGetValueAtIndex(members
, i
);
843 if ((current
!= NULL
) &&
844 CFArrayContainsValue(current
, CFRangeMake(0, n_current
), member
)) {
845 // current members are allowed
849 if ((available
!= NULL
) &&
850 CFArrayContainsValue(available
, CFRangeMake(0, n_available
), member
)) {
851 // available members are allowed but cannot be associated
852 // with any other network services.
854 if (services
== NULL
) {
855 services
= __SCNetworkServiceCopyAllEnabled(interfacePrivate
->prefs
);
857 if ((services
!= NULL
) &&
858 __SCNetworkServiceExistsForInterface(services
, member
)) {
859 sc_status
= kSCStatusKeyExists
;
867 // if member not allowed
868 sc_status
= kSCStatusInvalidArgument
;
872 if (available
!= NULL
) CFRelease(available
);
873 if (services
!= NULL
) CFRelease(services
);
876 if (sc_status
!= kSCStatusOK
) {
877 _SCErrorSet(sc_status
);
881 ok
= _SCBondInterfaceSetMemberInterfaces(bond
, members
);
887 SCBondInterfaceSetLocalizedDisplayName(SCBondInterfaceRef bond
, CFStringRef newName
)
889 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
892 if (!isA_SCBondInterface(bond
)) {
893 _SCErrorSet(kSCStatusInvalidArgument
);
897 if ((newName
!= NULL
) && !isA_CFString(newName
)) {
898 _SCErrorSet(kSCStatusInvalidArgument
);
902 // set name in the stored preferences
903 if (interfacePrivate
->prefs
!= NULL
) {
904 CFDictionaryRef dict
;
905 CFMutableDictionaryRef newDict
;
908 path
= CFStringCreateWithFormat(NULL
,
911 kSCPrefVirtualNetworkInterfaces
,
912 kSCNetworkInterfaceTypeBond
,
913 interfacePrivate
->entity_device
);
914 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
915 if (!isA_CFDictionary(dict
)) {
916 // if the prefs are confused
918 _SCErrorSet(kSCStatusFailed
);
922 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
923 if (newName
!= NULL
) {
924 CFDictionarySetValue(newDict
, kSCPropUserDefinedName
, newName
);
926 CFDictionaryRemoveValue(newDict
, kSCPropUserDefinedName
);
928 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
933 // set name in the SCBondInterfaceRef
935 if (interfacePrivate
->localized_name
!= NULL
) {
936 CFRelease(interfacePrivate
->localized_name
);
937 interfacePrivate
->localized_name
= NULL
;
939 if (newName
!= NULL
) {
940 interfacePrivate
->localized_name
= CFStringCreateCopy(NULL
, newName
);
949 SCBondInterfaceSetOptions(SCBondInterfaceRef bond
, CFDictionaryRef newOptions
)
951 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
954 if (!isA_SCBondInterface(bond
)) {
955 _SCErrorSet(kSCStatusInvalidArgument
);
959 if ((newOptions
!= NULL
) && !isA_CFDictionary(newOptions
)) {
960 _SCErrorSet(kSCStatusInvalidArgument
);
964 // set options in the stored preferences
965 if (interfacePrivate
->prefs
!= NULL
) {
966 CFDictionaryRef dict
;
967 CFMutableDictionaryRef newDict
;
970 path
= CFStringCreateWithFormat(NULL
,
973 kSCPrefVirtualNetworkInterfaces
,
974 kSCNetworkInterfaceTypeBond
,
975 interfacePrivate
->entity_device
);
976 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
977 if (!isA_CFDictionary(dict
)) {
978 // if the prefs are confused
980 _SCErrorSet(kSCStatusFailed
);
984 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
985 if (newOptions
!= NULL
) {
986 CFDictionarySetValue(newDict
, kSCPropVirtualNetworkInterfacesBondOptions
, newOptions
);
988 CFDictionaryRemoveValue(newDict
, kSCPropVirtualNetworkInterfacesBondOptions
);
990 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
995 // set options in the SCBondInterfaceRef
997 if (interfacePrivate
->bond
.options
!= NULL
) {
998 CFRelease(interfacePrivate
->bond
.options
);
999 interfacePrivate
->bond
.options
= NULL
;
1001 if (newOptions
!= NULL
) {
1002 interfacePrivate
->bond
.options
= CFDictionaryCreateCopy(NULL
, newOptions
);
1011 _SCBondInterfaceSetMode(SCBondInterfaceRef bond
, CFNumberRef mode
)
1013 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
1014 Boolean needs_release
= FALSE
;
1018 int mode_num
= IF_BOND_MODE_LACP
;
1020 mode
= CFNumberCreate(NULL
, kCFNumberIntType
, &mode_num
);
1021 needs_release
= TRUE
;
1024 // set mode in the stored preferences
1025 if (interfacePrivate
->prefs
!= NULL
) {
1026 CFDictionaryRef dict
;
1027 CFMutableDictionaryRef newDict
;
1030 path
= CFStringCreateWithFormat(NULL
,
1033 kSCPrefVirtualNetworkInterfaces
,
1034 kSCNetworkInterfaceTypeBond
,
1035 interfacePrivate
->entity_device
);
1036 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
1037 if (!isA_CFDictionary(dict
)) {
1038 // if the prefs are confused
1040 _SCErrorSet(kSCStatusFailed
);
1044 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
1045 CFDictionarySetValue(newDict
, kSCPropVirtualNetworkInterfacesBondMode
, mode
);
1047 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
1054 if (interfacePrivate
->bond
.mode
!= NULL
) {
1055 CFRelease(interfacePrivate
->bond
.mode
);
1057 interfacePrivate
->bond
.mode
= mode
;
1062 if (needs_release
) CFRelease(mode
);
1067 SCBondInterfaceSetMode(SCBondInterfaceRef bond
, CFNumberRef mode
)
1071 if (!isA_SCBondInterface(bond
) || !isA_CFNumber(mode
)) {
1072 _SCErrorSet(kSCStatusInvalidArgument
);
1076 if (CFNumberGetValue(mode
, kCFNumberIntType
, &mode_num
) == FALSE
) {
1077 _SCErrorSet(kSCStatusInvalidArgument
);
1082 case IF_BOND_MODE_LACP
:
1083 case IF_BOND_MODE_STATIC
:
1086 _SCErrorSet(kSCStatusInvalidArgument
);
1090 return (_SCBondInterfaceSetMode(bond
, mode
));
1094 SCBondInterfaceGetMode(SCBondInterfaceRef bond
)
1096 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
1098 if (!isA_SCBondInterface(bond
)) {
1099 _SCErrorSet(kSCStatusInvalidArgument
);
1102 return (interfacePrivate
->bond
.mode
);
1107 #pragma mark SCBondStatus APIs
1112 // base CFType information
1113 CFRuntimeBase cfBase
;
1116 SCBondInterfaceRef bond
;
1117 CFDictionaryRef status_bond
;
1119 // member interfaces and status
1120 CFArrayRef interfaces
; // of SCNetworkInterfaceRef's
1121 CFDictionaryRef status_interfaces
; // key = interface, val = interface status)
1123 } SCBondStatusPrivate
, * SCBondStatusPrivateRef
;
1126 const CFStringRef kSCBondStatusDeviceAggregationStatus
= CFSTR("AggregationStatus");
1127 const CFStringRef kSCBondStatusDeviceCollecting
= CFSTR("Collecting");
1128 const CFStringRef kSCBondStatusDeviceDistributing
= CFSTR("Distributing");
1131 static CFStringRef
__SCBondStatusCopyDescription (CFTypeRef cf
);
1132 static void __SCBondStatusDeallocate (CFTypeRef cf
);
1133 static Boolean
__SCBondStatusEqual (CFTypeRef cf1
, CFTypeRef cf2
);
1136 static const CFRuntimeClass __SCBondStatusClass
= {
1138 "BondStatus", // className
1141 __SCBondStatusDeallocate
, // dealloc
1142 __SCBondStatusEqual
, // equal
1144 NULL
, // copyFormattingDesc
1145 __SCBondStatusCopyDescription
// copyDebugDesc
1149 static CFTypeID __kSCBondStatusTypeID
= _kCFRuntimeNotATypeID
;
1152 static pthread_once_t bondStatus_init
= PTHREAD_ONCE_INIT
;
1156 __SCBondStatusCopyDescription(CFTypeRef cf
)
1158 CFAllocatorRef allocator
= CFGetAllocator(cf
);
1159 CFMutableStringRef result
;
1160 SCBondStatusPrivateRef statusPrivate
= (SCBondStatusPrivateRef
)cf
;
1162 result
= CFStringCreateMutable(allocator
, 0);
1163 CFStringAppendFormat(result
, NULL
, CFSTR("<SCBondStatus %p [%p]> {"), cf
, allocator
);
1164 CFStringAppendFormat(result
, NULL
, CFSTR(" bond = %@"), statusPrivate
->bond
);
1165 CFStringAppendFormat(result
, NULL
, CFSTR(", interface = %@"), statusPrivate
->status_bond
);
1166 CFStringAppendFormat(result
, NULL
, CFSTR(", members = %@"), statusPrivate
->status_interfaces
);
1167 CFStringAppendFormat(result
, NULL
, CFSTR(" }"));
1174 __SCBondStatusDeallocate(CFTypeRef cf
)
1176 SCBondStatusPrivateRef statusPrivate
= (SCBondStatusPrivateRef
)cf
;
1178 /* release resources */
1180 CFRelease(statusPrivate
->bond
);
1181 CFRelease(statusPrivate
->status_bond
);
1182 if (statusPrivate
->interfaces
!= NULL
) CFRelease(statusPrivate
->interfaces
);
1183 CFRelease(statusPrivate
->status_interfaces
);
1189 __SCBondStatusEqual(CFTypeRef cf1
, CFTypeRef cf2
)
1191 SCBondStatusPrivateRef status1
= (SCBondStatusPrivateRef
)cf1
;
1192 SCBondStatusPrivateRef status2
= (SCBondStatusPrivateRef
)cf2
;
1194 if (status1
== status2
)
1197 if (!CFEqual(status1
->bond
, status2
->bond
))
1198 return FALSE
; // if not the same bond
1200 if (!CFEqual(status1
->status_bond
, status2
->status_bond
))
1201 return FALSE
; // if not the same interface status
1203 if (!CFEqual(status1
->status_interfaces
, status2
->status_interfaces
))
1204 return FALSE
; // if not the same status of the member interfaces
1211 __SCBondStatusInitialize(void)
1213 __kSCBondStatusTypeID
= _CFRuntimeRegisterClass(&__SCBondStatusClass
);
1218 static SCBondStatusRef
1219 __SCBondStatusCreatePrivate(CFAllocatorRef allocator
,
1220 SCBondInterfaceRef bond
,
1221 CFDictionaryRef status_bond
,
1222 CFDictionaryRef status_interfaces
)
1224 SCBondStatusPrivateRef statusPrivate
;
1227 /* initialize runtime */
1228 pthread_once(&bondStatus_init
, __SCBondStatusInitialize
);
1231 size
= sizeof(SCBondStatusPrivate
) - sizeof(CFRuntimeBase
);
1232 statusPrivate
= (SCBondStatusPrivateRef
)_CFRuntimeCreateInstance(allocator
,
1233 __kSCBondStatusTypeID
,
1236 if (statusPrivate
== NULL
) {
1240 /* establish the bond status */
1242 statusPrivate
->bond
= CFRetain(bond
);
1243 statusPrivate
->status_bond
= CFDictionaryCreateCopy(NULL
, status_bond
);
1245 statusPrivate
->interfaces
= NULL
;
1246 statusPrivate
->status_interfaces
= CFDictionaryCreateCopy(NULL
, status_interfaces
);
1248 return (SCBondStatusRef
)statusPrivate
;
1252 static __inline__ CFTypeRef
1253 isA_SCBondStatus(CFTypeRef obj
)
1255 return (isA_CFType(obj
, SCBondStatusGetTypeID()));
1260 SCBondStatusGetTypeID()
1262 pthread_once(&bondStatus_init
, __SCBondStatusInitialize
); /* initialize runtime */
1263 return __kSCBondStatusTypeID
;
1270 CFArrayRef
/* of SCNetworkInterfaceRef's */
1271 SCBondStatusGetMemberInterfaces(SCBondStatusRef bondStatus
)
1273 SCBondStatusPrivateRef statusPrivate
= (SCBondStatusPrivateRef
)bondStatus
;
1275 if (!isA_SCBondStatus(bondStatus
)) {
1279 if (statusPrivate
->interfaces
== NULL
) {
1280 const void * keys_q
[N_QUICK
];
1281 const void ** keys
= keys_q
;
1284 n
= CFDictionaryGetCount(statusPrivate
->status_interfaces
);
1285 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
1286 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
1288 CFDictionaryGetKeysAndValues(statusPrivate
->status_interfaces
, keys
, NULL
);
1289 statusPrivate
->interfaces
= CFArrayCreate(NULL
, keys
, n
, &kCFTypeArrayCallBacks
);
1290 if (keys
!= keys_q
) {
1291 CFAllocatorDeallocate(NULL
, keys
);
1295 return statusPrivate
->interfaces
;
1300 SCBondStatusGetInterfaceStatus(SCBondStatusRef bondStatus
, SCNetworkInterfaceRef interface
)
1302 CFDictionaryRef status
= NULL
;
1303 SCBondStatusPrivateRef statusPrivate
= (SCBondStatusPrivateRef
)bondStatus
;
1305 if (!isA_SCBondStatus(bondStatus
)) {
1309 if (interface
== NULL
) {
1310 // return status of the bond
1311 status
= statusPrivate
->status_bond
;
1313 // return status of the member interface
1314 status
= CFDictionaryGetValue(statusPrivate
->status_interfaces
, interface
);
1322 SCBondInterfaceCopyStatus(SCBondInterfaceRef bond
)
1327 struct if_bond_status_req
*ibsr_p
= NULL
;
1328 char if_name
[IFNAMSIZ
];
1332 struct if_bond_status
*scan_p
;
1333 SCBondStatusRef status
= NULL
;
1334 CFMutableDictionaryRef status_bond
;
1335 CFMutableDictionaryRef status_interfaces
;
1337 if (!isA_SCBondInterface(bond
)) {
1338 _SCErrorSet(kSCStatusInvalidArgument
);
1342 s
= inet_dgram_socket();
1348 _SC_cfstring_to_cstring(SCNetworkInterfaceGetBSDName(bond
),
1351 kCFStringEncodingASCII
);
1352 if (siocgifmedia(s
, if_name
, &bond_if_status
, &bond_if_active
) == -1) {
1359 SCLog(TRUE
, LOG_ERR
,
1360 CFSTR("siocgifmedia(%s) failed: %s"),
1366 ibsr_p
= if_bond_status_req_copy(s
, if_name
);
1367 if (ibsr_p
== NULL
) {
1372 status_bond
= CFDictionaryCreateMutable(NULL
,
1374 &kCFTypeDictionaryKeyCallBacks
,
1375 &kCFTypeDictionaryValueCallBacks
);
1377 status_interfaces
= CFDictionaryCreateMutable(NULL
,
1379 &kCFTypeDictionaryKeyCallBacks
,
1380 &kCFTypeDictionaryValueCallBacks
);
1381 n
= ibsr_p
->ibsr_total
;
1382 for (i
= 0, scan_p
= (struct if_bond_status
*)ibsr_p
->ibsr_buffer
; i
< n
; i
++, scan_p
++) {
1384 int distributing
= 0;
1385 SCNetworkInterfaceRef interface
;
1386 CFStringRef interface_name
;
1387 struct if_bond_partner_state
* ps
;
1388 CFMutableDictionaryRef status_interface
;
1391 ps
= &scan_p
->ibs_partner_state
;
1393 if (lacp_actor_partner_state_in_sync(scan_p
->ibs_state
)) {
1395 status_val
= kSCBondStatusOK
;
1396 if (lacp_actor_partner_state_in_sync(ps
->ibps_state
)) {
1397 /* partner is also in-sync */
1398 if (lacp_actor_partner_state_collecting(scan_p
->ibs_state
)
1399 && lacp_actor_partner_state_distributing(ps
->ibps_state
)) {
1400 /* we're able to collect (receive) frames */
1403 if (lacp_actor_partner_state_distributing(scan_p
->ibs_state
)
1404 && lacp_actor_partner_state_collecting(ps
->ibps_state
)) {
1405 /* we're able to distribute (transmit) frames */
1412 static lacp_system zeroes
= { {0, 0, 0, 0, 0, 0}};
1414 if (siocgifmedia(s
, scan_p
->ibs_if_name
, &status
, &active
) == -1) {
1420 SCLog(TRUE
, LOG_ERR
,
1421 CFSTR("siocgifmedia(%s) failed: %s"),
1427 if (((status
& IFM_AVALID
) == 0) ||
1428 ((status
& IFM_ACTIVE
) == 0) ||
1429 ((active
& IFM_FDX
) == 0)) {
1430 /* link down or not full-duplex */
1431 status_val
= kSCBondStatusLinkInvalid
;
1432 } else if ((ps
->ibps_system_priority
== 0) &&
1433 (bcmp(&zeroes
, &ps
->ibps_system
, sizeof(zeroes
)) == 0)) {
1434 /* no one on the other end of the link */
1435 status_val
= kSCBondStatusNoPartner
;
1436 } else if (active
!= bond_if_active
) {
1437 /* the link speed was different */
1438 status_val
= kSCBondStatusLinkInvalid
;
1440 /* partner is not in the active group */
1441 status_val
= kSCBondStatusNotInActiveGroup
;
1446 strlcpy(if_name
, scan_p
->ibs_if_name
, sizeof(if_name
));
1447 interface_name
= CFStringCreateWithCString(NULL
, if_name
, kCFStringEncodingASCII
);
1448 interface
= _SCNetworkInterfaceCreateWithBSDName(NULL
, interface_name
,
1449 kIncludeNoVirtualInterfaces
);
1450 CFRelease(interface_name
);
1453 status_interface
= CFDictionaryCreateMutable(NULL
,
1455 &kCFTypeDictionaryKeyCallBacks
,
1456 &kCFTypeDictionaryValueCallBacks
);
1457 num
= CFNumberCreate(NULL
, kCFNumberIntType
, &status_val
);
1458 CFDictionarySetValue(status_interface
, kSCBondStatusDeviceAggregationStatus
, num
);
1460 num
= CFNumberCreate(NULL
, kCFNumberIntType
, &collecting
);
1461 CFDictionarySetValue(status_interface
, kSCBondStatusDeviceCollecting
, num
);
1463 num
= CFNumberCreate(NULL
, kCFNumberIntType
, &distributing
);
1464 CFDictionarySetValue(status_interface
, kSCBondStatusDeviceDistributing
, num
);
1467 CFDictionarySetValue(status_interfaces
, interface
, status_interface
);
1468 CFRelease(interface
);
1469 CFRelease(status_interface
);
1472 status
= __SCBondStatusCreatePrivate(NULL
, bond
, status_bond
, status_interfaces
);
1473 CFRelease(status_bond
);
1474 CFRelease(status_interfaces
);
1481 if (ibsr_p
!= NULL
) {
1484 return (SCBondStatusRef
)status
;
1489 #pragma mark SCBondInterface management
1493 __bond_set_mode(int s
, CFStringRef bond_if
, CFNumberRef mode
)
1495 struct if_bond_req breq
;
1499 mode_num
= IF_BOND_MODE_LACP
;
1501 CFNumberGetValue(mode
, kCFNumberIntType
, &mode_num
);
1505 bzero(&ifr
, sizeof(ifr
));
1506 (void) _SC_cfstring_to_cstring(bond_if
,
1508 sizeof(ifr
.ifr_name
),
1509 kCFStringEncodingASCII
);
1510 ifr
.ifr_data
= (caddr_t
)&breq
;
1511 bzero(&breq
, sizeof(breq
));
1512 breq
.ibr_op
= IF_BOND_OP_SET_MODE
;
1513 breq
.ibr_ibru
.ibru_int_val
= mode_num
;
1514 if (ioctl(s
, SIOCSIFBOND
, (caddr_t
)&ifr
) == -1) {
1516 SCLog(TRUE
, LOG_ERR
,
1517 CFSTR("could not set mode to %d on bond \"%@\": %s"),
1528 __bond_add_interface(int s
, CFStringRef bond_if
, CFStringRef interface_if
)
1530 struct if_bond_req breq
;
1534 bzero(&ifr
, sizeof(ifr
));
1535 (void) _SC_cfstring_to_cstring(bond_if
,
1537 sizeof(ifr
.ifr_name
),
1538 kCFStringEncodingASCII
);
1539 ifr
.ifr_data
= (caddr_t
)&breq
;
1542 bzero(&breq
, sizeof(breq
));
1543 breq
.ibr_op
= IF_BOND_OP_ADD_INTERFACE
;
1544 (void) _SC_cfstring_to_cstring(interface_if
,
1545 breq
.ibr_ibru
.ibru_if_name
,
1546 sizeof(breq
.ibr_ibru
.ibru_if_name
),
1547 kCFStringEncodingASCII
);
1549 // add new bond member
1550 if (ioctl(s
, SIOCSIFBOND
, (caddr_t
)&ifr
) == -1) {
1552 SCLog(TRUE
, LOG_ERR
,
1553 CFSTR("could not add interface \"%@\" to bond \"%@\": %s"),
1565 __bond_remove_interface(int s
, CFStringRef bond_if
, CFStringRef interface_if
)
1567 struct if_bond_req breq
;
1571 bzero(&ifr
, sizeof(ifr
));
1572 (void) _SC_cfstring_to_cstring(bond_if
,
1574 sizeof(ifr
.ifr_name
),
1575 kCFStringEncodingASCII
);
1576 ifr
.ifr_data
= (caddr_t
)&breq
;
1578 // bond member to remove
1579 bzero(&breq
, sizeof(breq
));
1580 breq
.ibr_op
= IF_BOND_OP_REMOVE_INTERFACE
;
1581 (void) _SC_cfstring_to_cstring(interface_if
,
1582 breq
.ibr_ibru
.ibru_if_name
,
1583 sizeof(breq
.ibr_ibru
.ibru_if_name
),
1584 kCFStringEncodingASCII
);
1586 // remove bond member
1587 if (ioctl(s
, SIOCSIFBOND
, (caddr_t
)&ifr
) == -1) {
1589 SCLog(TRUE
, LOG_ERR
,
1590 CFSTR("could not remove interface \"%@\" from bond \"%@\": %s"),
1602 _SCBondInterfaceUpdateConfiguration(SCPreferencesRef prefs
)
1604 CFArrayRef active
= NULL
;
1605 CFArrayRef config
= NULL
;
1612 if (prefs
== NULL
) {
1613 _SCErrorSet(kSCStatusInvalidArgument
);
1617 /* configured Bonds */
1618 config
= SCBondInterfaceCopyAll(prefs
);
1619 nConfig
= (config
!= NULL
) ? CFArrayGetCount(config
) : 0;
1622 active
= _SCBondInterfaceCopyActive();
1623 nActive
= (active
!= NULL
) ? CFArrayGetCount(active
) : 0;
1626 * remove any no-longer-configured bond interfaces and
1627 * any devices associated with a bond that are no longer
1628 * associated with a bond.
1630 for (i
= 0; i
< nActive
; i
++) {
1631 SCBondInterfaceRef a_bond
;
1632 CFStringRef a_bond_if
;
1634 Boolean found
= FALSE
;
1636 a_bond
= CFArrayGetValueAtIndex(active
, i
);
1637 a_bond_if
= SCNetworkInterfaceGetBSDName(a_bond
);
1639 for (j
= 0; j
< nConfig
; j
++) {
1640 SCBondInterfaceRef c_bond
;
1641 CFStringRef c_bond_if
;
1643 c_bond
= CFArrayGetValueAtIndex(config
, j
);
1644 c_bond_if
= SCNetworkInterfaceGetBSDName(c_bond
);
1646 if (CFEqual(a_bond_if
, c_bond_if
)) {
1648 CFArrayRef a_bond_interfaces
;
1650 CFArrayRef c_bond_interfaces
;
1653 c_bond_interfaces
= SCBondInterfaceGetMemberInterfaces(c_bond
);
1654 c_count
= (c_bond_interfaces
!= NULL
) ? CFArrayGetCount(c_bond_interfaces
) : 0;
1656 a_bond_interfaces
= SCBondInterfaceGetMemberInterfaces(a_bond
);
1657 a_count
= (a_bond_interfaces
!= NULL
) ? CFArrayGetCount(a_bond_interfaces
) : 0;
1659 for (a
= 0; a
< a_count
; a
++) {
1660 SCNetworkInterfaceRef a_interface
;
1661 CFStringRef a_interface_if
;
1663 a_interface
= CFArrayGetValueAtIndex(a_bond_interfaces
, a
);
1664 if ((c_count
== 0) ||
1665 !CFArrayContainsValue(c_bond_interfaces
,
1666 CFRangeMake(0, c_count
),
1669 * if this device is no longer part
1673 s
= inet_dgram_socket();
1681 a_interface_if
= SCNetworkInterfaceGetBSDName(a_interface
);
1682 if (!__bond_remove_interface(s
, a_bond_if
, a_interface_if
)) {
1695 * if this interface is no longer configured
1698 s
= inet_dgram_socket();
1706 if (!__destroyInterface(s
, a_bond_if
)) {
1714 * add any newly-configured bond interfaces and add any
1715 * devices that should now be associated with the bond.
1717 for (i
= 0; i
< nConfig
; i
++) {
1718 CFNumberRef c_bond_mode
;
1719 SCBondInterfaceRef c_bond
;
1720 CFArrayRef c_bond_interfaces
;
1721 CFStringRef c_bond_if
;
1723 Boolean found
= FALSE
;
1726 c_bond
= CFArrayGetValueAtIndex(config
, i
);
1727 c_bond_if
= SCNetworkInterfaceGetBSDName(c_bond
);
1728 c_bond_interfaces
= SCBondInterfaceGetMemberInterfaces(c_bond
);
1729 c_bond_mode
= SCBondInterfaceGetMode(c_bond
);
1730 c_count
= (c_bond_interfaces
!= NULL
) ? CFArrayGetCount(c_bond_interfaces
) : 0;
1732 for (j
= 0; j
< nActive
; j
++) {
1733 SCBondInterfaceRef a_bond
;
1734 CFArrayRef a_bond_interfaces
;
1735 CFNumberRef a_bond_mode
;
1736 CFStringRef a_bond_if
;
1739 a_bond
= CFArrayGetValueAtIndex(active
, j
);
1740 a_bond_if
= SCNetworkInterfaceGetBSDName(a_bond
);
1741 a_bond_interfaces
= SCBondInterfaceGetMemberInterfaces(a_bond
);
1742 a_bond_mode
= SCBondInterfaceGetMode(a_bond
);
1743 a_count
= (a_bond_interfaces
!= NULL
) ? CFArrayGetCount(a_bond_interfaces
) : 0;
1745 if (CFEqual(c_bond_if
, a_bond_if
)) {
1747 Boolean if_list_change
= FALSE
;
1748 Boolean mode_change
= FALSE
;
1752 if (!_SC_CFEqual(a_bond_mode
, c_bond_mode
)) {
1756 if (!_SC_CFEqual(c_bond_interfaces
, a_bond_interfaces
)) {
1757 if_list_change
= TRUE
;
1759 if (!mode_change
&& !if_list_change
) {
1760 break; // if no change
1763 s
= inet_dgram_socket();
1771 __bond_set_mode(s
, a_bond_if
, c_bond_mode
);
1773 if (!if_list_change
) {
1774 break; // no if list changes
1778 * ensure that the first device of the bond matches, if
1779 * not then we remove all current devices and add them
1780 * back in the preferred order.
1782 if ((c_count
> 0) &&
1784 !CFEqual(CFArrayGetValueAtIndex(c_bond_interfaces
, 0),
1785 CFArrayGetValueAtIndex(a_bond_interfaces
, 0))) {
1788 for (a
= 0; a
< a_count
; a
++) {
1789 SCNetworkInterfaceRef a_interface
;
1790 CFStringRef a_interface_if
;
1792 a_interface
= CFArrayGetValueAtIndex(a_bond_interfaces
, a
);
1793 if (!CFArrayContainsValue(c_bond_interfaces
,
1794 CFRangeMake(0, c_count
),
1796 continue; // if already removed
1799 a_interface_if
= SCNetworkInterfaceGetBSDName(a_interface
);
1800 if (!__bond_remove_interface(s
, a_bond_if
, a_interface_if
)) {
1805 a_count
= 0; // all active devices have been removed
1809 * add any devices which are not currently associated
1810 * with the bond interface.
1812 for (c
= 0; c
< c_count
; c
++) {
1813 SCNetworkInterfaceRef c_interface
;
1814 SCNetworkInterfacePrivateRef c_interfacePrivate
;
1815 CFStringRef c_interface_if
;
1817 c_interface
= CFArrayGetValueAtIndex(c_bond_interfaces
, c
);
1818 if ((a_count
== 0) ||
1819 !CFArrayContainsValue(a_bond_interfaces
,
1820 CFRangeMake(0, a_count
),
1823 * check if this member interface can be added to a bond.
1825 c_interfacePrivate
= (SCNetworkInterfacePrivateRef
)c_interface
;
1826 if (!c_interfacePrivate
->supportsBond
) {
1827 // if member not supported
1832 * if this member interface is not currently part of the bond.
1834 c_interface_if
= SCNetworkInterfaceGetBSDName(c_interface
);
1835 if (!__bond_add_interface(s
, c_bond_if
, c_interface_if
)) {
1836 // if member could not be added
1850 s
= inet_dgram_socket();
1859 * establish the new bond interface.
1861 if (!__createInterface(s
, c_bond_if
)) {
1868 __bond_set_mode(s
, c_bond_if
, c_bond_mode
);
1871 * add the member interfaces
1873 for (c
= 0; c
< c_count
; c
++) {
1874 SCNetworkInterfaceRef c_interface
;
1875 SCNetworkInterfacePrivateRef c_interfacePrivate
;
1876 CFStringRef c_interface_if
;
1878 c_interface
= CFArrayGetValueAtIndex(c_bond_interfaces
, c
);
1879 c_interfacePrivate
= (SCNetworkInterfacePrivateRef
)c_interface
;
1880 if (!c_interfacePrivate
->supportsBond
) {
1881 // if member not supported
1885 c_interface_if
= SCNetworkInterfaceGetBSDName(c_interface
);
1886 if (!__bond_add_interface(s
, c_bond_if
, c_interface_if
)) {
1887 // if member could not be added
1897 if (active
!= NULL
) CFRelease(active
);
1898 if (config
!= NULL
) CFRelease(config
);
1899 if (s
!= -1) (void) close(s
);