2 * Copyright (c) 2009-2018 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 "SCNetworkConfigurationInternal.h"
36 #include "SCPreferencesInternal.h"
41 #include <sys/types.h>
42 #include <sys/ioctl.h>
43 #include <sys/socket.h>
44 #include <sys/sysctl.h>
45 #include <net/ethernet.h>
46 #define KERNEL_PRIVATE
48 #include <net/if_var.h>
50 #include <net/if_types.h>
51 #include <net/if_media.h>
52 #include <net/route.h>
55 #include <net/if_bridgevar.h>
58 /* ---------- Bridge support ---------- */
65 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
67 SC_log(LOG_ERR
, "socket() failed: %s", strerror(errno
));
74 static struct ifbifconf
*
75 ifbifconf_copy(int s
, const char * ifname
)
79 struct ifbifconf
* ibc_p
= NULL
;
81 uint32_t len
= sizeof(struct ifbreq
) * 16;
83 memset(&ifd
, 0, sizeof(ifd
));
84 strlcpy(ifd
.ifd_name
, ifname
, sizeof(ifd
.ifd_name
));
85 ifd
.ifd_cmd
= BRDGGIFS
;
87 buflen
= sizeof(struct ifbifconf
) + len
;
90 memset(buf
, 0, buflen
);
91 ibc_p
= (struct ifbifconf
*)buf
;
92 ibc_p
->ifbic_len
= len
;
93 ibc_p
->ifbic_buf
= buf
+ sizeof(*ibc_p
);
95 ifd
.ifd_len
= sizeof(*ibc_p
);
97 if (ioctl(s
, SIOCGDRVSPEC
, (caddr_t
)&ifd
) == -1) {
101 if ((ibc_p
->ifbic_len
+ sizeof(struct ifbreq
)) < len
) {
102 // if we have room for all of the member interfaces
107 buflen
= sizeof(struct ifbifconf
) + len
;
108 buf
= reallocf(buf
, buflen
);
127 add_interface(CFMutableArrayRef
*interfaces
, CFStringRef if_name
, SCPreferencesRef ni_prefs
)
129 SCNetworkInterfaceRef interface
= NULL
;
131 if (*interfaces
== NULL
) {
132 *interfaces
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
134 if (ni_prefs
!= NULL
) {
135 interface
= __SCNetworkInterfaceCreateWithNIPreferencesUsingBSDName(NULL
, ni_prefs
, if_name
);
137 if (interface
== NULL
) {
138 interface
= _SCNetworkInterfaceCreateWithBSDName(NULL
, if_name
,
139 kIncludeNoVirtualInterfaces
);
142 if (interface
!= NULL
) {
143 CFArrayAppendValue(*interfaces
, interface
);
144 CFRelease(interface
);
149 CFMutableArrayRef bridges
;
150 SCPreferencesRef ni_prefs
;
151 SCPreferencesRef prefs
;
152 } addContext
, *addContextRef
;
156 add_configured_interface(const void *key
, const void *value
, void *context
)
158 SCBridgeInterfaceRef bridge
;
159 CFStringRef bridge_if
= (CFStringRef
)key
;
160 CFDictionaryRef bridge_info
= (CFDictionaryRef
)value
;
161 CFDictionaryRef bridge_options
;
163 CFArrayRef interfaces
;
164 SCNetworkInterfacePrivateRef interfacePrivate
;
165 CFMutableArrayRef members
= NULL
;
166 addContextRef myContext
= (addContextRef
)context
;
168 CFStringRef name_auto
= NULL
;
171 // create the bridge interface
172 bridge
= (SCBridgeInterfaceRef
)_SCBridgeInterfaceCreatePrivate(NULL
, bridge_if
);
173 assert(bridge
!= NULL
);
175 // estabish link to the stored configuration
176 interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
177 interfacePrivate
->prefs
= CFRetain(myContext
->prefs
);
179 // add member interfaces
180 interfaces
= CFDictionaryGetValue(bridge_info
, kSCPropVirtualNetworkInterfacesBridgeInterfaces
);
181 n
= isA_CFArray(interfaces
) ? CFArrayGetCount(interfaces
) : 0;
182 for (i
= 0; i
< n
; i
++) {
185 member
= CFArrayGetValueAtIndex(interfaces
, i
);
186 if (isA_CFString(member
)) {
187 add_interface(&members
, member
, myContext
->ni_prefs
);
190 if (members
!= NULL
) {
191 __SCBridgeInterfaceSetMemberInterfaces(bridge
, members
);
196 bridge_options
= CFDictionaryGetValue(bridge_info
, kSCPropVirtualNetworkInterfacesBridgeOptions
);
197 if (isA_CFDictionary(bridge_options
)) {
198 SCBridgeInterfaceSetOptions(bridge
, bridge_options
);
199 name_auto
= CFDictionaryGetValue(bridge_options
, CFSTR("__AUTO__"));
203 name
= CFDictionaryGetValue(bridge_info
, kSCPropUserDefinedName
);
204 if (isA_CFString(name
)) {
205 SCBridgeInterfaceSetLocalizedDisplayName(bridge
, name
);
206 } else if (isA_CFString(name_auto
)) {
207 interfacePrivate
->localized_key
= name_auto
;
208 if (interfacePrivate
->localized_arg1
!= NULL
) {
209 CFRelease(interfacePrivate
->localized_arg1
);
210 interfacePrivate
->localized_arg1
= NULL
;
214 CFArrayAppendValue(myContext
->bridges
, bridge
);
222 #pragma mark SCBridgeInterface APIs
225 static __inline__
void
226 my_CFDictionaryApplyFunction(CFDictionaryRef theDict
,
227 CFDictionaryApplierFunction applier
,
230 CFAllocatorRef myAllocator
;
231 CFDictionaryRef myDict
;
233 myAllocator
= CFGetAllocator(theDict
);
234 myDict
= CFDictionaryCreateCopy(myAllocator
, theDict
);
235 CFDictionaryApplyFunction(myDict
, applier
, context
);
242 SCBridgeInterfaceCopyAll(SCPreferencesRef prefs
)
245 CFDictionaryRef dict
;
246 SCPreferencesRef ni_prefs
;
249 if (__SCPreferencesUsingDefaultPrefs(prefs
)) {
252 ni_prefs
= __SCPreferencesCreateNIPrefsFromPrefs(prefs
);
254 context
.bridges
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
255 context
.prefs
= prefs
;
256 context
.ni_prefs
= ni_prefs
;
258 path
= CFStringCreateWithFormat(NULL
,
261 kSCPrefVirtualNetworkInterfaces
,
262 kSCNetworkInterfaceTypeBridge
);
263 dict
= SCPreferencesPathGetValue(prefs
, path
);
264 if (isA_CFDictionary(dict
)) {
265 my_CFDictionaryApplyFunction(dict
, add_configured_interface
, &context
);
268 if (ni_prefs
!= NULL
) {
271 return context
.bridges
;
275 __private_extern__
void
276 __SCBridgeInterfaceListCollectMembers(CFArrayRef interfaces
, CFMutableSetRef set
)
281 n
= CFArrayGetCount(interfaces
);
282 for (i
= 0; i
< n
; i
++) {
283 SCBridgeInterfaceRef bridgeInterface
;
286 bridgeInterface
= CFArrayGetValueAtIndex(interfaces
, i
);
287 members
= SCBridgeInterfaceGetMemberInterfaces(bridgeInterface
);
288 if (members
!= NULL
) {
292 // exclude the member interfaces of this bridge
293 n_members
= CFArrayGetCount(members
);
294 for (j
= 0; j
< n_members
; j
++) {
295 SCNetworkInterfaceRef member
;
297 member
= CFArrayGetValueAtIndex(members
, j
);
298 CFSetAddValue(set
, member
);
307 CFArrayRef
/* of SCNetworkInterfaceRef's */
308 SCBridgeInterfaceCopyAvailableMemberInterfaces(SCPreferencesRef prefs
)
310 CFMutableArrayRef available
;
311 CFMutableSetRef excluded
;
312 CFArrayRef interfaces
;
314 available
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
315 excluded
= CFSetCreateMutable (NULL
, 0, &kCFTypeSetCallBacks
);
317 #if !TARGET_OS_IPHONE
318 // exclude Bond [member] interfaces
319 interfaces
= SCBondInterfaceCopyAll(prefs
);
320 if (interfaces
!= NULL
) {
321 __SCBondInterfaceListCollectMembers(interfaces
, excluded
);
322 CFRelease(interfaces
);
324 #endif // !TARGET_OS_IPHONE
326 // exclude Bridge [member] interfaces
327 interfaces
= SCBridgeInterfaceCopyAll(prefs
);
328 if (interfaces
!= NULL
) {
329 __SCBridgeInterfaceListCollectMembers(interfaces
, excluded
);
330 CFRelease(interfaces
);
333 // exclude VLAN [physical] interfaces
334 interfaces
= SCVLANInterfaceCopyAll(prefs
);
335 if (interfaces
!= NULL
) {
339 n
= CFArrayGetCount(interfaces
);
340 for (i
= 0; i
< n
; i
++) {
341 SCVLANInterfaceRef vlanInterface
;
342 SCNetworkInterfaceRef physical
;
344 // exclude the physical interface of this VLAN
345 vlanInterface
= CFArrayGetValueAtIndex(interfaces
, i
);
346 physical
= SCVLANInterfaceGetPhysicalInterface(vlanInterface
);
347 CFSetAddValue(excluded
, physical
);
349 CFRelease(interfaces
);
352 // identify available interfaces
353 interfaces
= __SCNetworkInterfaceCopyAll_IONetworkInterface(FALSE
);
354 if (interfaces
!= NULL
) {
358 n
= CFArrayGetCount(interfaces
);
359 for (i
= 0; i
< n
; i
++) {
360 SCNetworkInterfaceRef interface
;
361 SCNetworkInterfacePrivateRef interfacePrivate
;
363 interface
= CFArrayGetValueAtIndex(interfaces
, i
);
364 interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
366 if (!interfacePrivate
->supportsBridge
) {
367 // if this interface is not available
371 if (CFSetContainsValue(excluded
, interface
)) {
376 CFArrayAppendValue(available
, interface
);
378 CFRelease(interfaces
);
388 _SCBridgeInterfaceCopyActive(void)
390 struct ifaddrs
*ifap
;
393 CFMutableArrayRef bridges
= NULL
;
395 if (getifaddrs(&ifap
) == -1) {
397 SC_log(LOG_NOTICE
, "getifaddrs() failed: %s", strerror(errno
));
401 s
= inet_dgram_socket();
407 bridges
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
409 for (ifp
= ifap
; ifp
!= NULL
; ifp
= ifp
->ifa_next
) {
411 SCBridgeInterfaceRef bridge
;
412 CFStringRef bridge_if
;
413 struct ifbifconf
*ibc_p
;
414 struct if_data
*if_data
;
415 CFMutableArrayRef members
= NULL
;
418 if_data
= (struct if_data
*)ifp
->ifa_data
;
420 || ifp
->ifa_addr
->sa_family
!= AF_LINK
421 || if_data
->ifi_type
!= IFT_BRIDGE
) {
425 // make sure that we leave non-SC configured bridge
426 // interfaces (those with unit #'s >= 100) alone.
427 n
= strlen(ifp
->ifa_name
);
429 isdigit(ifp
->ifa_name
[n
- 1]) &&
430 isdigit(ifp
->ifa_name
[n
- 2]) &&
431 isdigit(ifp
->ifa_name
[n
- 3])) {
432 // if not SC managed bridge interface
436 ibc_p
= ifbifconf_copy(s
, ifp
->ifa_name
);
438 if (errno
== EBUSY
) {
442 SC_log(LOG_NOTICE
, "ifbifconf_copy(%s) failed: %s",
450 // create the bridge interface
451 bridge_if
= CFStringCreateWithCString(NULL
, ifp
->ifa_name
, kCFStringEncodingASCII
);
452 bridge
= (SCBridgeInterfaceRef
)_SCBridgeInterfaceCreatePrivate(NULL
, bridge_if
);
453 CFRelease(bridge_if
);
455 // add member interfaces
456 if (ibc_p
->ifbic_len
> 0) {
457 // iterate over each member interface
458 for (size_t i
= 0; i
< ibc_p
->ifbic_len
/ sizeof(struct ifbreq
); i
++) {
459 struct ifbreq
*ibr_p
;
462 ibr_p
= ibc_p
->ifbic_req
+ i
;
463 member
= CFStringCreateWithCString(NULL
, ibr_p
->ifbr_ifsname
, kCFStringEncodingASCII
);
464 add_interface(&members
, member
, NULL
);
470 if (members
!= NULL
) {
471 __SCBridgeInterfaceSetMemberInterfaces(bridge
, members
);
476 CFArrayAppendValue(bridges
, bridge
);
492 SCBridgeInterfaceCreate(SCPreferencesRef prefs
)
494 CFAllocatorRef allocator
;
495 SCBridgeInterfaceRef bridge
= NULL
;
499 _SCErrorSet(kSCStatusInvalidArgument
);
503 allocator
= CFGetAllocator(prefs
);
505 // create a new bridge using an unused interface name
506 for (i
= 0; bridge
== NULL
; i
++) {
507 CFDictionaryRef dict
;
508 CFStringRef bridge_if
;
509 SCNetworkInterfacePrivateRef interfacePrivate
;
510 CFMutableDictionaryRef newDict
;
511 CFArrayRef newInterfaces
;
515 bridge_if
= CFStringCreateWithFormat(allocator
, NULL
, CFSTR("bridge%ld"), i
);
516 path
= CFStringCreateWithFormat(allocator
,
519 kSCPrefVirtualNetworkInterfaces
,
520 kSCNetworkInterfaceTypeBridge
,
522 dict
= SCPreferencesPathGetValue(prefs
, path
);
524 // if bridge interface name not available
526 CFRelease(bridge_if
);
530 // add the bridge to the stored preferences
531 newDict
= CFDictionaryCreateMutable(allocator
,
533 &kCFTypeDictionaryKeyCallBacks
,
534 &kCFTypeDictionaryValueCallBacks
);
535 newInterfaces
= CFArrayCreate(allocator
, NULL
, 0, &kCFTypeArrayCallBacks
);
536 CFDictionaryAddValue(newDict
, kSCPropVirtualNetworkInterfacesBridgeInterfaces
, newInterfaces
);
537 CFRelease(newInterfaces
);
538 ok
= SCPreferencesPathSetValue(prefs
, path
, newDict
);
542 // if the bridge could not be saved
543 CFRelease(bridge_if
);
547 // create the SCBridgeInterfaceRef
548 bridge
= (SCBridgeInterfaceRef
)_SCBridgeInterfaceCreatePrivate(allocator
, bridge_if
);
549 CFRelease(bridge_if
);
551 // estabish link to the stored configuration
552 interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
553 interfacePrivate
->prefs
= CFRetain(prefs
);
561 SCBridgeInterfaceRemove(SCBridgeInterfaceRef bridge
)
563 CFStringRef bridge_if
;
564 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
568 if (!isA_SCBridgeInterface(bridge
)) {
569 _SCErrorSet(kSCStatusInvalidArgument
);
573 if (interfacePrivate
->prefs
== NULL
) {
574 _SCErrorSet(kSCStatusInvalidArgument
);
578 bridge_if
= SCNetworkInterfaceGetBSDName(bridge
);
579 path
= CFStringCreateWithFormat(NULL
,
582 kSCPrefVirtualNetworkInterfaces
,
583 kSCNetworkInterfaceTypeBridge
,
585 ok
= SCPreferencesPathRemoveValue(interfacePrivate
->prefs
, path
);
593 SCBridgeInterfaceGetMemberInterfaces(SCBridgeInterfaceRef bridge
)
595 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
597 if (!isA_SCBridgeInterface(bridge
)) {
598 _SCErrorSet(kSCStatusInvalidArgument
);
602 return interfacePrivate
->bridge
.interfaces
;
607 SCBridgeInterfaceGetOptions(SCBridgeInterfaceRef bridge
)
609 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
611 if (!isA_SCBridgeInterface(bridge
)) {
612 _SCErrorSet(kSCStatusInvalidArgument
);
616 return interfacePrivate
->bridge
.options
;
622 __SCBridgeInterfaceSetMemberInterfaces(SCBridgeInterfaceRef bridge
, CFArrayRef members
)
625 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
627 CFMutableArrayRef newMembers
;
630 n
= (members
!= NULL
) ? CFArrayGetCount(members
) : 0;
632 // set member interfaces in the stored preferences
633 if (interfacePrivate
->prefs
!= NULL
) {
634 CFDictionaryRef dict
;
635 CFMutableDictionaryRef newDict
;
638 path
= CFStringCreateWithFormat(NULL
,
641 kSCPrefVirtualNetworkInterfaces
,
642 kSCNetworkInterfaceTypeBridge
,
643 interfacePrivate
->entity_device
);
644 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
645 if (!isA_CFDictionary(dict
)) {
646 // if the prefs are confused
648 _SCErrorSet(kSCStatusFailed
);
652 newMembers
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
653 for (i
= 0; i
< n
; i
++) {
654 SCNetworkInterfaceRef interface
;
655 CFStringRef memberName
;
657 interface
= CFArrayGetValueAtIndex(members
, i
);
658 memberName
= SCNetworkInterfaceGetBSDName(interface
);
659 CFArrayAppendValue(newMembers
, memberName
);
662 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
663 CFDictionarySetValue(newDict
, kSCPropVirtualNetworkInterfacesBridgeInterfaces
, newMembers
);
664 CFRelease(newMembers
);
665 if (!CFEqual(dict
, newDict
)) {
666 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
673 newMembers
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
674 for (i
= 0; i
< n
; i
++) {
675 SCNetworkInterfaceRef member
;
676 SCNetworkInterfacePrivateRef newMember
;
678 member
= CFArrayGetValueAtIndex(members
, i
);
679 newMember
= __SCNetworkInterfaceCreateCopy(NULL
,
681 interfacePrivate
->prefs
,
682 interfacePrivate
->serviceID
);
683 CFArrayAppendValue(newMembers
, newMember
);
684 CFRelease(newMember
);
686 CFRelease(interfacePrivate
->bridge
.interfaces
);
687 interfacePrivate
->bridge
.interfaces
= newMembers
;
695 SCBridgeInterfaceSetMemberInterfaces(SCBridgeInterfaceRef bridge
, CFArrayRef members
)
697 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
699 int sc_status
= kSCStatusOK
;
701 if (!isA_SCBridgeInterface(bridge
)) {
702 _SCErrorSet(kSCStatusInvalidArgument
);
706 if (members
!= NULL
) {
709 if (!isA_CFArray(members
)) {
710 _SCErrorSet(kSCStatusInvalidArgument
);
714 n_members
= CFArrayGetCount(members
);
715 for (CFIndex i
= 0; i
< n_members
; i
++) {
716 SCNetworkInterfaceRef member
;
717 CFStringRef memberName
;
719 member
= CFArrayGetValueAtIndex(members
, i
);
720 if (!isA_SCNetworkInterface(member
)) {
721 _SCErrorSet(kSCStatusInvalidArgument
);
725 memberName
= SCNetworkInterfaceGetBSDName(member
);
726 if (memberName
== NULL
) {
727 _SCErrorSet(kSCStatusInvalidArgument
);
733 if (interfacePrivate
->prefs
!= NULL
) {
734 CFArrayRef available
;
739 CFArrayRef services
= NULL
;
741 current
= SCBridgeInterfaceGetMemberInterfaces(bridge
);
742 n_current
= (current
!= NULL
) ? CFArrayGetCount(current
) : 0;
744 available
= SCBridgeInterfaceCopyAvailableMemberInterfaces(interfacePrivate
->prefs
);
745 n_available
= (available
!= NULL
) ? CFArrayGetCount(available
) : 0;
747 n_members
= (members
!= NULL
) ? CFArrayGetCount(members
) : 0;
748 for (CFIndex i
= 0; i
< n_members
; i
++) {
749 SCNetworkInterfaceRef member
;
751 member
= CFArrayGetValueAtIndex(members
, i
);
753 if ((current
!= NULL
) &&
754 CFArrayContainsValue(current
, CFRangeMake(0, n_current
), member
)) {
755 // current members are allowed
759 if ((available
!= NULL
) &&
760 CFArrayContainsValue(available
, CFRangeMake(0, n_available
), member
)) {
761 // available members are allowed but cannot be associated
762 // with any other network services.
764 if (services
== NULL
) {
765 services
= __SCNetworkServiceCopyAllEnabled(interfacePrivate
->prefs
);
767 if ((services
!= NULL
) &&
768 __SCNetworkServiceExistsForInterface(services
, member
)) {
769 sc_status
= kSCStatusKeyExists
;
777 // if member not allowed
778 sc_status
= kSCStatusInvalidArgument
;
782 if (available
!= NULL
) CFRelease(available
);
783 if (services
!= NULL
) CFRelease(services
);
786 if (sc_status
!= kSCStatusOK
) {
787 _SCErrorSet(sc_status
);
791 ok
= __SCBridgeInterfaceSetMemberInterfaces(bridge
, members
);
797 SCBridgeInterfaceSetLocalizedDisplayName(SCBridgeInterfaceRef bridge
, CFStringRef newName
)
799 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
802 if (!isA_SCBridgeInterface(bridge
)) {
803 _SCErrorSet(kSCStatusInvalidArgument
);
807 if ((newName
!= NULL
) && !isA_CFString(newName
)) {
808 _SCErrorSet(kSCStatusInvalidArgument
);
812 // set name in the stored preferences
813 if (interfacePrivate
->prefs
!= NULL
) {
814 CFDictionaryRef dict
;
815 CFMutableDictionaryRef newDict
;
818 path
= CFStringCreateWithFormat(NULL
,
821 kSCPrefVirtualNetworkInterfaces
,
822 kSCNetworkInterfaceTypeBridge
,
823 interfacePrivate
->entity_device
);
824 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
825 if (!isA_CFDictionary(dict
)) {
826 // if the prefs are confused
828 _SCErrorSet(kSCStatusFailed
);
832 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
833 if (newName
!= NULL
) {
834 CFDictionarySetValue(newDict
, kSCPropUserDefinedName
, newName
);
836 CFDictionaryRemoveValue(newDict
, kSCPropUserDefinedName
);
838 if (!CFEqual(dict
, newDict
)) {
839 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
845 // set name in the SCBridgeInterfaceRef
847 if (interfacePrivate
->localized_name
!= NULL
) {
848 CFRelease(interfacePrivate
->localized_name
);
849 interfacePrivate
->localized_name
= NULL
;
851 if (newName
!= NULL
) {
852 interfacePrivate
->localized_name
= CFStringCreateCopy(NULL
, newName
);
861 SCBridgeInterfaceSetOptions(SCBridgeInterfaceRef bridge
, CFDictionaryRef newOptions
)
863 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
866 if (!isA_SCBridgeInterface(bridge
)) {
867 _SCErrorSet(kSCStatusInvalidArgument
);
871 if ((newOptions
!= NULL
) && !isA_CFDictionary(newOptions
)) {
872 _SCErrorSet(kSCStatusInvalidArgument
);
876 // set options in the stored preferences
877 if (interfacePrivate
->prefs
!= NULL
) {
878 CFDictionaryRef dict
;
879 CFMutableDictionaryRef newDict
;
882 path
= CFStringCreateWithFormat(NULL
,
885 kSCPrefVirtualNetworkInterfaces
,
886 kSCNetworkInterfaceTypeBridge
,
887 interfacePrivate
->entity_device
);
888 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
889 if (!isA_CFDictionary(dict
)) {
890 // if the prefs are confused
892 _SCErrorSet(kSCStatusFailed
);
896 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
897 if (newOptions
!= NULL
) {
898 CFDictionarySetValue(newDict
, kSCPropVirtualNetworkInterfacesBridgeOptions
, newOptions
);
900 CFDictionaryRemoveValue(newDict
, kSCPropVirtualNetworkInterfacesBridgeOptions
);
902 if (!CFEqual(dict
, newDict
)) {
903 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
909 // set options in the SCBridgeInterfaceRef
911 if (interfacePrivate
->bridge
.options
!= NULL
) {
912 CFRelease(interfacePrivate
->bridge
.options
);
913 interfacePrivate
->bridge
.options
= NULL
;
915 if (newOptions
!= NULL
) {
916 CFStringRef name_auto
= NULL
;
918 interfacePrivate
->bridge
.options
= CFDictionaryCreateCopy(NULL
, newOptions
);
920 // set [auto] display name from options
921 if ((interfacePrivate
->localized_name
== NULL
) &&
922 CFDictionaryGetValueIfPresent(newOptions
,
924 (const void **)&name_auto
) &&
925 isA_CFString(name_auto
)) {
927 interfacePrivate
->localized_key
= name_auto
;
928 if (interfacePrivate
->localized_arg1
!= NULL
) {
929 CFRelease(interfacePrivate
->localized_arg1
);
930 interfacePrivate
->localized_arg1
= NULL
;
941 #pragma mark SCBridgeInterface management
946 __bridge_add_interface(int s
, CFStringRef bridge_if
, CFStringRef interface_if
)
952 memset(&ifd
, 0, sizeof(ifd
));
953 (void) _SC_cfstring_to_cstring(bridge_if
,
955 sizeof(ifd
.ifd_name
),
956 kCFStringEncodingASCII
);
957 ifd
.ifd_cmd
= BRDGADD
;
958 ifd
.ifd_len
= sizeof(breq
);
959 ifd
.ifd_data
= (caddr_t
)&breq
;
962 memset(&breq
, 0, sizeof(breq
));
963 (void) _SC_cfstring_to_cstring(interface_if
,
965 sizeof(breq
.ifbr_ifsname
),
966 kCFStringEncodingASCII
);
968 // add new bridge member
969 if (ioctl(s
, SIOCSDRVSPEC
, (caddr_t
)&ifd
) == -1) {
971 SC_log(LOG_ERR
, "could not add interface \"%@\" to bridge \"%@\": %s",
978 SC_log(LOG_INFO
, "%@: added bridge member: %@", bridge_if
, interface_if
);
984 __bridge_remove_interface(int s
, CFStringRef bridge_if
, CFStringRef interface_if
)
990 memset(&ifd
, 0, sizeof(ifd
));
991 (void) _SC_cfstring_to_cstring(bridge_if
,
993 sizeof(ifd
.ifd_name
),
994 kCFStringEncodingASCII
);
995 ifd
.ifd_cmd
= BRDGDEL
;
996 ifd
.ifd_len
= sizeof(breq
);
997 ifd
.ifd_data
= (caddr_t
)&breq
;
999 // bridge member to remove
1000 memset(&breq
, 0, sizeof(breq
));
1001 (void) _SC_cfstring_to_cstring(interface_if
,
1003 sizeof(breq
.ifbr_ifsname
),
1004 kCFStringEncodingASCII
);
1006 // remove bridge member
1007 if (ioctl(s
, SIOCSDRVSPEC
, (caddr_t
)&ifd
) == -1) {
1009 SC_log(LOG_ERR
, "could not remove interface \"%@\" from bridge \"%@\": %s",
1016 SC_log(LOG_INFO
, "%@: removed bridge member: %@", bridge_if
, interface_if
);
1022 __bridge_set_mac(int s
, CFStringRef bridge_if
, CFDataRef macAddr
)
1026 memset(&ifr
, 0, sizeof(ifr
));
1027 (void) _SC_cfstring_to_cstring(bridge_if
,
1029 sizeof(ifr
.ifr_name
),
1030 kCFStringEncodingASCII
);
1031 ifr
.ifr_addr
.sa_len
= CFDataGetLength(macAddr
);
1032 if (ifr
.ifr_addr
.sa_len
> sizeof(ifr
.ifr_addr
.sa_data
)) {
1033 _SCErrorSet(kSCStatusInvalidArgument
);
1034 SC_log(LOG_ERR
, "%@: maformed MAC address (%d > %lu)",
1036 ifr
.ifr_addr
.sa_len
,
1037 sizeof(ifr
.ifr_addr
.sa_data
));
1040 CFDataGetBytes(macAddr
, CFRangeMake(0, ifr
.ifr_addr
.sa_len
), (UInt8
*)ifr
.ifr_addr
.sa_data
);
1042 if (ioctl(s
, SIOCSIFLLADDR
, &ifr
) == -1) {
1044 SC_log(LOG_ERR
, "%@: could not set MAC address: %s",
1050 SC_log(LOG_INFO
, "%@: updated MAC address: %{ private }@", bridge_if
, macAddr
);
1053 #endif // IFT_BRIDGE
1057 _SCBridgeInterfaceUpdateConfiguration(SCPreferencesRef prefs
)
1060 CFArrayRef active
= NULL
;
1061 CFArrayRef config
= NULL
;
1068 if (prefs
== NULL
) {
1069 _SCErrorSet(kSCStatusInvalidArgument
);
1073 /* configured Bridges */
1074 config
= SCBridgeInterfaceCopyAll(prefs
);
1075 nConfig
= (config
!= NULL
) ? CFArrayGetCount(config
) : 0;
1077 /* active Bridges */
1078 active
= _SCBridgeInterfaceCopyActive();
1079 nActive
= (active
!= NULL
) ? CFArrayGetCount(active
) : 0;
1082 * remove any no-longer-configured bridge interfaces and
1083 * any members associated with a bridge that are no longer
1084 * associated with a bridge.
1086 for (i
= 0; i
< nActive
; i
++) {
1087 SCBridgeInterfaceRef a_bridge
;
1088 CFStringRef a_bridge_if
;
1090 Boolean found
= FALSE
;
1092 a_bridge
= CFArrayGetValueAtIndex(active
, i
);
1093 a_bridge_if
= SCNetworkInterfaceGetBSDName(a_bridge
);
1095 for (j
= 0; j
< nConfig
; j
++) {
1096 SCBridgeInterfaceRef c_bridge
;
1097 CFStringRef c_bridge_if
;
1099 c_bridge
= CFArrayGetValueAtIndex(config
, j
);
1100 c_bridge_if
= SCNetworkInterfaceGetBSDName(c_bridge
);
1102 if (CFEqual(a_bridge_if
, c_bridge_if
)) {
1104 CFArrayRef a_bridge_interfaces
;
1106 CFArrayRef c_bridge_interfaces
;
1109 c_bridge_interfaces
= SCBridgeInterfaceGetMemberInterfaces(c_bridge
);
1110 c_count
= (c_bridge_interfaces
!= NULL
) ? CFArrayGetCount(c_bridge_interfaces
) : 0;
1112 a_bridge_interfaces
= SCBridgeInterfaceGetMemberInterfaces(a_bridge
);
1113 a_count
= (a_bridge_interfaces
!= NULL
) ? CFArrayGetCount(a_bridge_interfaces
) : 0;
1115 for (a
= 0; a
< a_count
; a
++) {
1116 SCNetworkInterfaceRef a_interface
;
1117 CFStringRef a_interface_if
;
1119 a_interface
= CFArrayGetValueAtIndex(a_bridge_interfaces
, a
);
1120 if ((c_count
== 0) ||
1121 !CFArrayContainsValue(c_bridge_interfaces
,
1122 CFRangeMake(0, c_count
),
1125 * if this member is no longer part
1129 s
= inet_dgram_socket();
1137 a_interface_if
= SCNetworkInterfaceGetBSDName(a_interface
);
1138 if (!__bridge_remove_interface(s
, a_bridge_if
, a_interface_if
)) {
1151 * if this interface is no longer configured
1154 s
= inet_dgram_socket();
1162 if (!__destroyInterface(s
, a_bridge_if
)) {
1170 * add any newly-configured bridge interfaces and add any
1171 * members that should now be associated with the bridge.
1173 for (i
= 0; i
< nConfig
; i
++) {
1174 SCBridgeInterfaceRef c_bridge
;
1175 CFArrayRef c_bridge_interfaces
;
1176 CFStringRef c_bridge_if
;
1178 Boolean found
= FALSE
;
1180 Boolean setMAC
= FALSE
;
1182 c_bridge
= CFArrayGetValueAtIndex(config
, i
);
1183 c_bridge_if
= SCNetworkInterfaceGetBSDName(c_bridge
);
1184 c_bridge_interfaces
= SCBridgeInterfaceGetMemberInterfaces(c_bridge
);
1185 c_count
= (c_bridge_interfaces
!= NULL
) ? CFArrayGetCount(c_bridge_interfaces
) : 0;
1187 for (j
= 0; j
< nActive
; j
++) {
1188 SCBridgeInterfaceRef a_bridge
;
1189 CFArrayRef a_bridge_interfaces
;
1190 CFStringRef a_bridge_if
;
1193 a_bridge
= CFArrayGetValueAtIndex(active
, j
);
1194 a_bridge_if
= SCNetworkInterfaceGetBSDName(a_bridge
);
1195 a_bridge_interfaces
= SCBridgeInterfaceGetMemberInterfaces(a_bridge
);
1196 a_count
= (a_bridge_interfaces
!= NULL
) ? CFArrayGetCount(a_bridge_interfaces
) : 0;
1198 if (CFEqual(c_bridge_if
, a_bridge_if
)) {
1203 if (_SC_CFEqual(c_bridge_interfaces
, a_bridge_interfaces
)) {
1204 break; // if no change
1208 s
= inet_dgram_socket();
1217 * ensure that the first member of the bridge matches, if
1218 * not then we remove all current members and add them
1219 * back in the preferred order.
1221 if ((c_count
> 0) &&
1223 !CFEqual(CFArrayGetValueAtIndex(c_bridge_interfaces
, 0),
1224 CFArrayGetValueAtIndex(a_bridge_interfaces
, 0))) {
1227 for (a
= 0; a
< a_count
; a
++) {
1228 SCNetworkInterfaceRef a_interface
;
1229 CFStringRef a_interface_if
;
1231 a_interface
= CFArrayGetValueAtIndex(a_bridge_interfaces
, a
);
1232 if (!CFArrayContainsValue(c_bridge_interfaces
,
1233 CFRangeMake(0, c_count
),
1235 continue; // if already removed
1238 a_interface_if
= SCNetworkInterfaceGetBSDName(a_interface
);
1239 if (!__bridge_remove_interface(s
, a_bridge_if
, a_interface_if
)) {
1244 a_count
= 0; // all active members have been removed
1252 * add any members which are not currently associated
1253 * with the bridge interface.
1255 for (c
= 0; c
< c_count
; c
++) {
1256 SCNetworkInterfaceRef c_interface
;
1257 SCNetworkInterfacePrivateRef c_interfacePrivate
;
1258 CFStringRef c_interface_if
;
1260 c_interface
= CFArrayGetValueAtIndex(c_bridge_interfaces
, c
);
1261 if ((a_count
== 0) ||
1262 !CFArrayContainsValue(a_bridge_interfaces
,
1263 CFRangeMake(0, a_count
),
1266 * check if this member interface can be added to a bridge.
1268 c_interfacePrivate
= (SCNetworkInterfacePrivateRef
)c_interface
;
1269 if (!c_interfacePrivate
->supportsBridge
) {
1270 // if member not supported
1275 * if this is the first member interface, set the MAC address
1281 macAddr
= _SCNetworkInterfaceGetHardwareAddress(c_interface
);
1282 if (!__bridge_set_mac(s
, c_bridge_if
, macAddr
)) {
1283 // if bridge MAC could not be set
1290 * add the member interface to the bridge.
1292 c_interface_if
= SCNetworkInterfaceGetBSDName(c_interface
);
1293 if (!__bridge_add_interface(s
, c_bridge_if
, c_interface_if
)) {
1294 // if member could not be added
1308 s
= inet_dgram_socket();
1317 * establish the new bridge interface.
1319 if (!__createInterface(s
, c_bridge_if
)) {
1328 * add the member interfaces
1330 for (c
= 0; c
< c_count
; c
++) {
1331 SCNetworkInterfaceRef c_interface
;
1332 SCNetworkInterfacePrivateRef c_interfacePrivate
;
1333 CFStringRef c_interface_if
;
1335 c_interface
= CFArrayGetValueAtIndex(c_bridge_interfaces
, c
);
1336 c_interfacePrivate
= (SCNetworkInterfacePrivateRef
)c_interface
;
1337 if (!c_interfacePrivate
->supportsBridge
) {
1338 // if member not supported
1343 * if this is the first member interface, set the MAC address
1349 macAddr
= _SCNetworkInterfaceGetHardwareAddress(c_interface
);
1350 if (!__bridge_set_mac(s
, c_bridge_if
, macAddr
)) {
1351 // if bridge MAC could not be set
1358 * add the member interface to the bridge.
1360 c_interface_if
= SCNetworkInterfaceGetBSDName(c_interface
);
1361 if (!__bridge_add_interface(s
, c_bridge_if
, c_interface_if
)) {
1362 // if member could not be added
1371 if (active
!= NULL
) CFRelease(active
);
1372 if (config
!= NULL
) CFRelease(config
);
1373 if (s
!= -1) (void) close(s
);
1378 #endif // IFT_BRIDGE