2 * Copyright (c) 2009-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 * July 27, 2009 Allan Nathanson <ajn@apple.com>
32 #include <CoreFoundation/CoreFoundation.h>
33 #include <CoreFoundation/CFRuntime.h>
35 #include <SystemConfiguration/SystemConfiguration.h>
36 #include "SCNetworkConfigurationInternal.h"
37 #include <SystemConfiguration/SCValidation.h>
38 #include <SystemConfiguration/SCPrivate.h>
43 #include <sys/types.h>
44 #include <sys/ioctl.h>
45 #include <sys/socket.h>
46 #include <sys/sysctl.h>
47 #include <net/ethernet.h>
48 #define KERNEL_PRIVATE
50 #include <net/if_var.h>
52 #include <net/if_types.h>
53 #include <net/if_media.h>
54 #include <net/route.h>
57 #include <net/if_bridgevar.h>
60 /* ---------- Bridge support ---------- */
67 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
69 SCLog(TRUE
, LOG_ERR
, CFSTR("socket() failed: %s"), strerror(errno
));
76 static struct ifbifconf
*
77 ifbifconf_copy(int s
, const char * ifname
)
81 struct ifbifconf
* ibc_p
= NULL
;
83 uint32_t len
= sizeof(struct ifbreq
) * 16;
85 bzero(&ifd
, sizeof(ifd
));
86 strncpy(ifd
.ifd_name
, ifname
, sizeof(ifd
.ifd_name
));
87 ifd
.ifd_cmd
= BRDGGIFS
;
89 buflen
= sizeof(struct ifbifconf
) + len
;
93 ibc_p
= (struct ifbifconf
*)buf
;
94 ibc_p
->ifbic_len
= len
;
95 ibc_p
->ifbic_buf
= buf
+ sizeof(*ibc_p
);
97 ifd
.ifd_len
= sizeof(*ibc_p
);
99 if (ioctl(s
, SIOCGDRVSPEC
, (caddr_t
)&ifd
) == -1) {
103 if ((ibc_p
->ifbic_len
+ sizeof(struct ifbreq
)) < len
) {
104 // if we have room for all of the member interfaces
109 buflen
= sizeof(struct ifbifconf
) + len
;
110 buf
= reallocf(buf
, buflen
);
129 add_interface(CFMutableArrayRef
*interfaces
, CFStringRef if_name
)
131 SCNetworkInterfaceRef interface
;
133 if (*interfaces
== NULL
) {
134 *interfaces
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
137 interface
= _SCNetworkInterfaceCreateWithBSDName(NULL
, if_name
,
138 kIncludeNoVirtualInterfaces
);
139 CFArrayAppendValue(*interfaces
, interface
);
140 CFRelease(interface
);
145 _SCBridgeInterfaceSetMemberInterfaces(SCBridgeInterfaceRef bridge
, CFArrayRef members
);
149 CFMutableArrayRef bridges
;
150 SCPreferencesRef prefs
;
151 } addContext
, *addContextRef
;
155 add_configured_interface(const void *key
, const void *value
, void *context
)
157 SCBridgeInterfaceRef bridge
;
158 CFStringRef bridge_if
= (CFStringRef
)key
;
159 CFDictionaryRef bridge_info
= (CFDictionaryRef
)value
;
160 CFDictionaryRef bridge_options
;
162 CFArrayRef interfaces
;
163 SCNetworkInterfacePrivateRef interfacePrivate
;
164 CFMutableArrayRef members
= NULL
;
165 addContextRef myContext
= (addContextRef
)context
;
169 // create the bridge interface
170 bridge
= (SCBridgeInterfaceRef
)_SCBridgeInterfaceCreatePrivate(NULL
, bridge_if
);
172 // add member interfaces
173 interfaces
= CFDictionaryGetValue(bridge_info
, kSCPropVirtualNetworkInterfacesBridgeInterfaces
);
174 n
= isA_CFArray(interfaces
) ? CFArrayGetCount(interfaces
) : 0;
175 for (i
= 0; i
< n
; i
++) {
178 member
= CFArrayGetValueAtIndex(interfaces
, i
);
179 if (isA_CFString(member
)) {
180 add_interface(&members
, member
);
183 if (members
!= NULL
) {
184 _SCBridgeInterfaceSetMemberInterfaces(bridge
, members
);
189 name
= CFDictionaryGetValue(bridge_info
, kSCPropUserDefinedName
);
190 if (isA_CFString(name
)) {
191 SCBridgeInterfaceSetLocalizedDisplayName(bridge
, name
);
195 bridge_options
= CFDictionaryGetValue(bridge_info
, kSCPropVirtualNetworkInterfacesBridgeOptions
);
196 if (isA_CFDictionary(bridge_options
)) {
197 SCBridgeInterfaceSetOptions(bridge
, bridge_options
);
200 // estabish link to the stored configuration
201 interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
202 interfacePrivate
->prefs
= CFRetain(myContext
->prefs
);
204 CFArrayAppendValue(myContext
->bridges
, bridge
);
212 #pragma mark SCBridgeInterface APIs
216 SCBridgeInterfaceCopyAll(SCPreferencesRef prefs
)
219 CFDictionaryRef dict
;
222 context
.bridges
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
223 context
.prefs
= prefs
;
225 path
= CFStringCreateWithFormat(NULL
,
228 kSCPrefVirtualNetworkInterfaces
,
229 kSCNetworkInterfaceTypeBridge
);
230 dict
= SCPreferencesPathGetValue(prefs
, path
);
231 if (isA_CFDictionary(dict
)) {
232 CFDictionaryApplyFunction(dict
, add_configured_interface
, &context
);
236 return context
.bridges
;
240 __private_extern__
void
241 __SCBridgeInterfaceListCollectMembers(CFArrayRef interfaces
, CFMutableSetRef set
)
246 n
= CFArrayGetCount(interfaces
);
247 for (i
= 0; i
< n
; i
++) {
248 SCBridgeInterfaceRef bridgeInterface
;
251 bridgeInterface
= CFArrayGetValueAtIndex(interfaces
, i
);
252 members
= SCBridgeInterfaceGetMemberInterfaces(bridgeInterface
);
253 if (members
!= NULL
) {
257 // exclude the member interfaces of this bridge
258 n_members
= CFArrayGetCount(members
);
259 for (j
= 0; j
< n_members
; j
++) {
260 SCNetworkInterfaceRef member
;
262 member
= CFArrayGetValueAtIndex(members
, j
);
263 CFSetAddValue(set
, member
);
272 CFArrayRef
/* of SCNetworkInterfaceRef's */
273 SCBridgeInterfaceCopyAvailableMemberInterfaces(SCPreferencesRef prefs
)
275 CFMutableArrayRef available
;
276 CFMutableSetRef excluded
;
277 CFArrayRef interfaces
;
279 available
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
280 excluded
= CFSetCreateMutable (NULL
, 0, &kCFTypeSetCallBacks
);
282 // exclude Bond [member] interfaces
283 interfaces
= SCBondInterfaceCopyAll(prefs
);
284 if (interfaces
!= NULL
) {
285 __SCBondInterfaceListCollectMembers(interfaces
, excluded
);
286 CFRelease(interfaces
);
289 // exclude Bridge [member] interfaces
290 interfaces
= SCBridgeInterfaceCopyAll(prefs
);
291 if (interfaces
!= NULL
) {
292 __SCBridgeInterfaceListCollectMembers(interfaces
, excluded
);
293 CFRelease(interfaces
);
296 // exclude VLAN [physical] interfaces
297 interfaces
= SCVLANInterfaceCopyAll(prefs
);
298 if (interfaces
!= NULL
) {
302 n
= CFArrayGetCount(interfaces
);
303 for (i
= 0; i
< n
; i
++) {
304 SCVLANInterfaceRef vlanInterface
;
305 SCNetworkInterfaceRef physical
;
307 // exclude the physical interface of this VLAN
308 vlanInterface
= CFArrayGetValueAtIndex(interfaces
, i
);
309 physical
= SCVLANInterfaceGetPhysicalInterface(vlanInterface
);
310 CFSetAddValue(excluded
, physical
);
312 CFRelease(interfaces
);
315 // identify available interfaces
316 interfaces
= __SCNetworkInterfaceCopyAll_IONetworkInterface();
317 if (interfaces
!= NULL
) {
321 n
= CFArrayGetCount(interfaces
);
322 for (i
= 0; i
< n
; i
++) {
323 SCNetworkInterfaceRef interface
;
324 SCNetworkInterfacePrivateRef interfacePrivate
;
326 interface
= CFArrayGetValueAtIndex(interfaces
, i
);
327 interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
329 if (!interfacePrivate
->supportsBridge
) {
330 // if this interface is not available
334 if (CFSetContainsValue(excluded
, interface
)) {
339 CFArrayAppendValue(available
, interface
);
341 CFRelease(interfaces
);
351 _SCBridgeInterfaceCopyActive(void)
353 struct ifaddrs
*ifap
;
356 CFMutableArrayRef bridges
= NULL
;
358 if (getifaddrs(&ifap
) == -1) {
360 SCLog(TRUE
, LOG_ERR
, CFSTR("getifaddrs() failed: %s"), strerror(errno
));
364 s
= inet_dgram_socket();
370 bridges
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
372 for (ifp
= ifap
; ifp
!= NULL
; ifp
= ifp
->ifa_next
) {
374 SCBridgeInterfaceRef bridge
;
375 CFStringRef bridge_if
;
376 struct ifbifconf
*ibc_p
;
377 struct if_data
*if_data
;
378 CFMutableArrayRef members
= NULL
;
380 if_data
= (struct if_data
*)ifp
->ifa_data
;
382 || ifp
->ifa_addr
->sa_family
!= AF_LINK
383 || if_data
->ifi_type
!= IFT_BRIDGE
) {
387 ibc_p
= ifbifconf_copy(s
, ifp
->ifa_name
);
389 if (errno
== EBUSY
) {
394 CFSTR("ifbifconf_copy(%s) failed: %s"),
402 // create the bridge interface
403 bridge_if
= CFStringCreateWithCString(NULL
, ifp
->ifa_name
, kCFStringEncodingASCII
);
404 bridge
= (SCBridgeInterfaceRef
)_SCBridgeInterfaceCreatePrivate(NULL
, bridge_if
);
405 CFRelease(bridge_if
);
407 // add member interfaces
408 if (ibc_p
->ifbic_len
> 0) {
411 // iterate over each member interface
412 for (i
= 0; i
< ibc_p
->ifbic_len
/ sizeof(struct ifbreq
); i
++) {
413 struct ifbreq
*ibr_p
;
416 ibr_p
= ibc_p
->ifbic_req
+ i
;
417 member
= CFStringCreateWithCString(NULL
, ibr_p
->ifbr_ifsname
, kCFStringEncodingASCII
);
418 add_interface(&members
, member
);
424 if (members
!= NULL
) {
425 _SCBridgeInterfaceSetMemberInterfaces(bridge
, members
);
430 CFArrayAppendValue(bridges
, bridge
);
444 SCBridgeInterfaceCreate(SCPreferencesRef prefs
)
446 CFAllocatorRef allocator
;
447 SCBridgeInterfaceRef bridge
= NULL
;
451 _SCErrorSet(kSCStatusInvalidArgument
);
455 allocator
= CFGetAllocator(prefs
);
457 // create a new bridge using an unused interface name
458 for (i
= 0; bridge
== NULL
; i
++) {
459 CFDictionaryRef dict
;
460 CFStringRef bridge_if
;
461 SCNetworkInterfacePrivateRef interfacePrivate
;
462 CFMutableDictionaryRef newDict
;
463 CFArrayRef newInterfaces
;
467 bridge_if
= CFStringCreateWithFormat(allocator
, NULL
, CFSTR("bridge%d"), i
);
468 path
= CFStringCreateWithFormat(allocator
,
471 kSCPrefVirtualNetworkInterfaces
,
472 kSCNetworkInterfaceTypeBridge
,
474 dict
= SCPreferencesPathGetValue(prefs
, path
);
476 // if bridge interface name not available
478 CFRelease(bridge_if
);
482 // add the bridge to the stored preferences
483 newDict
= CFDictionaryCreateMutable(allocator
,
485 &kCFTypeDictionaryKeyCallBacks
,
486 &kCFTypeDictionaryValueCallBacks
);
487 newInterfaces
= CFArrayCreate(allocator
, NULL
, 0, &kCFTypeArrayCallBacks
);
488 CFDictionaryAddValue(newDict
, kSCPropVirtualNetworkInterfacesBridgeInterfaces
, newInterfaces
);
489 CFRelease(newInterfaces
);
490 ok
= SCPreferencesPathSetValue(prefs
, path
, newDict
);
494 // if the bridge could not be saved
495 CFRelease(bridge_if
);
499 // create the SCBridgeInterfaceRef
500 bridge
= (SCBridgeInterfaceRef
)_SCBridgeInterfaceCreatePrivate(allocator
, bridge_if
);
501 CFRelease(bridge_if
);
503 // estabish link to the stored configuration
504 interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
505 interfacePrivate
->prefs
= CFRetain(prefs
);
513 SCBridgeInterfaceRemove(SCBridgeInterfaceRef bridge
)
515 CFStringRef bridge_if
;
516 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
520 if (!isA_SCBridgeInterface(bridge
)) {
521 _SCErrorSet(kSCStatusInvalidArgument
);
525 if (interfacePrivate
->prefs
== NULL
) {
526 _SCErrorSet(kSCStatusInvalidArgument
);
530 bridge_if
= SCNetworkInterfaceGetBSDName(bridge
);
531 path
= CFStringCreateWithFormat(NULL
,
534 kSCPrefVirtualNetworkInterfaces
,
535 kSCNetworkInterfaceTypeBridge
,
537 ok
= SCPreferencesPathRemoveValue(interfacePrivate
->prefs
, path
);
545 SCBridgeInterfaceGetMemberInterfaces(SCBridgeInterfaceRef bridge
)
547 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
549 if (!isA_SCBridgeInterface(bridge
)) {
550 _SCErrorSet(kSCStatusInvalidArgument
);
554 return interfacePrivate
->bridge
.interfaces
;
559 SCBridgeInterfaceGetOptions(SCBridgeInterfaceRef bridge
)
561 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
563 if (!isA_SCBridgeInterface(bridge
)) {
564 _SCErrorSet(kSCStatusInvalidArgument
);
568 return interfacePrivate
->bridge
.options
;
573 _SCBridgeInterfaceSetMemberInterfaces(SCBridgeInterfaceRef bridge
, CFArrayRef members
)
576 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
578 CFMutableArrayRef newMembers
;
581 n
= (members
!= NULL
) ? CFArrayGetCount(members
) : 0;
583 // set member interfaces in the stored preferences
584 if (interfacePrivate
->prefs
!= NULL
) {
585 CFDictionaryRef dict
;
586 CFMutableDictionaryRef newDict
;
589 path
= CFStringCreateWithFormat(NULL
,
592 kSCPrefVirtualNetworkInterfaces
,
593 kSCNetworkInterfaceTypeBridge
,
594 interfacePrivate
->entity_device
);
595 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
596 if (!isA_CFDictionary(dict
)) {
597 // if the prefs are confused
599 _SCErrorSet(kSCStatusFailed
);
603 newMembers
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
604 for (i
= 0; i
< n
; i
++) {
605 SCNetworkInterfaceRef interface
;
606 CFStringRef memberName
;
608 interface
= CFArrayGetValueAtIndex(members
, i
);
609 memberName
= SCNetworkInterfaceGetBSDName(interface
);
610 CFArrayAppendValue(newMembers
, memberName
);
613 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
614 CFDictionarySetValue(newDict
, kSCPropVirtualNetworkInterfacesBridgeInterfaces
, newMembers
);
615 CFRelease(newMembers
);
617 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
623 newMembers
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
624 for (i
= 0; i
< n
; i
++) {
625 SCNetworkInterfaceRef member
;
626 SCNetworkInterfacePrivateRef newMember
;
628 member
= CFArrayGetValueAtIndex(members
, i
);
629 newMember
= __SCNetworkInterfaceCreateCopy(NULL
,
631 interfacePrivate
->prefs
,
632 interfacePrivate
->serviceID
);
633 CFArrayAppendValue(newMembers
, newMember
);
634 CFRelease(newMember
);
636 CFRelease(interfacePrivate
->bridge
.interfaces
);
637 interfacePrivate
->bridge
.interfaces
= newMembers
;
645 SCBridgeInterfaceSetMemberInterfaces(SCBridgeInterfaceRef bridge
, CFArrayRef members
)
647 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
649 int sc_status
= kSCStatusOK
;
651 if (!isA_SCBridgeInterface(bridge
)) {
652 _SCErrorSet(kSCStatusInvalidArgument
);
656 if ((members
!= NULL
) && !isA_CFArray(members
)) {
657 _SCErrorSet(kSCStatusInvalidArgument
);
661 if (interfacePrivate
->prefs
!= NULL
) {
662 CFArrayRef available
;
668 CFArrayRef services
= NULL
;
670 current
= SCBridgeInterfaceGetMemberInterfaces(bridge
);
671 n_current
= (current
!= NULL
) ? CFArrayGetCount(current
) : 0;
673 available
= SCBridgeInterfaceCopyAvailableMemberInterfaces(interfacePrivate
->prefs
);
674 n_available
= (available
!= NULL
) ? CFArrayGetCount(available
) : 0;
676 n_members
= (members
!= NULL
) ? CFArrayGetCount(members
) : 0;
677 for (i
= 0; i
< n_members
; i
++) {
678 SCNetworkInterfaceRef member
;
680 member
= CFArrayGetValueAtIndex(members
, i
);
682 if ((current
!= NULL
) &&
683 CFArrayContainsValue(current
, CFRangeMake(0, n_current
), member
)) {
684 // current members are allowed
688 if ((available
!= NULL
) &&
689 CFArrayContainsValue(available
, CFRangeMake(0, n_available
), member
)) {
690 // available members are allowed but cannot be associated
691 // with any other network services.
693 if (services
== NULL
) {
694 services
= __SCNetworkServiceCopyAllEnabled(interfacePrivate
->prefs
);
696 if ((services
!= NULL
) &&
697 __SCNetworkServiceExistsForInterface(services
, member
)) {
698 sc_status
= kSCStatusKeyExists
;
706 // if member not allowed
707 sc_status
= kSCStatusInvalidArgument
;
711 if (available
!= NULL
) CFRelease(available
);
712 if (services
!= NULL
) CFRelease(services
);
715 if (sc_status
!= kSCStatusOK
) {
716 _SCErrorSet(sc_status
);
720 ok
= _SCBridgeInterfaceSetMemberInterfaces(bridge
, members
);
726 SCBridgeInterfaceSetLocalizedDisplayName(SCBridgeInterfaceRef bridge
, CFStringRef newName
)
728 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
731 if (!isA_SCBridgeInterface(bridge
)) {
732 _SCErrorSet(kSCStatusInvalidArgument
);
736 if ((newName
!= NULL
) && !isA_CFString(newName
)) {
737 _SCErrorSet(kSCStatusInvalidArgument
);
741 // set name in the stored preferences
742 if (interfacePrivate
->prefs
!= NULL
) {
743 CFDictionaryRef dict
;
744 CFMutableDictionaryRef newDict
;
747 path
= CFStringCreateWithFormat(NULL
,
750 kSCPrefVirtualNetworkInterfaces
,
751 kSCNetworkInterfaceTypeBridge
,
752 interfacePrivate
->entity_device
);
753 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
754 if (!isA_CFDictionary(dict
)) {
755 // if the prefs are confused
757 _SCErrorSet(kSCStatusFailed
);
761 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
762 if (newName
!= NULL
) {
763 CFDictionarySetValue(newDict
, kSCPropUserDefinedName
, newName
);
765 CFDictionaryRemoveValue(newDict
, kSCPropUserDefinedName
);
767 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
772 // set name in the SCBridgeInterfaceRef
774 if (interfacePrivate
->localized_name
!= NULL
) {
775 CFRelease(interfacePrivate
->localized_name
);
776 interfacePrivate
->localized_name
= NULL
;
778 if (newName
!= NULL
) {
779 interfacePrivate
->localized_name
= CFStringCreateCopy(NULL
, newName
);
788 SCBridgeInterfaceSetOptions(SCBridgeInterfaceRef bridge
, CFDictionaryRef newOptions
)
790 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
793 if (!isA_SCBridgeInterface(bridge
)) {
794 _SCErrorSet(kSCStatusInvalidArgument
);
798 if ((newOptions
!= NULL
) && !isA_CFDictionary(newOptions
)) {
799 _SCErrorSet(kSCStatusInvalidArgument
);
803 // set options in the stored preferences
804 if (interfacePrivate
->prefs
!= NULL
) {
805 CFDictionaryRef dict
;
806 CFMutableDictionaryRef newDict
;
809 path
= CFStringCreateWithFormat(NULL
,
812 kSCPrefVirtualNetworkInterfaces
,
813 kSCNetworkInterfaceTypeBridge
,
814 interfacePrivate
->entity_device
);
815 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
816 if (!isA_CFDictionary(dict
)) {
817 // if the prefs are confused
819 _SCErrorSet(kSCStatusFailed
);
823 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
824 if (newOptions
!= NULL
) {
825 CFDictionarySetValue(newDict
, kSCPropVirtualNetworkInterfacesBridgeOptions
, newOptions
);
827 CFDictionaryRemoveValue(newDict
, kSCPropVirtualNetworkInterfacesBridgeOptions
);
829 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
834 // set options in the SCBridgeInterfaceRef
836 if (interfacePrivate
->bridge
.options
!= NULL
) {
837 CFRelease(interfacePrivate
->bridge
.options
);
838 interfacePrivate
->bridge
.options
= NULL
;
840 if (newOptions
!= NULL
) {
841 interfacePrivate
->bridge
.options
= CFDictionaryCreateCopy(NULL
, newOptions
);
850 #pragma mark SCBridgeInterface management
855 __bridge_add_interface(int s
, CFStringRef bridge_if
, CFStringRef interface_if
)
861 bzero(&ifd
, sizeof(ifd
));
862 (void) _SC_cfstring_to_cstring(bridge_if
,
864 sizeof(ifd
.ifd_name
),
865 kCFStringEncodingASCII
);
866 ifd
.ifd_cmd
= BRDGADD
;
867 ifd
.ifd_len
= sizeof(breq
);
868 ifd
.ifd_data
= (caddr_t
)&breq
;
871 bzero(&breq
, sizeof(breq
));
872 (void) _SC_cfstring_to_cstring(interface_if
,
874 sizeof(breq
.ifbr_ifsname
),
875 kCFStringEncodingASCII
);
877 // add new bridge member
878 if (ioctl(s
, SIOCSDRVSPEC
, (caddr_t
)&ifd
) == -1) {
881 CFSTR("could not add interface \"%@\" to bridge \"%@\": %s"),
893 __bridge_remove_interface(int s
, CFStringRef bridge_if
, CFStringRef interface_if
)
899 bzero(&ifd
, sizeof(ifd
));
900 (void) _SC_cfstring_to_cstring(bridge_if
,
902 sizeof(ifd
.ifd_name
),
903 kCFStringEncodingASCII
);
904 ifd
.ifd_cmd
= BRDGDEL
;
905 ifd
.ifd_len
= sizeof(breq
);
906 ifd
.ifd_data
= (caddr_t
)&breq
;
908 // bridge member to remove
909 bzero(&breq
, sizeof(breq
));
910 (void) _SC_cfstring_to_cstring(interface_if
,
912 sizeof(breq
.ifbr_ifsname
),
913 kCFStringEncodingASCII
);
915 // remove bridge member
916 if (ioctl(s
, SIOCSDRVSPEC
, (caddr_t
)&ifd
) == -1) {
919 CFSTR("could not add interface \"%@\" to bridge \"%@\": %s"),
932 _SCBridgeInterfaceUpdateConfiguration(SCPreferencesRef prefs
)
935 CFArrayRef active
= NULL
;
936 CFArrayRef config
= NULL
;
944 _SCErrorSet(kSCStatusInvalidArgument
);
948 /* configured Bridges */
949 config
= SCBridgeInterfaceCopyAll(prefs
);
950 nConfig
= (config
!= NULL
) ? CFArrayGetCount(config
) : 0;
953 active
= _SCBridgeInterfaceCopyActive();
954 nActive
= (active
!= NULL
) ? CFArrayGetCount(active
) : 0;
957 * remove any no-longer-configured bridge interfaces and
958 * any devices associated with a bridge that are no longer
959 * associated with a bridge.
961 for (i
= 0; i
< nActive
; i
++) {
962 SCBridgeInterfaceRef a_bridge
;
963 CFStringRef a_bridge_if
;
965 Boolean found
= FALSE
;
967 a_bridge
= CFArrayGetValueAtIndex(active
, i
);
968 a_bridge_if
= SCNetworkInterfaceGetBSDName(a_bridge
);
970 for (j
= 0; j
< nConfig
; j
++) {
971 SCBridgeInterfaceRef c_bridge
;
972 CFStringRef c_bridge_if
;
974 c_bridge
= CFArrayGetValueAtIndex(config
, j
);
975 c_bridge_if
= SCNetworkInterfaceGetBSDName(c_bridge
);
977 if (CFEqual(a_bridge_if
, c_bridge_if
)) {
979 CFArrayRef a_bridge_interfaces
;
981 CFArrayRef c_bridge_interfaces
;
984 c_bridge_interfaces
= SCBridgeInterfaceGetMemberInterfaces(c_bridge
);
985 c_count
= (c_bridge_interfaces
!= NULL
) ? CFArrayGetCount(c_bridge_interfaces
) : 0;
987 a_bridge_interfaces
= SCBridgeInterfaceGetMemberInterfaces(a_bridge
);
988 a_count
= (a_bridge_interfaces
!= NULL
) ? CFArrayGetCount(a_bridge_interfaces
) : 0;
990 for (a
= 0; a
< a_count
; a
++) {
991 SCNetworkInterfaceRef a_interface
;
992 CFStringRef a_interface_if
;
994 a_interface
= CFArrayGetValueAtIndex(a_bridge_interfaces
, a
);
995 if ((c_count
== 0) ||
996 !CFArrayContainsValue(c_bridge_interfaces
,
997 CFRangeMake(0, c_count
),
1000 * if this device is no longer part
1004 s
= inet_dgram_socket();
1012 a_interface_if
= SCNetworkInterfaceGetBSDName(a_interface
);
1013 if (!__bridge_remove_interface(s
, a_bridge_if
, a_interface_if
)) {
1026 * if this interface is no longer configured
1029 s
= inet_dgram_socket();
1037 if (!__destroyInterface(s
, a_bridge_if
)) {
1045 * add any newly-configured bridge interfaces and add any
1046 * devices that should now be associated with the bridge.
1048 for (i
= 0; i
< nConfig
; i
++) {
1049 SCBridgeInterfaceRef c_bridge
;
1050 CFArrayRef c_bridge_interfaces
;
1051 CFStringRef c_bridge_if
;
1053 Boolean found
= FALSE
;
1056 c_bridge
= CFArrayGetValueAtIndex(config
, i
);
1057 c_bridge_if
= SCNetworkInterfaceGetBSDName(c_bridge
);
1058 c_bridge_interfaces
= SCBridgeInterfaceGetMemberInterfaces(c_bridge
);
1059 c_count
= (c_bridge_interfaces
!= NULL
) ? CFArrayGetCount(c_bridge_interfaces
) : 0;
1061 for (j
= 0; j
< nActive
; j
++) {
1062 SCBridgeInterfaceRef a_bridge
;
1063 CFArrayRef a_bridge_interfaces
;
1064 CFStringRef a_bridge_if
;
1067 a_bridge
= CFArrayGetValueAtIndex(active
, j
);
1068 a_bridge_if
= SCNetworkInterfaceGetBSDName(a_bridge
);
1069 a_bridge_interfaces
= SCBridgeInterfaceGetMemberInterfaces(a_bridge
);
1070 a_count
= (a_bridge_interfaces
!= NULL
) ? CFArrayGetCount(a_bridge_interfaces
) : 0;
1072 if (CFEqual(c_bridge_if
, a_bridge_if
)) {
1074 Boolean if_list_change
= FALSE
;
1078 if (!_SC_CFEqual(c_bridge_interfaces
, a_bridge_interfaces
)) {
1079 if_list_change
= TRUE
;
1081 if (!if_list_change
) {
1082 break; // if no change
1085 s
= inet_dgram_socket();
1092 if (!if_list_change
) {
1093 break; // no if list changes
1097 * ensure that the first device of the bridge matches, if
1098 * not then we remove all current devices and add them
1099 * back in the preferred order.
1101 if ((c_count
> 0) &&
1103 !CFEqual(CFArrayGetValueAtIndex(c_bridge_interfaces
, 0),
1104 CFArrayGetValueAtIndex(a_bridge_interfaces
, 0))) {
1107 for (a
= 0; a
< a_count
; a
++) {
1108 SCNetworkInterfaceRef a_interface
;
1109 CFStringRef a_interface_if
;
1111 a_interface
= CFArrayGetValueAtIndex(a_bridge_interfaces
, a
);
1112 if (!CFArrayContainsValue(c_bridge_interfaces
,
1113 CFRangeMake(0, c_count
),
1115 continue; // if already removed
1118 a_interface_if
= SCNetworkInterfaceGetBSDName(a_interface
);
1119 if (!__bridge_remove_interface(s
, a_bridge_if
, a_interface_if
)) {
1124 a_count
= 0; // all active devices have been removed
1128 * add any devices which are not currently associated
1129 * with the bridge interface.
1131 for (c
= 0; c
< c_count
; c
++) {
1132 SCNetworkInterfaceRef c_interface
;
1133 SCNetworkInterfacePrivateRef c_interfacePrivate
;
1134 CFStringRef c_interface_if
;
1136 c_interface
= CFArrayGetValueAtIndex(c_bridge_interfaces
, c
);
1137 if ((a_count
== 0) ||
1138 !CFArrayContainsValue(a_bridge_interfaces
,
1139 CFRangeMake(0, a_count
),
1142 * check if this member interface can be added to a bridge.
1144 c_interfacePrivate
= (SCNetworkInterfacePrivateRef
)c_interface
;
1145 if (!c_interfacePrivate
->supportsBridge
) {
1146 // if member not supported
1151 * if this member interface is not currently part of the bridge.
1153 c_interface_if
= SCNetworkInterfaceGetBSDName(c_interface
);
1154 if (!__bridge_add_interface(s
, c_bridge_if
, c_interface_if
)) {
1155 // if member could not be added
1169 s
= inet_dgram_socket();
1178 * establish the new bridge interface.
1180 if (!__createInterface(s
, c_bridge_if
)) {
1187 * add the member interfaces
1189 for (c
= 0; c
< c_count
; c
++) {
1190 SCNetworkInterfaceRef c_interface
;
1191 SCNetworkInterfacePrivateRef c_interfacePrivate
;
1192 CFStringRef c_interface_if
;
1194 c_interface
= CFArrayGetValueAtIndex(c_bridge_interfaces
, c
);
1195 c_interfacePrivate
= (SCNetworkInterfacePrivateRef
)c_interface
;
1196 if (!c_interfacePrivate
->supportsBridge
) {
1197 // if member not supported
1201 c_interface_if
= SCNetworkInterfaceGetBSDName(c_interface
);
1202 if (!__bridge_add_interface(s
, c_bridge_if
, c_interface_if
)) {
1203 // if member could not be added
1213 if (active
!= NULL
) CFRelease(active
);
1214 if (config
!= NULL
) CFRelease(config
);
1215 if (s
!= -1) (void) close(s
);
1220 #endif // IFT_BRIDGE