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 #if !TARGET_OS_IPHONE
283 // exclude Bond [member] interfaces
284 interfaces
= SCBondInterfaceCopyAll(prefs
);
285 if (interfaces
!= NULL
) {
286 __SCBondInterfaceListCollectMembers(interfaces
, excluded
);
287 CFRelease(interfaces
);
289 #endif // !TARGET_OS_IPHONE
291 // exclude Bridge [member] interfaces
292 interfaces
= SCBridgeInterfaceCopyAll(prefs
);
293 if (interfaces
!= NULL
) {
294 __SCBridgeInterfaceListCollectMembers(interfaces
, excluded
);
295 CFRelease(interfaces
);
298 // exclude VLAN [physical] interfaces
299 interfaces
= SCVLANInterfaceCopyAll(prefs
);
300 if (interfaces
!= NULL
) {
304 n
= CFArrayGetCount(interfaces
);
305 for (i
= 0; i
< n
; i
++) {
306 SCVLANInterfaceRef vlanInterface
;
307 SCNetworkInterfaceRef physical
;
309 // exclude the physical interface of this VLAN
310 vlanInterface
= CFArrayGetValueAtIndex(interfaces
, i
);
311 physical
= SCVLANInterfaceGetPhysicalInterface(vlanInterface
);
312 CFSetAddValue(excluded
, physical
);
314 CFRelease(interfaces
);
317 // identify available interfaces
318 interfaces
= __SCNetworkInterfaceCopyAll_IONetworkInterface();
319 if (interfaces
!= NULL
) {
323 n
= CFArrayGetCount(interfaces
);
324 for (i
= 0; i
< n
; i
++) {
325 SCNetworkInterfaceRef interface
;
326 SCNetworkInterfacePrivateRef interfacePrivate
;
328 interface
= CFArrayGetValueAtIndex(interfaces
, i
);
329 interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
331 if (!interfacePrivate
->supportsBridge
) {
332 // if this interface is not available
336 if (CFSetContainsValue(excluded
, interface
)) {
341 CFArrayAppendValue(available
, interface
);
343 CFRelease(interfaces
);
353 _SCBridgeInterfaceCopyActive(void)
355 struct ifaddrs
*ifap
;
358 CFMutableArrayRef bridges
= NULL
;
360 if (getifaddrs(&ifap
) == -1) {
362 SCLog(TRUE
, LOG_ERR
, CFSTR("getifaddrs() failed: %s"), strerror(errno
));
366 s
= inet_dgram_socket();
372 bridges
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
374 for (ifp
= ifap
; ifp
!= NULL
; ifp
= ifp
->ifa_next
) {
376 SCBridgeInterfaceRef bridge
;
377 CFStringRef bridge_if
;
378 struct ifbifconf
*ibc_p
;
379 struct if_data
*if_data
;
380 CFMutableArrayRef members
= NULL
;
382 if_data
= (struct if_data
*)ifp
->ifa_data
;
384 || ifp
->ifa_addr
->sa_family
!= AF_LINK
385 || if_data
->ifi_type
!= IFT_BRIDGE
) {
389 ibc_p
= ifbifconf_copy(s
, ifp
->ifa_name
);
391 if (errno
== EBUSY
) {
396 CFSTR("ifbifconf_copy(%s) failed: %s"),
404 // create the bridge interface
405 bridge_if
= CFStringCreateWithCString(NULL
, ifp
->ifa_name
, kCFStringEncodingASCII
);
406 bridge
= (SCBridgeInterfaceRef
)_SCBridgeInterfaceCreatePrivate(NULL
, bridge_if
);
407 CFRelease(bridge_if
);
409 // add member interfaces
410 if (ibc_p
->ifbic_len
> 0) {
413 // iterate over each member interface
414 for (i
= 0; i
< ibc_p
->ifbic_len
/ sizeof(struct ifbreq
); i
++) {
415 struct ifbreq
*ibr_p
;
418 ibr_p
= ibc_p
->ifbic_req
+ i
;
419 member
= CFStringCreateWithCString(NULL
, ibr_p
->ifbr_ifsname
, kCFStringEncodingASCII
);
420 add_interface(&members
, member
);
426 if (members
!= NULL
) {
427 _SCBridgeInterfaceSetMemberInterfaces(bridge
, members
);
432 CFArrayAppendValue(bridges
, bridge
);
446 SCBridgeInterfaceCreate(SCPreferencesRef prefs
)
448 CFAllocatorRef allocator
;
449 SCBridgeInterfaceRef bridge
= NULL
;
453 _SCErrorSet(kSCStatusInvalidArgument
);
457 allocator
= CFGetAllocator(prefs
);
459 // create a new bridge using an unused interface name
460 for (i
= 0; bridge
== NULL
; i
++) {
461 CFDictionaryRef dict
;
462 CFStringRef bridge_if
;
463 SCNetworkInterfacePrivateRef interfacePrivate
;
464 CFMutableDictionaryRef newDict
;
465 CFArrayRef newInterfaces
;
469 bridge_if
= CFStringCreateWithFormat(allocator
, NULL
, CFSTR("bridge%d"), i
);
470 path
= CFStringCreateWithFormat(allocator
,
473 kSCPrefVirtualNetworkInterfaces
,
474 kSCNetworkInterfaceTypeBridge
,
476 dict
= SCPreferencesPathGetValue(prefs
, path
);
478 // if bridge interface name not available
480 CFRelease(bridge_if
);
484 // add the bridge to the stored preferences
485 newDict
= CFDictionaryCreateMutable(allocator
,
487 &kCFTypeDictionaryKeyCallBacks
,
488 &kCFTypeDictionaryValueCallBacks
);
489 newInterfaces
= CFArrayCreate(allocator
, NULL
, 0, &kCFTypeArrayCallBacks
);
490 CFDictionaryAddValue(newDict
, kSCPropVirtualNetworkInterfacesBridgeInterfaces
, newInterfaces
);
491 CFRelease(newInterfaces
);
492 ok
= SCPreferencesPathSetValue(prefs
, path
, newDict
);
496 // if the bridge could not be saved
497 CFRelease(bridge_if
);
501 // create the SCBridgeInterfaceRef
502 bridge
= (SCBridgeInterfaceRef
)_SCBridgeInterfaceCreatePrivate(allocator
, bridge_if
);
503 CFRelease(bridge_if
);
505 // estabish link to the stored configuration
506 interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
507 interfacePrivate
->prefs
= CFRetain(prefs
);
515 SCBridgeInterfaceRemove(SCBridgeInterfaceRef bridge
)
517 CFStringRef bridge_if
;
518 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
522 if (!isA_SCBridgeInterface(bridge
)) {
523 _SCErrorSet(kSCStatusInvalidArgument
);
527 if (interfacePrivate
->prefs
== NULL
) {
528 _SCErrorSet(kSCStatusInvalidArgument
);
532 bridge_if
= SCNetworkInterfaceGetBSDName(bridge
);
533 path
= CFStringCreateWithFormat(NULL
,
536 kSCPrefVirtualNetworkInterfaces
,
537 kSCNetworkInterfaceTypeBridge
,
539 ok
= SCPreferencesPathRemoveValue(interfacePrivate
->prefs
, path
);
547 SCBridgeInterfaceGetMemberInterfaces(SCBridgeInterfaceRef bridge
)
549 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
551 if (!isA_SCBridgeInterface(bridge
)) {
552 _SCErrorSet(kSCStatusInvalidArgument
);
556 return interfacePrivate
->bridge
.interfaces
;
561 SCBridgeInterfaceGetOptions(SCBridgeInterfaceRef bridge
)
563 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
565 if (!isA_SCBridgeInterface(bridge
)) {
566 _SCErrorSet(kSCStatusInvalidArgument
);
570 return interfacePrivate
->bridge
.options
;
575 _SCBridgeInterfaceSetMemberInterfaces(SCBridgeInterfaceRef bridge
, CFArrayRef members
)
578 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
580 CFMutableArrayRef newMembers
;
583 n
= (members
!= NULL
) ? CFArrayGetCount(members
) : 0;
585 // set member interfaces in the stored preferences
586 if (interfacePrivate
->prefs
!= NULL
) {
587 CFDictionaryRef dict
;
588 CFMutableDictionaryRef newDict
;
591 path
= CFStringCreateWithFormat(NULL
,
594 kSCPrefVirtualNetworkInterfaces
,
595 kSCNetworkInterfaceTypeBridge
,
596 interfacePrivate
->entity_device
);
597 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
598 if (!isA_CFDictionary(dict
)) {
599 // if the prefs are confused
601 _SCErrorSet(kSCStatusFailed
);
605 newMembers
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
606 for (i
= 0; i
< n
; i
++) {
607 SCNetworkInterfaceRef interface
;
608 CFStringRef memberName
;
610 interface
= CFArrayGetValueAtIndex(members
, i
);
611 memberName
= SCNetworkInterfaceGetBSDName(interface
);
612 CFArrayAppendValue(newMembers
, memberName
);
615 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
616 CFDictionarySetValue(newDict
, kSCPropVirtualNetworkInterfacesBridgeInterfaces
, newMembers
);
617 CFRelease(newMembers
);
619 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
625 newMembers
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
626 for (i
= 0; i
< n
; i
++) {
627 SCNetworkInterfaceRef member
;
628 SCNetworkInterfacePrivateRef newMember
;
630 member
= CFArrayGetValueAtIndex(members
, i
);
631 newMember
= __SCNetworkInterfaceCreateCopy(NULL
,
633 interfacePrivate
->prefs
,
634 interfacePrivate
->serviceID
);
635 CFArrayAppendValue(newMembers
, newMember
);
636 CFRelease(newMember
);
638 CFRelease(interfacePrivate
->bridge
.interfaces
);
639 interfacePrivate
->bridge
.interfaces
= newMembers
;
647 SCBridgeInterfaceSetMemberInterfaces(SCBridgeInterfaceRef bridge
, CFArrayRef members
)
649 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
651 int sc_status
= kSCStatusOK
;
653 if (!isA_SCBridgeInterface(bridge
)) {
654 _SCErrorSet(kSCStatusInvalidArgument
);
658 if ((members
!= NULL
) && !isA_CFArray(members
)) {
659 _SCErrorSet(kSCStatusInvalidArgument
);
663 if (interfacePrivate
->prefs
!= NULL
) {
664 CFArrayRef available
;
670 CFArrayRef services
= NULL
;
672 current
= SCBridgeInterfaceGetMemberInterfaces(bridge
);
673 n_current
= (current
!= NULL
) ? CFArrayGetCount(current
) : 0;
675 available
= SCBridgeInterfaceCopyAvailableMemberInterfaces(interfacePrivate
->prefs
);
676 n_available
= (available
!= NULL
) ? CFArrayGetCount(available
) : 0;
678 n_members
= (members
!= NULL
) ? CFArrayGetCount(members
) : 0;
679 for (i
= 0; i
< n_members
; i
++) {
680 SCNetworkInterfaceRef member
;
682 member
= CFArrayGetValueAtIndex(members
, i
);
684 if ((current
!= NULL
) &&
685 CFArrayContainsValue(current
, CFRangeMake(0, n_current
), member
)) {
686 // current members are allowed
690 if ((available
!= NULL
) &&
691 CFArrayContainsValue(available
, CFRangeMake(0, n_available
), member
)) {
692 // available members are allowed but cannot be associated
693 // with any other network services.
695 if (services
== NULL
) {
696 services
= __SCNetworkServiceCopyAllEnabled(interfacePrivate
->prefs
);
698 if ((services
!= NULL
) &&
699 __SCNetworkServiceExistsForInterface(services
, member
)) {
700 sc_status
= kSCStatusKeyExists
;
708 // if member not allowed
709 sc_status
= kSCStatusInvalidArgument
;
713 if (available
!= NULL
) CFRelease(available
);
714 if (services
!= NULL
) CFRelease(services
);
717 if (sc_status
!= kSCStatusOK
) {
718 _SCErrorSet(sc_status
);
722 ok
= _SCBridgeInterfaceSetMemberInterfaces(bridge
, members
);
728 SCBridgeInterfaceSetLocalizedDisplayName(SCBridgeInterfaceRef bridge
, CFStringRef newName
)
730 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
733 if (!isA_SCBridgeInterface(bridge
)) {
734 _SCErrorSet(kSCStatusInvalidArgument
);
738 if ((newName
!= NULL
) && !isA_CFString(newName
)) {
739 _SCErrorSet(kSCStatusInvalidArgument
);
743 // set name in the stored preferences
744 if (interfacePrivate
->prefs
!= NULL
) {
745 CFDictionaryRef dict
;
746 CFMutableDictionaryRef newDict
;
749 path
= CFStringCreateWithFormat(NULL
,
752 kSCPrefVirtualNetworkInterfaces
,
753 kSCNetworkInterfaceTypeBridge
,
754 interfacePrivate
->entity_device
);
755 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
756 if (!isA_CFDictionary(dict
)) {
757 // if the prefs are confused
759 _SCErrorSet(kSCStatusFailed
);
763 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
764 if (newName
!= NULL
) {
765 CFDictionarySetValue(newDict
, kSCPropUserDefinedName
, newName
);
767 CFDictionaryRemoveValue(newDict
, kSCPropUserDefinedName
);
769 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
774 // set name in the SCBridgeInterfaceRef
776 if (interfacePrivate
->localized_name
!= NULL
) {
777 CFRelease(interfacePrivate
->localized_name
);
778 interfacePrivate
->localized_name
= NULL
;
780 if (newName
!= NULL
) {
781 interfacePrivate
->localized_name
= CFStringCreateCopy(NULL
, newName
);
790 SCBridgeInterfaceSetOptions(SCBridgeInterfaceRef bridge
, CFDictionaryRef newOptions
)
792 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
795 if (!isA_SCBridgeInterface(bridge
)) {
796 _SCErrorSet(kSCStatusInvalidArgument
);
800 if ((newOptions
!= NULL
) && !isA_CFDictionary(newOptions
)) {
801 _SCErrorSet(kSCStatusInvalidArgument
);
805 // set options in the stored preferences
806 if (interfacePrivate
->prefs
!= NULL
) {
807 CFDictionaryRef dict
;
808 CFMutableDictionaryRef newDict
;
811 path
= CFStringCreateWithFormat(NULL
,
814 kSCPrefVirtualNetworkInterfaces
,
815 kSCNetworkInterfaceTypeBridge
,
816 interfacePrivate
->entity_device
);
817 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
818 if (!isA_CFDictionary(dict
)) {
819 // if the prefs are confused
821 _SCErrorSet(kSCStatusFailed
);
825 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
826 if (newOptions
!= NULL
) {
827 CFDictionarySetValue(newDict
, kSCPropVirtualNetworkInterfacesBridgeOptions
, newOptions
);
829 CFDictionaryRemoveValue(newDict
, kSCPropVirtualNetworkInterfacesBridgeOptions
);
831 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
836 // set options in the SCBridgeInterfaceRef
838 if (interfacePrivate
->bridge
.options
!= NULL
) {
839 CFRelease(interfacePrivate
->bridge
.options
);
840 interfacePrivate
->bridge
.options
= NULL
;
842 if (newOptions
!= NULL
) {
843 interfacePrivate
->bridge
.options
= CFDictionaryCreateCopy(NULL
, newOptions
);
852 #pragma mark SCBridgeInterface management
857 __bridge_add_interface(int s
, CFStringRef bridge_if
, CFStringRef interface_if
)
863 bzero(&ifd
, sizeof(ifd
));
864 (void) _SC_cfstring_to_cstring(bridge_if
,
866 sizeof(ifd
.ifd_name
),
867 kCFStringEncodingASCII
);
868 ifd
.ifd_cmd
= BRDGADD
;
869 ifd
.ifd_len
= sizeof(breq
);
870 ifd
.ifd_data
= (caddr_t
)&breq
;
873 bzero(&breq
, sizeof(breq
));
874 (void) _SC_cfstring_to_cstring(interface_if
,
876 sizeof(breq
.ifbr_ifsname
),
877 kCFStringEncodingASCII
);
879 // add new bridge member
880 if (ioctl(s
, SIOCSDRVSPEC
, (caddr_t
)&ifd
) == -1) {
883 CFSTR("could not add interface \"%@\" to bridge \"%@\": %s"),
895 __bridge_remove_interface(int s
, CFStringRef bridge_if
, CFStringRef interface_if
)
901 bzero(&ifd
, sizeof(ifd
));
902 (void) _SC_cfstring_to_cstring(bridge_if
,
904 sizeof(ifd
.ifd_name
),
905 kCFStringEncodingASCII
);
906 ifd
.ifd_cmd
= BRDGDEL
;
907 ifd
.ifd_len
= sizeof(breq
);
908 ifd
.ifd_data
= (caddr_t
)&breq
;
910 // bridge member to remove
911 bzero(&breq
, sizeof(breq
));
912 (void) _SC_cfstring_to_cstring(interface_if
,
914 sizeof(breq
.ifbr_ifsname
),
915 kCFStringEncodingASCII
);
917 // remove bridge member
918 if (ioctl(s
, SIOCSDRVSPEC
, (caddr_t
)&ifd
) == -1) {
921 CFSTR("could not add interface \"%@\" to bridge \"%@\": %s"),
934 _SCBridgeInterfaceUpdateConfiguration(SCPreferencesRef prefs
)
937 CFArrayRef active
= NULL
;
938 CFArrayRef config
= NULL
;
946 _SCErrorSet(kSCStatusInvalidArgument
);
950 /* configured Bridges */
951 config
= SCBridgeInterfaceCopyAll(prefs
);
952 nConfig
= (config
!= NULL
) ? CFArrayGetCount(config
) : 0;
955 active
= _SCBridgeInterfaceCopyActive();
956 nActive
= (active
!= NULL
) ? CFArrayGetCount(active
) : 0;
959 * remove any no-longer-configured bridge interfaces and
960 * any devices associated with a bridge that are no longer
961 * associated with a bridge.
963 for (i
= 0; i
< nActive
; i
++) {
964 SCBridgeInterfaceRef a_bridge
;
965 CFStringRef a_bridge_if
;
967 Boolean found
= FALSE
;
969 a_bridge
= CFArrayGetValueAtIndex(active
, i
);
970 a_bridge_if
= SCNetworkInterfaceGetBSDName(a_bridge
);
972 for (j
= 0; j
< nConfig
; j
++) {
973 SCBridgeInterfaceRef c_bridge
;
974 CFStringRef c_bridge_if
;
976 c_bridge
= CFArrayGetValueAtIndex(config
, j
);
977 c_bridge_if
= SCNetworkInterfaceGetBSDName(c_bridge
);
979 if (CFEqual(a_bridge_if
, c_bridge_if
)) {
981 CFArrayRef a_bridge_interfaces
;
983 CFArrayRef c_bridge_interfaces
;
986 c_bridge_interfaces
= SCBridgeInterfaceGetMemberInterfaces(c_bridge
);
987 c_count
= (c_bridge_interfaces
!= NULL
) ? CFArrayGetCount(c_bridge_interfaces
) : 0;
989 a_bridge_interfaces
= SCBridgeInterfaceGetMemberInterfaces(a_bridge
);
990 a_count
= (a_bridge_interfaces
!= NULL
) ? CFArrayGetCount(a_bridge_interfaces
) : 0;
992 for (a
= 0; a
< a_count
; a
++) {
993 SCNetworkInterfaceRef a_interface
;
994 CFStringRef a_interface_if
;
996 a_interface
= CFArrayGetValueAtIndex(a_bridge_interfaces
, a
);
997 if ((c_count
== 0) ||
998 !CFArrayContainsValue(c_bridge_interfaces
,
999 CFRangeMake(0, c_count
),
1002 * if this device is no longer part
1006 s
= inet_dgram_socket();
1014 a_interface_if
= SCNetworkInterfaceGetBSDName(a_interface
);
1015 if (!__bridge_remove_interface(s
, a_bridge_if
, a_interface_if
)) {
1028 * if this interface is no longer configured
1031 s
= inet_dgram_socket();
1039 if (!__destroyInterface(s
, a_bridge_if
)) {
1047 * add any newly-configured bridge interfaces and add any
1048 * devices that should now be associated with the bridge.
1050 for (i
= 0; i
< nConfig
; i
++) {
1051 SCBridgeInterfaceRef c_bridge
;
1052 CFArrayRef c_bridge_interfaces
;
1053 CFStringRef c_bridge_if
;
1055 Boolean found
= FALSE
;
1058 c_bridge
= CFArrayGetValueAtIndex(config
, i
);
1059 c_bridge_if
= SCNetworkInterfaceGetBSDName(c_bridge
);
1060 c_bridge_interfaces
= SCBridgeInterfaceGetMemberInterfaces(c_bridge
);
1061 c_count
= (c_bridge_interfaces
!= NULL
) ? CFArrayGetCount(c_bridge_interfaces
) : 0;
1063 for (j
= 0; j
< nActive
; j
++) {
1064 SCBridgeInterfaceRef a_bridge
;
1065 CFArrayRef a_bridge_interfaces
;
1066 CFStringRef a_bridge_if
;
1069 a_bridge
= CFArrayGetValueAtIndex(active
, j
);
1070 a_bridge_if
= SCNetworkInterfaceGetBSDName(a_bridge
);
1071 a_bridge_interfaces
= SCBridgeInterfaceGetMemberInterfaces(a_bridge
);
1072 a_count
= (a_bridge_interfaces
!= NULL
) ? CFArrayGetCount(a_bridge_interfaces
) : 0;
1074 if (CFEqual(c_bridge_if
, a_bridge_if
)) {
1076 Boolean if_list_change
= FALSE
;
1080 if (!_SC_CFEqual(c_bridge_interfaces
, a_bridge_interfaces
)) {
1081 if_list_change
= TRUE
;
1083 if (!if_list_change
) {
1084 break; // if no change
1087 s
= inet_dgram_socket();
1094 if (!if_list_change
) {
1095 break; // no if list changes
1099 * ensure that the first device of the bridge matches, if
1100 * not then we remove all current devices and add them
1101 * back in the preferred order.
1103 if ((c_count
> 0) &&
1105 !CFEqual(CFArrayGetValueAtIndex(c_bridge_interfaces
, 0),
1106 CFArrayGetValueAtIndex(a_bridge_interfaces
, 0))) {
1109 for (a
= 0; a
< a_count
; a
++) {
1110 SCNetworkInterfaceRef a_interface
;
1111 CFStringRef a_interface_if
;
1113 a_interface
= CFArrayGetValueAtIndex(a_bridge_interfaces
, a
);
1114 if (!CFArrayContainsValue(c_bridge_interfaces
,
1115 CFRangeMake(0, c_count
),
1117 continue; // if already removed
1120 a_interface_if
= SCNetworkInterfaceGetBSDName(a_interface
);
1121 if (!__bridge_remove_interface(s
, a_bridge_if
, a_interface_if
)) {
1126 a_count
= 0; // all active devices have been removed
1130 * add any devices which are not currently associated
1131 * with the bridge interface.
1133 for (c
= 0; c
< c_count
; c
++) {
1134 SCNetworkInterfaceRef c_interface
;
1135 SCNetworkInterfacePrivateRef c_interfacePrivate
;
1136 CFStringRef c_interface_if
;
1138 c_interface
= CFArrayGetValueAtIndex(c_bridge_interfaces
, c
);
1139 if ((a_count
== 0) ||
1140 !CFArrayContainsValue(a_bridge_interfaces
,
1141 CFRangeMake(0, a_count
),
1144 * check if this member interface can be added to a bridge.
1146 c_interfacePrivate
= (SCNetworkInterfacePrivateRef
)c_interface
;
1147 if (!c_interfacePrivate
->supportsBridge
) {
1148 // if member not supported
1153 * if this member interface is not currently part of the bridge.
1155 c_interface_if
= SCNetworkInterfaceGetBSDName(c_interface
);
1156 if (!__bridge_add_interface(s
, c_bridge_if
, c_interface_if
)) {
1157 // if member could not be added
1171 s
= inet_dgram_socket();
1180 * establish the new bridge interface.
1182 if (!__createInterface(s
, c_bridge_if
)) {
1189 * add the member interfaces
1191 for (c
= 0; c
< c_count
; c
++) {
1192 SCNetworkInterfaceRef c_interface
;
1193 SCNetworkInterfacePrivateRef c_interfacePrivate
;
1194 CFStringRef c_interface_if
;
1196 c_interface
= CFArrayGetValueAtIndex(c_bridge_interfaces
, c
);
1197 c_interfacePrivate
= (SCNetworkInterfacePrivateRef
)c_interface
;
1198 if (!c_interfacePrivate
->supportsBridge
) {
1199 // if member not supported
1203 c_interface_if
= SCNetworkInterfaceGetBSDName(c_interface
);
1204 if (!__bridge_add_interface(s
, c_bridge_if
, c_interface_if
)) {
1205 // if member could not be added
1215 if (active
!= NULL
) CFRelease(active
);
1216 if (config
!= NULL
) CFRelease(config
);
1217 if (s
!= -1) (void) close(s
);
1222 #endif // IFT_BRIDGE