2 * Copyright (c) 2004-2009 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 strncpy(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 __SCBondInterfaceListCopyMembers(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 exclude
;
432 CFArrayRef interfaces
;
434 available
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
435 exclude
= CFSetCreateMutable (NULL
, 0, &kCFTypeSetCallBacks
);
437 // exclude Bond [member] interfaces
438 interfaces
= SCBondInterfaceCopyAll(prefs
);
439 if (interfaces
!= NULL
) {
440 __SCBondInterfaceListCopyMembers(interfaces
, exclude
);
441 CFRelease(interfaces
);
444 // exclude VLAN [physical] interfaces
445 interfaces
= SCVLANInterfaceCopyAll(prefs
);
446 if (interfaces
!= NULL
) {
450 n
= CFArrayGetCount(interfaces
);
451 for (i
= 0; i
< n
; i
++) {
452 SCVLANInterfaceRef vlanInterface
;
453 SCNetworkInterfaceRef physical
;
455 // exclude the physical interface of this VLAN
456 vlanInterface
= CFArrayGetValueAtIndex(interfaces
, i
);
457 physical
= SCVLANInterfaceGetPhysicalInterface(vlanInterface
);
458 CFSetAddValue(exclude
, physical
);
460 CFRelease(interfaces
);
463 // identify available interfaces
464 interfaces
= __SCNetworkInterfaceCopyAll_IONetworkInterface();
465 if (interfaces
!= NULL
) {
469 n
= CFArrayGetCount(interfaces
);
470 for (i
= 0; i
< n
; i
++) {
471 SCNetworkInterfaceRef interface
;
472 SCNetworkInterfacePrivateRef interfacePrivate
;
474 interface
= CFArrayGetValueAtIndex(interfaces
, i
);
475 interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
477 if (!interfacePrivate
->supportsBond
) {
478 // if this interface is not available
482 if (CFSetContainsValue(exclude
, interface
)) {
487 CFArrayAppendValue(available
, interface
);
489 CFRelease(interfaces
);
499 _SCBondInterfaceCopyActive(void)
501 struct ifaddrs
*ifap
;
504 CFMutableArrayRef bonds
= NULL
;
506 if (getifaddrs(&ifap
) == -1) {
508 SCLog(TRUE
, LOG_ERR
, CFSTR("getifaddrs() failed: %s"), strerror(errno
));
512 s
= inet_dgram_socket();
518 bonds
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
520 for (ifp
= ifap
; ifp
!= NULL
; ifp
= ifp
->ifa_next
) {
521 SCBondInterfaceRef bond
;
523 struct if_bond_status_req
*ibsr_p
;
524 struct if_data
*if_data
;
527 CFMutableArrayRef members
= NULL
;
529 if_data
= (struct if_data
*)ifp
->ifa_data
;
531 || ifp
->ifa_addr
->sa_family
!= AF_LINK
532 || if_data
->ifi_type
!= IFT_IEEE8023ADLAG
) {
536 ibsr_p
= if_bond_status_req_copy(s
, ifp
->ifa_name
);
537 if (ibsr_p
== NULL
) {
538 if (errno
== EBUSY
) {
543 CFSTR("if_bond_status_req_copy(%s) failed: %s"),
551 // create the bond interface
552 bond_if
= CFStringCreateWithCString(NULL
, ifp
->ifa_name
, kCFStringEncodingASCII
);
553 bond
= (SCBondInterfaceRef
)_SCBondInterfaceCreatePrivate(NULL
, bond_if
);
557 int_val
= ibsr_p
->ibsr_mode
;
558 mode
= CFNumberCreate(NULL
, kCFNumberIntType
, &int_val
);
559 _SCBondInterfaceSetMode(bond
, mode
);
562 // add member interfaces
563 if (ibsr_p
->ibsr_total
> 0) {
565 struct if_bond_status
* ibs_p
;
567 // iterate over each member interface
568 ibs_p
= (struct if_bond_status
*)ibsr_p
->ibsr_buffer
;
569 for (i
= 0; i
< ibsr_p
->ibsr_total
; i
++) {
570 char if_name
[IFNAMSIZ
+ 1];
573 bzero(&if_name
, sizeof(if_name
));
574 bcopy(ibs_p
[i
].ibs_if_name
, if_name
, IFNAMSIZ
);
575 member
= CFStringCreateWithCString(NULL
, if_name
, kCFStringEncodingASCII
);
576 add_interface(&members
, member
);
582 if (members
!= NULL
) {
583 _SCBondInterfaceSetMemberInterfaces(bond
, members
);
588 CFArrayAppendValue(bonds
, bond
);
601 SCBondInterfaceCreate(SCPreferencesRef prefs
)
603 CFAllocatorRef allocator
;
604 SCBondInterfaceRef bond
= NULL
;
608 _SCErrorSet(kSCStatusInvalidArgument
);
612 allocator
= CFGetAllocator(prefs
);
614 // create a new bond using an unused interface name
615 for (i
= 0; bond
== NULL
; i
++) {
616 CFDictionaryRef dict
;
618 SCNetworkInterfacePrivateRef interfacePrivate
;
619 CFMutableDictionaryRef newDict
;
620 CFArrayRef newInterfaces
;
624 bond_if
= CFStringCreateWithFormat(allocator
, NULL
, CFSTR("bond%d"), i
);
625 path
= CFStringCreateWithFormat(allocator
,
628 kSCPrefVirtualNetworkInterfaces
,
629 kSCNetworkInterfaceTypeBond
,
631 dict
= SCPreferencesPathGetValue(prefs
, path
);
633 // if bond interface name not available
639 // add the bond to the stored preferences
640 newDict
= CFDictionaryCreateMutable(allocator
,
642 &kCFTypeDictionaryKeyCallBacks
,
643 &kCFTypeDictionaryValueCallBacks
);
644 newInterfaces
= CFArrayCreate(allocator
, NULL
, 0, &kCFTypeArrayCallBacks
);
645 CFDictionaryAddValue(newDict
, kSCPropVirtualNetworkInterfacesBondInterfaces
, newInterfaces
);
646 CFRelease(newInterfaces
);
647 ok
= SCPreferencesPathSetValue(prefs
, path
, newDict
);
651 // if the bond could not be saved
656 // create the SCBondInterfaceRef
657 bond
= (SCBondInterfaceRef
)_SCBondInterfaceCreatePrivate(allocator
, bond_if
);
660 // estabish link to the stored configuration
661 interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
662 interfacePrivate
->prefs
= CFRetain(prefs
);
670 SCBondInterfaceRemove(SCBondInterfaceRef bond
)
673 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
677 if (!isA_SCBondInterface(bond
)) {
678 _SCErrorSet(kSCStatusInvalidArgument
);
682 if (interfacePrivate
->prefs
== NULL
) {
683 _SCErrorSet(kSCStatusInvalidArgument
);
687 bond_if
= SCNetworkInterfaceGetBSDName(bond
);
688 path
= CFStringCreateWithFormat(NULL
,
691 kSCPrefVirtualNetworkInterfaces
,
692 kSCNetworkInterfaceTypeBond
,
694 ok
= SCPreferencesPathRemoveValue(interfacePrivate
->prefs
, path
);
702 SCBondInterfaceGetMemberInterfaces(SCBondInterfaceRef bond
)
704 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
706 if (!isA_SCBondInterface(bond
)) {
707 _SCErrorSet(kSCStatusInvalidArgument
);
711 return interfacePrivate
->bond
.interfaces
;
716 SCBondInterfaceGetOptions(SCBondInterfaceRef bond
)
718 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
720 if (!isA_SCBondInterface(bond
)) {
721 _SCErrorSet(kSCStatusInvalidArgument
);
725 return interfacePrivate
->bond
.options
;
730 _SCBondInterfaceSetMemberInterfaces(SCBondInterfaceRef bond
, CFArrayRef members
)
733 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
735 CFMutableArrayRef newMembers
;
738 n
= (members
!= NULL
) ? CFArrayGetCount(members
) : 0;
740 // set member interfaces in the stored preferences
741 if (interfacePrivate
->prefs
!= NULL
) {
742 CFDictionaryRef dict
;
743 CFMutableDictionaryRef newDict
;
746 path
= CFStringCreateWithFormat(NULL
,
749 kSCPrefVirtualNetworkInterfaces
,
750 kSCNetworkInterfaceTypeBond
,
751 interfacePrivate
->entity_device
);
752 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
753 if (!isA_CFDictionary(dict
)) {
754 // if the prefs are confused
756 _SCErrorSet(kSCStatusFailed
);
760 newMembers
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
761 for (i
= 0; i
< n
; i
++) {
762 SCNetworkInterfaceRef interface
;
763 CFStringRef memberName
;
765 interface
= CFArrayGetValueAtIndex(members
, i
);
766 memberName
= SCNetworkInterfaceGetBSDName(interface
);
767 CFArrayAppendValue(newMembers
, memberName
);
770 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
771 CFDictionarySetValue(newDict
, kSCPropVirtualNetworkInterfacesBondInterfaces
, newMembers
);
772 CFRelease(newMembers
);
774 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
780 newMembers
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
781 for (i
= 0; i
< n
; i
++) {
782 SCNetworkInterfaceRef member
;
783 SCNetworkInterfacePrivateRef newMember
;
785 member
= CFArrayGetValueAtIndex(members
, i
);
786 newMember
= __SCNetworkInterfaceCreateCopy(NULL
,
788 interfacePrivate
->prefs
,
789 interfacePrivate
->serviceID
);
790 CFArrayAppendValue(newMembers
, newMember
);
791 CFRelease(newMember
);
793 CFRelease(interfacePrivate
->bond
.interfaces
);
794 interfacePrivate
->bond
.interfaces
= newMembers
;
802 SCBondInterfaceSetMemberInterfaces(SCBondInterfaceRef bond
, CFArrayRef members
)
804 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
807 if (!isA_SCBondInterface(bond
)) {
808 _SCErrorSet(kSCStatusInvalidArgument
);
812 if ((members
!= NULL
) && !isA_CFArray(members
)) {
813 _SCErrorSet(kSCStatusInvalidArgument
);
817 if (interfacePrivate
->prefs
!= NULL
) {
818 CFArrayRef available
;
825 current
= SCBondInterfaceGetMemberInterfaces(bond
);
826 n_current
= (current
!= NULL
) ? CFArrayGetCount(current
) : 0;
828 available
= SCBondInterfaceCopyAvailableMemberInterfaces(interfacePrivate
->prefs
);
829 n_available
= (available
!= NULL
) ? CFArrayGetCount(available
) : 0;
831 n_members
= (members
!= NULL
) ? CFArrayGetCount(members
) : 0;
832 for (i
= 0; i
< n_members
; i
++) {
833 SCNetworkInterfaceRef member
;
835 member
= CFArrayGetValueAtIndex(members
, i
);
837 if ((current
!= NULL
) &&
838 CFArrayContainsValue(current
, CFRangeMake(0, n_current
), member
)) {
839 // current members are allowed
843 if ((available
!= NULL
) &&
844 CFArrayContainsValue(available
, CFRangeMake(0, n_available
), member
)) {
845 // available members are allowed
849 // if member not allowed
854 CFRelease(available
);
857 _SCErrorSet(kSCStatusInvalidArgument
);
862 ok
= _SCBondInterfaceSetMemberInterfaces(bond
, members
);
870 SCBondInterfaceSetLocalizedDisplayName(SCBondInterfaceRef bond
, CFStringRef newName
)
872 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
875 if (!isA_SCBondInterface(bond
)) {
876 _SCErrorSet(kSCStatusInvalidArgument
);
880 if ((newName
!= NULL
) && !isA_CFString(newName
)) {
881 _SCErrorSet(kSCStatusInvalidArgument
);
885 // set name in the stored preferences
886 if (interfacePrivate
->prefs
!= NULL
) {
887 CFDictionaryRef dict
;
888 CFMutableDictionaryRef newDict
;
891 path
= CFStringCreateWithFormat(NULL
,
894 kSCPrefVirtualNetworkInterfaces
,
895 kSCNetworkInterfaceTypeBond
,
896 interfacePrivate
->entity_device
);
897 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
898 if (!isA_CFDictionary(dict
)) {
899 // if the prefs are confused
901 _SCErrorSet(kSCStatusFailed
);
905 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
906 if (newName
!= NULL
) {
907 CFDictionarySetValue(newDict
, kSCPropUserDefinedName
, newName
);
909 CFDictionaryRemoveValue(newDict
, kSCPropUserDefinedName
);
911 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
916 // set name in the SCBondInterfaceRef
918 if (interfacePrivate
->localized_name
!= NULL
) {
919 CFRelease(interfacePrivate
->localized_name
);
920 interfacePrivate
->localized_name
= NULL
;
922 if (newName
!= NULL
) {
923 interfacePrivate
->localized_name
= CFStringCreateCopy(NULL
, newName
);
932 SCBondInterfaceSetOptions(SCBondInterfaceRef bond
, CFDictionaryRef newOptions
)
934 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
937 if (!isA_SCBondInterface(bond
)) {
938 _SCErrorSet(kSCStatusInvalidArgument
);
942 if ((newOptions
!= NULL
) && !isA_CFDictionary(newOptions
)) {
943 _SCErrorSet(kSCStatusInvalidArgument
);
947 // set options in the stored preferences
948 if (interfacePrivate
->prefs
!= NULL
) {
949 CFDictionaryRef dict
;
950 CFMutableDictionaryRef newDict
;
953 path
= CFStringCreateWithFormat(NULL
,
956 kSCPrefVirtualNetworkInterfaces
,
957 kSCNetworkInterfaceTypeBond
,
958 interfacePrivate
->entity_device
);
959 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
960 if (!isA_CFDictionary(dict
)) {
961 // if the prefs are confused
963 _SCErrorSet(kSCStatusFailed
);
967 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
968 if (newOptions
!= NULL
) {
969 CFDictionarySetValue(newDict
, kSCPropVirtualNetworkInterfacesBondOptions
, newOptions
);
971 CFDictionaryRemoveValue(newDict
, kSCPropVirtualNetworkInterfacesBondOptions
);
973 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
978 // set options in the SCBondInterfaceRef
980 if (interfacePrivate
->bond
.options
!= NULL
) {
981 CFRelease(interfacePrivate
->bond
.options
);
982 interfacePrivate
->bond
.options
= NULL
;
984 if (newOptions
!= NULL
) {
985 interfacePrivate
->bond
.options
= CFDictionaryCreateCopy(NULL
, newOptions
);
994 _SCBondInterfaceSetMode(SCBondInterfaceRef bond
, CFNumberRef mode
)
996 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
997 Boolean needs_release
= FALSE
;
1001 int mode_num
= IF_BOND_MODE_LACP
;
1003 mode
= CFNumberCreate(NULL
, kCFNumberIntType
, &mode_num
);
1004 needs_release
= TRUE
;
1007 // set mode in the stored preferences
1008 if (interfacePrivate
->prefs
!= NULL
) {
1009 CFDictionaryRef dict
;
1010 CFMutableDictionaryRef newDict
;
1013 path
= CFStringCreateWithFormat(NULL
,
1016 kSCPrefVirtualNetworkInterfaces
,
1017 kSCNetworkInterfaceTypeBond
,
1018 interfacePrivate
->entity_device
);
1019 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
1020 if (!isA_CFDictionary(dict
)) {
1021 // if the prefs are confused
1023 _SCErrorSet(kSCStatusFailed
);
1027 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
1028 CFDictionarySetValue(newDict
, kSCPropVirtualNetworkInterfacesBondMode
, mode
);
1030 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
1037 if (interfacePrivate
->bond
.mode
!= NULL
) {
1038 CFRelease(interfacePrivate
->bond
.mode
);
1040 interfacePrivate
->bond
.mode
= mode
;
1045 if (needs_release
) CFRelease(mode
);
1050 SCBondInterfaceSetMode(SCBondInterfaceRef bond
, CFNumberRef mode
)
1054 if (!isA_SCBondInterface(bond
) || !isA_CFNumber(mode
)) {
1055 _SCErrorSet(kSCStatusInvalidArgument
);
1059 if (CFNumberGetValue(mode
, kCFNumberIntType
, &mode_num
) == FALSE
) {
1060 _SCErrorSet(kSCStatusInvalidArgument
);
1065 case IF_BOND_MODE_LACP
:
1066 case IF_BOND_MODE_STATIC
:
1069 _SCErrorSet(kSCStatusInvalidArgument
);
1073 return (_SCBondInterfaceSetMode(bond
, mode
));
1077 SCBondInterfaceGetMode(SCBondInterfaceRef bond
)
1079 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bond
;
1081 if (!isA_SCBondInterface(bond
)) {
1082 _SCErrorSet(kSCStatusInvalidArgument
);
1085 return (interfacePrivate
->bond
.mode
);
1090 #pragma mark SCBondStatus APIs
1095 // base CFType information
1096 CFRuntimeBase cfBase
;
1099 SCBondInterfaceRef bond
;
1100 CFDictionaryRef status_bond
;
1102 // member interfaces and status
1103 CFArrayRef interfaces
; // of SCNetworkInterfaceRef's
1104 CFDictionaryRef status_interfaces
; // key = interface, val = interface status)
1106 } SCBondStatusPrivate
, * SCBondStatusPrivateRef
;
1109 const CFStringRef kSCBondStatusDeviceAggregationStatus
= CFSTR("AggregationStatus");
1110 const CFStringRef kSCBondStatusDeviceCollecting
= CFSTR("Collecting");
1111 const CFStringRef kSCBondStatusDeviceDistributing
= CFSTR("Distributing");
1114 static CFStringRef
__SCBondStatusCopyDescription (CFTypeRef cf
);
1115 static void __SCBondStatusDeallocate (CFTypeRef cf
);
1116 static Boolean
__SCBondStatusEqual (CFTypeRef cf1
, CFTypeRef cf2
);
1119 static const CFRuntimeClass __SCBondStatusClass
= {
1121 "BondStatus", // className
1124 __SCBondStatusDeallocate
, // dealloc
1125 __SCBondStatusEqual
, // equal
1127 NULL
, // copyFormattingDesc
1128 __SCBondStatusCopyDescription
// copyDebugDesc
1132 static CFTypeID __kSCBondStatusTypeID
= _kCFRuntimeNotATypeID
;
1135 static pthread_once_t bondStatus_init
= PTHREAD_ONCE_INIT
;
1139 __SCBondStatusCopyDescription(CFTypeRef cf
)
1141 CFAllocatorRef allocator
= CFGetAllocator(cf
);
1142 CFMutableStringRef result
;
1143 SCBondStatusPrivateRef statusPrivate
= (SCBondStatusPrivateRef
)cf
;
1145 result
= CFStringCreateMutable(allocator
, 0);
1146 CFStringAppendFormat(result
, NULL
, CFSTR("<SCBondStatus %p [%p]> {"), cf
, allocator
);
1147 CFStringAppendFormat(result
, NULL
, CFSTR(" bond = %@"), statusPrivate
->bond
);
1148 CFStringAppendFormat(result
, NULL
, CFSTR(", interface = %@"), statusPrivate
->status_bond
);
1149 CFStringAppendFormat(result
, NULL
, CFSTR(", members = %@"), statusPrivate
->status_interfaces
);
1150 CFStringAppendFormat(result
, NULL
, CFSTR(" }"));
1157 __SCBondStatusDeallocate(CFTypeRef cf
)
1159 SCBondStatusPrivateRef statusPrivate
= (SCBondStatusPrivateRef
)cf
;
1161 /* release resources */
1163 CFRelease(statusPrivate
->bond
);
1164 CFRelease(statusPrivate
->status_bond
);
1165 if (statusPrivate
->interfaces
!= NULL
) CFRelease(statusPrivate
->interfaces
);
1166 CFRelease(statusPrivate
->status_interfaces
);
1172 __SCBondStatusEqual(CFTypeRef cf1
, CFTypeRef cf2
)
1174 SCBondStatusPrivateRef status1
= (SCBondStatusPrivateRef
)cf1
;
1175 SCBondStatusPrivateRef status2
= (SCBondStatusPrivateRef
)cf2
;
1177 if (status1
== status2
)
1180 if (!CFEqual(status1
->bond
, status2
->bond
))
1181 return FALSE
; // if not the same bond
1183 if (!CFEqual(status1
->status_bond
, status2
->status_bond
))
1184 return FALSE
; // if not the same interface status
1186 if (!CFEqual(status1
->status_interfaces
, status2
->status_interfaces
))
1187 return FALSE
; // if not the same status of the member interfaces
1194 __SCBondStatusInitialize(void)
1196 __kSCBondStatusTypeID
= _CFRuntimeRegisterClass(&__SCBondStatusClass
);
1201 static SCBondStatusRef
1202 __SCBondStatusCreatePrivate(CFAllocatorRef allocator
,
1203 SCBondInterfaceRef bond
,
1204 CFDictionaryRef status_bond
,
1205 CFDictionaryRef status_interfaces
)
1207 SCBondStatusPrivateRef statusPrivate
;
1210 /* initialize runtime */
1211 pthread_once(&bondStatus_init
, __SCBondStatusInitialize
);
1214 size
= sizeof(SCBondStatusPrivate
) - sizeof(CFRuntimeBase
);
1215 statusPrivate
= (SCBondStatusPrivateRef
)_CFRuntimeCreateInstance(allocator
,
1216 __kSCBondStatusTypeID
,
1219 if (statusPrivate
== NULL
) {
1223 /* establish the bond status */
1225 statusPrivate
->bond
= CFRetain(bond
);
1226 statusPrivate
->status_bond
= CFDictionaryCreateCopy(NULL
, status_bond
);
1228 statusPrivate
->interfaces
= NULL
;
1229 statusPrivate
->status_interfaces
= CFDictionaryCreateCopy(NULL
, status_interfaces
);
1231 return (SCBondStatusRef
)statusPrivate
;
1235 static __inline__ CFTypeRef
1236 isA_SCBondStatus(CFTypeRef obj
)
1238 return (isA_CFType(obj
, SCBondStatusGetTypeID()));
1243 SCBondStatusGetTypeID()
1245 pthread_once(&bondStatus_init
, __SCBondStatusInitialize
); /* initialize runtime */
1246 return __kSCBondStatusTypeID
;
1253 CFArrayRef
/* of SCNetworkInterfaceRef's */
1254 SCBondStatusGetMemberInterfaces(SCBondStatusRef bondStatus
)
1256 SCBondStatusPrivateRef statusPrivate
= (SCBondStatusPrivateRef
)bondStatus
;
1258 if (!isA_SCBondStatus(bondStatus
)) {
1262 if (statusPrivate
->interfaces
== NULL
) {
1263 const void * keys_q
[N_QUICK
];
1264 const void ** keys
= keys_q
;
1267 n
= CFDictionaryGetCount(statusPrivate
->status_interfaces
);
1268 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
1269 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
1271 CFDictionaryGetKeysAndValues(statusPrivate
->status_interfaces
, keys
, NULL
);
1272 statusPrivate
->interfaces
= CFArrayCreate(NULL
, keys
, n
, &kCFTypeArrayCallBacks
);
1273 if (keys
!= keys_q
) {
1274 CFAllocatorDeallocate(NULL
, keys
);
1278 return statusPrivate
->interfaces
;
1283 SCBondStatusGetInterfaceStatus(SCBondStatusRef bondStatus
, SCNetworkInterfaceRef interface
)
1285 CFDictionaryRef status
= NULL
;
1286 SCBondStatusPrivateRef statusPrivate
= (SCBondStatusPrivateRef
)bondStatus
;
1288 if (!isA_SCBondStatus(bondStatus
)) {
1292 if (interface
== NULL
) {
1293 // return status of the bond
1294 status
= statusPrivate
->status_bond
;
1296 // return status of the member interface
1297 status
= CFDictionaryGetValue(statusPrivate
->status_interfaces
, interface
);
1305 SCBondInterfaceCopyStatus(SCBondInterfaceRef bond
)
1310 struct if_bond_status_req
*ibsr_p
= NULL
;
1311 char if_name
[IFNAMSIZ
+ 1];
1315 struct if_bond_status
*scan_p
;
1316 SCBondStatusRef status
= NULL
;
1317 CFMutableDictionaryRef status_bond
;
1318 CFMutableDictionaryRef status_interfaces
;
1320 if (!isA_SCBondInterface(bond
)) {
1321 _SCErrorSet(kSCStatusInvalidArgument
);
1325 s
= inet_dgram_socket();
1331 _SC_cfstring_to_cstring(SCNetworkInterfaceGetBSDName(bond
),
1334 kCFStringEncodingASCII
);
1335 if (siocgifmedia(s
, if_name
, &bond_if_status
, &bond_if_active
) == -1) {
1342 SCLog(TRUE
, LOG_ERR
,
1343 CFSTR("siocgifmedia(%s) failed: %s"),
1349 ibsr_p
= if_bond_status_req_copy(s
, if_name
);
1350 if (ibsr_p
== NULL
) {
1355 status_bond
= CFDictionaryCreateMutable(NULL
,
1357 &kCFTypeDictionaryKeyCallBacks
,
1358 &kCFTypeDictionaryValueCallBacks
);
1360 status_interfaces
= CFDictionaryCreateMutable(NULL
,
1362 &kCFTypeDictionaryKeyCallBacks
,
1363 &kCFTypeDictionaryValueCallBacks
);
1364 n
= ibsr_p
->ibsr_total
;
1365 for (i
= 0, scan_p
= (struct if_bond_status
*)ibsr_p
->ibsr_buffer
; i
< n
; i
++, scan_p
++) {
1367 int distributing
= 0;
1368 SCNetworkInterfaceRef interface
;
1369 CFStringRef interface_name
;
1370 struct if_bond_partner_state
* ps
;
1371 CFMutableDictionaryRef status_interface
;
1374 ps
= &scan_p
->ibs_partner_state
;
1376 if (lacp_actor_partner_state_in_sync(scan_p
->ibs_state
)) {
1378 status_val
= kSCBondStatusOK
;
1379 if (lacp_actor_partner_state_in_sync(ps
->ibps_state
)) {
1380 /* partner is also in-sync */
1381 if (lacp_actor_partner_state_collecting(scan_p
->ibs_state
)
1382 && lacp_actor_partner_state_distributing(ps
->ibps_state
)) {
1383 /* we're able to collect (receive) frames */
1386 if (lacp_actor_partner_state_distributing(scan_p
->ibs_state
)
1387 && lacp_actor_partner_state_collecting(ps
->ibps_state
)) {
1388 /* we're able to distribute (transmit) frames */
1395 static lacp_system zeroes
= { {0, 0, 0, 0, 0, 0}};
1397 if (siocgifmedia(s
, scan_p
->ibs_if_name
, &status
, &active
) == -1) {
1403 SCLog(TRUE
, LOG_ERR
,
1404 CFSTR("siocgifmedia(%s) failed: %s"),
1410 if (((status
& IFM_AVALID
) == 0) ||
1411 ((status
& IFM_ACTIVE
) == 0) ||
1412 ((active
& IFM_FDX
) == 0)) {
1413 /* link down or not full-duplex */
1414 status_val
= kSCBondStatusLinkInvalid
;
1415 } else if ((ps
->ibps_system_priority
== 0) &&
1416 (bcmp(&zeroes
, &ps
->ibps_system
, sizeof(zeroes
)) == 0)) {
1417 /* no one on the other end of the link */
1418 status_val
= kSCBondStatusNoPartner
;
1419 } else if (active
!= bond_if_active
) {
1420 /* the link speed was different */
1421 status_val
= kSCBondStatusLinkInvalid
;
1423 /* partner is not in the active group */
1424 status_val
= kSCBondStatusNotInActiveGroup
;
1429 bzero(&if_name
, sizeof(if_name
));
1430 bcopy(scan_p
->ibs_if_name
, if_name
, IFNAMSIZ
);
1431 interface_name
= CFStringCreateWithCString(NULL
, if_name
, kCFStringEncodingASCII
);
1432 interface
= _SCNetworkInterfaceCreateWithBSDName(NULL
, interface_name
,
1433 kIncludeNoVirtualInterfaces
);
1434 CFRelease(interface_name
);
1437 status_interface
= CFDictionaryCreateMutable(NULL
,
1439 &kCFTypeDictionaryKeyCallBacks
,
1440 &kCFTypeDictionaryValueCallBacks
);
1441 num
= CFNumberCreate(NULL
, kCFNumberIntType
, &status_val
);
1442 CFDictionarySetValue(status_interface
, kSCBondStatusDeviceAggregationStatus
, num
);
1444 num
= CFNumberCreate(NULL
, kCFNumberIntType
, &collecting
);
1445 CFDictionarySetValue(status_interface
, kSCBondStatusDeviceCollecting
, num
);
1447 num
= CFNumberCreate(NULL
, kCFNumberIntType
, &distributing
);
1448 CFDictionarySetValue(status_interface
, kSCBondStatusDeviceDistributing
, num
);
1451 CFDictionarySetValue(status_interfaces
, interface
, status_interface
);
1452 CFRelease(interface
);
1453 CFRelease(status_interface
);
1456 status
= __SCBondStatusCreatePrivate(NULL
, bond
, status_bond
, status_interfaces
);
1457 CFRelease(status_bond
);
1458 CFRelease(status_interfaces
);
1465 if (ibsr_p
!= NULL
) {
1468 return (SCBondStatusRef
)status
;
1473 #pragma mark SCBondInterface management
1477 __bond_set_mode(int s
, CFStringRef bond_if
, CFNumberRef mode
)
1479 struct if_bond_req breq
;
1483 mode_num
= IF_BOND_MODE_LACP
;
1485 CFNumberGetValue(mode
, kCFNumberIntType
, &mode_num
);
1489 bzero(&ifr
, sizeof(ifr
));
1490 (void) _SC_cfstring_to_cstring(bond_if
,
1492 sizeof(ifr
.ifr_name
),
1493 kCFStringEncodingASCII
);
1494 ifr
.ifr_data
= (caddr_t
)&breq
;
1495 bzero(&breq
, sizeof(breq
));
1496 breq
.ibr_op
= IF_BOND_OP_SET_MODE
;
1497 breq
.ibr_ibru
.ibru_int_val
= mode_num
;
1498 if (ioctl(s
, SIOCSIFBOND
, (caddr_t
)&ifr
) == -1) {
1500 SCLog(TRUE
, LOG_ERR
,
1501 CFSTR("could not set mode to %d on bond \"%@\": %s"),
1512 __bond_add_interface(int s
, CFStringRef bond_if
, CFStringRef interface_if
)
1514 struct if_bond_req breq
;
1518 bzero(&ifr
, sizeof(ifr
));
1519 (void) _SC_cfstring_to_cstring(bond_if
,
1521 sizeof(ifr
.ifr_name
),
1522 kCFStringEncodingASCII
);
1523 ifr
.ifr_data
= (caddr_t
)&breq
;
1526 bzero(&breq
, sizeof(breq
));
1527 breq
.ibr_op
= IF_BOND_OP_ADD_INTERFACE
;
1528 (void) _SC_cfstring_to_cstring(interface_if
,
1529 breq
.ibr_ibru
.ibru_if_name
,
1530 sizeof(breq
.ibr_ibru
.ibru_if_name
),
1531 kCFStringEncodingASCII
);
1533 // add new bond member
1534 if (ioctl(s
, SIOCSIFBOND
, (caddr_t
)&ifr
) == -1) {
1536 SCLog(TRUE
, LOG_ERR
,
1537 CFSTR("could not add interface \"%@\" to bond \"%@\": %s"),
1549 __bond_remove_interface(int s
, CFStringRef bond_if
, CFStringRef interface_if
)
1551 struct if_bond_req breq
;
1555 bzero(&ifr
, sizeof(ifr
));
1556 (void) _SC_cfstring_to_cstring(bond_if
,
1558 sizeof(ifr
.ifr_name
),
1559 kCFStringEncodingASCII
);
1560 ifr
.ifr_data
= (caddr_t
)&breq
;
1562 // bond member to remove
1563 bzero(&breq
, sizeof(breq
));
1564 breq
.ibr_op
= IF_BOND_OP_REMOVE_INTERFACE
;
1565 (void) _SC_cfstring_to_cstring(interface_if
,
1566 breq
.ibr_ibru
.ibru_if_name
,
1567 sizeof(breq
.ibr_ibru
.ibru_if_name
),
1568 kCFStringEncodingASCII
);
1570 // remove bond member
1571 if (ioctl(s
, SIOCSIFBOND
, (caddr_t
)&ifr
) == -1) {
1573 SCLog(TRUE
, LOG_ERR
,
1574 CFSTR("could not remove interface \"%@\" from bond \"%@\": %s"),
1586 _SCBondInterfaceUpdateConfiguration(SCPreferencesRef prefs
)
1588 CFArrayRef active
= NULL
;
1589 CFArrayRef config
= NULL
;
1596 if (prefs
== NULL
) {
1597 _SCErrorSet(kSCStatusInvalidArgument
);
1601 /* configured Bonds */
1602 config
= SCBondInterfaceCopyAll(prefs
);
1603 nConfig
= CFArrayGetCount(config
);
1606 active
= _SCBondInterfaceCopyActive();
1607 nActive
= CFArrayGetCount(active
);
1610 * remove any no-longer-configured bond interfaces and
1611 * any devices associated with a bond that are no longer
1612 * associated with a bond.
1614 for (i
= 0; i
< nActive
; i
++) {
1615 SCBondInterfaceRef a_bond
;
1616 CFStringRef a_bond_if
;
1618 Boolean found
= FALSE
;
1620 a_bond
= CFArrayGetValueAtIndex(active
, i
);
1621 a_bond_if
= SCNetworkInterfaceGetBSDName(a_bond
);
1623 for (j
= 0; j
< nConfig
; j
++) {
1624 SCBondInterfaceRef c_bond
;
1625 CFStringRef c_bond_if
;
1627 c_bond
= CFArrayGetValueAtIndex(config
, j
);
1628 c_bond_if
= SCNetworkInterfaceGetBSDName(c_bond
);
1630 if (CFEqual(a_bond_if
, c_bond_if
)) {
1632 CFArrayRef a_bond_interfaces
;
1634 CFArrayRef c_bond_interfaces
;
1637 c_bond_interfaces
= SCBondInterfaceGetMemberInterfaces(c_bond
);
1638 c_count
= (c_bond_interfaces
!= NULL
) ? CFArrayGetCount(c_bond_interfaces
) : 0;
1640 a_bond_interfaces
= SCBondInterfaceGetMemberInterfaces(a_bond
);
1641 a_count
= (a_bond_interfaces
!= NULL
) ? CFArrayGetCount(a_bond_interfaces
) : 0;
1643 for (a
= 0; a
< a_count
; a
++) {
1644 SCNetworkInterfaceRef a_interface
;
1645 CFStringRef a_interface_if
;
1647 a_interface
= CFArrayGetValueAtIndex(a_bond_interfaces
, a
);
1648 if ((c_count
== 0) ||
1649 !CFArrayContainsValue(c_bond_interfaces
,
1650 CFRangeMake(0, c_count
),
1653 * if this device is no longer part
1657 s
= inet_dgram_socket();
1665 a_interface_if
= SCNetworkInterfaceGetBSDName(a_interface
);
1666 if (!__bond_remove_interface(s
, a_bond_if
, a_interface_if
)) {
1679 * if this interface is no longer configured
1682 s
= inet_dgram_socket();
1690 if (!__destroyInterface(s
, a_bond_if
)) {
1698 * add any newly-configured bond interfaces and add any
1699 * devices that should now be associated with the bond.
1701 for (i
= 0; i
< nConfig
; i
++) {
1702 CFNumberRef c_bond_mode
;
1703 SCBondInterfaceRef c_bond
;
1704 CFArrayRef c_bond_interfaces
;
1705 CFStringRef c_bond_if
;
1707 Boolean found
= FALSE
;
1710 c_bond
= CFArrayGetValueAtIndex(config
, i
);
1711 c_bond_if
= SCNetworkInterfaceGetBSDName(c_bond
);
1712 c_bond_interfaces
= SCBondInterfaceGetMemberInterfaces(c_bond
);
1713 c_bond_mode
= SCBondInterfaceGetMode(c_bond
);
1714 c_count
= (c_bond_interfaces
!= NULL
) ? CFArrayGetCount(c_bond_interfaces
) : 0;
1716 for (j
= 0; j
< nActive
; j
++) {
1717 SCBondInterfaceRef a_bond
;
1718 CFArrayRef a_bond_interfaces
;
1719 CFNumberRef a_bond_mode
;
1720 CFStringRef a_bond_if
;
1723 a_bond
= CFArrayGetValueAtIndex(active
, j
);
1724 a_bond_if
= SCNetworkInterfaceGetBSDName(a_bond
);
1725 a_bond_interfaces
= SCBondInterfaceGetMemberInterfaces(a_bond
);
1726 a_bond_mode
= SCBondInterfaceGetMode(a_bond
);
1727 a_count
= (a_bond_interfaces
!= NULL
) ? CFArrayGetCount(a_bond_interfaces
) : 0;
1729 if (CFEqual(c_bond_if
, a_bond_if
)) {
1731 Boolean if_list_change
= FALSE
;
1732 Boolean mode_change
= FALSE
;
1736 if (!_SC_CFEqual(a_bond_mode
, c_bond_mode
)) {
1740 if (!_SC_CFEqual(c_bond_interfaces
, a_bond_interfaces
)) {
1741 if_list_change
= TRUE
;
1743 if (!mode_change
&& !if_list_change
) {
1744 break; // if no change
1747 s
= inet_dgram_socket();
1755 __bond_set_mode(s
, a_bond_if
, c_bond_mode
);
1757 if (!if_list_change
) {
1758 break; // no if list changes
1762 * ensure that the first device of the bond matches, if
1763 * not then we remove all current devices and add them
1764 * back in the preferred order.
1766 if ((c_count
> 0) &&
1768 !CFEqual(CFArrayGetValueAtIndex(c_bond_interfaces
, 0),
1769 CFArrayGetValueAtIndex(a_bond_interfaces
, 0))) {
1772 for (a
= 0; a
< a_count
; a
++) {
1773 SCNetworkInterfaceRef a_interface
;
1774 CFStringRef a_interface_if
;
1776 a_interface
= CFArrayGetValueAtIndex(a_bond_interfaces
, a
);
1777 if (!CFArrayContainsValue(c_bond_interfaces
,
1778 CFRangeMake(0, c_count
),
1780 continue; // if already removed
1783 a_interface_if
= SCNetworkInterfaceGetBSDName(a_interface
);
1784 if (!__bond_remove_interface(s
, a_bond_if
, a_interface_if
)) {
1789 a_count
= 0; // all active devices have been removed
1793 * add any devices which are not currently associated
1794 * with the bond interface.
1796 for (c
= 0; c
< c_count
; c
++) {
1797 SCNetworkInterfaceRef c_interface
;
1798 SCNetworkInterfacePrivateRef c_interfacePrivate
;
1799 CFStringRef c_interface_if
;
1801 c_interface
= CFArrayGetValueAtIndex(c_bond_interfaces
, c
);
1802 if ((a_count
== 0) ||
1803 !CFArrayContainsValue(a_bond_interfaces
,
1804 CFRangeMake(0, a_count
),
1807 * check if this member interface can be added to a bond.
1809 c_interfacePrivate
= (SCNetworkInterfacePrivateRef
)c_interface
;
1810 if (!c_interfacePrivate
->supportsBond
) {
1811 // if member not supported
1816 * if this member interface is not currently part of the bond.
1818 c_interface_if
= SCNetworkInterfaceGetBSDName(c_interface
);
1819 if (!__bond_add_interface(s
, c_bond_if
, c_interface_if
)) {
1820 // if member could not be added
1834 s
= inet_dgram_socket();
1843 * establish the new bond interface.
1845 if (!__createInterface(s
, c_bond_if
)) {
1852 __bond_set_mode(s
, c_bond_if
, c_bond_mode
);
1855 * add the member interfaces
1857 for (c
= 0; c
< c_count
; c
++) {
1858 SCNetworkInterfaceRef c_interface
;
1859 SCNetworkInterfacePrivateRef c_interfacePrivate
;
1860 CFStringRef c_interface_if
;
1862 c_interface
= CFArrayGetValueAtIndex(c_bond_interfaces
, c
);
1863 c_interfacePrivate
= (SCNetworkInterfacePrivateRef
)c_interface
;
1864 if (!c_interfacePrivate
->supportsBond
) {
1865 // if member not supported
1869 c_interface_if
= SCNetworkInterfaceGetBSDName(c_interface
);
1870 if (!__bond_add_interface(s
, c_bond_if
, c_interface_if
)) {
1871 // if member could not be added
1881 if (active
!= NULL
) CFRelease(active
);
1882 if (config
!= NULL
) CFRelease(config
);
1883 if (s
!= -1) (void) close(s
);