2 * Copyright (c) 2009-2018, 2020 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
= SCPreferencesCreateCompanion(prefs
, INTERFACES_DEFAULT_CONFIG
);
255 context
.bridges
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
256 context
.prefs
= prefs
;
257 context
.ni_prefs
= ni_prefs
;
259 path
= CFStringCreateWithFormat(NULL
,
262 kSCPrefVirtualNetworkInterfaces
,
263 kSCNetworkInterfaceTypeBridge
);
264 dict
= SCPreferencesPathGetValue(prefs
, path
);
266 if (isA_CFDictionary(dict
)) {
267 my_CFDictionaryApplyFunction(dict
, add_configured_interface
, &context
);
270 if (ni_prefs
!= NULL
) {
273 return context
.bridges
;
277 __private_extern__
void
278 __SCBridgeInterfaceListCollectMembers(CFArrayRef interfaces
, CFMutableSetRef set
)
283 n
= CFArrayGetCount(interfaces
);
284 for (i
= 0; i
< n
; i
++) {
285 SCBridgeInterfaceRef bridgeInterface
;
288 bridgeInterface
= CFArrayGetValueAtIndex(interfaces
, i
);
289 members
= SCBridgeInterfaceGetMemberInterfaces(bridgeInterface
);
290 if (members
!= NULL
) {
294 // exclude the member interfaces of this bridge
295 n_members
= CFArrayGetCount(members
);
296 for (j
= 0; j
< n_members
; j
++) {
297 SCNetworkInterfaceRef member
;
299 member
= CFArrayGetValueAtIndex(members
, j
);
300 CFSetAddValue(set
, member
);
309 CFArrayRef
/* of SCNetworkInterfaceRef's */
310 SCBridgeInterfaceCopyAvailableMemberInterfaces(SCPreferencesRef prefs
)
312 CFMutableArrayRef available
;
313 CFMutableSetRef excluded
;
314 CFArrayRef interfaces
;
316 available
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
317 excluded
= CFSetCreateMutable (NULL
, 0, &kCFTypeSetCallBacks
);
319 #if !TARGET_OS_IPHONE
320 // exclude Bond [member] interfaces
321 interfaces
= SCBondInterfaceCopyAll(prefs
);
322 if (interfaces
!= NULL
) {
323 __SCBondInterfaceListCollectMembers(interfaces
, excluded
);
324 CFRelease(interfaces
);
326 #endif // !TARGET_OS_IPHONE
328 // exclude Bridge [member] interfaces
329 interfaces
= SCBridgeInterfaceCopyAll(prefs
);
330 if (interfaces
!= NULL
) {
331 __SCBridgeInterfaceListCollectMembers(interfaces
, excluded
);
332 CFRelease(interfaces
);
335 // exclude VLAN [physical] interfaces
336 interfaces
= SCVLANInterfaceCopyAll(prefs
);
337 if (interfaces
!= NULL
) {
341 n
= CFArrayGetCount(interfaces
);
342 for (i
= 0; i
< n
; i
++) {
343 SCVLANInterfaceRef vlanInterface
;
344 SCNetworkInterfaceRef physical
;
346 // exclude the physical interface of this VLAN
347 vlanInterface
= CFArrayGetValueAtIndex(interfaces
, i
);
348 physical
= SCVLANInterfaceGetPhysicalInterface(vlanInterface
);
349 CFSetAddValue(excluded
, physical
);
351 CFRelease(interfaces
);
354 // identify available interfaces
355 interfaces
= __SCNetworkInterfaceCopyAll_IONetworkInterface(FALSE
);
356 if (interfaces
!= NULL
) {
360 n
= CFArrayGetCount(interfaces
);
361 for (i
= 0; i
< n
; i
++) {
362 SCNetworkInterfaceRef interface
;
363 SCNetworkInterfacePrivateRef interfacePrivate
;
365 interface
= CFArrayGetValueAtIndex(interfaces
, i
);
366 interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
368 if (!interfacePrivate
->supportsBridge
) {
369 // if this interface is not available
373 if (CFSetContainsValue(excluded
, interface
)) {
378 CFArrayAppendValue(available
, interface
);
380 CFRelease(interfaces
);
390 _SCBridgeInterfaceCopyActive(void)
392 struct ifaddrs
*ifap
;
395 CFMutableArrayRef bridges
= NULL
;
397 if (getifaddrs(&ifap
) == -1) {
399 SC_log(LOG_NOTICE
, "getifaddrs() failed: %s", strerror(errno
));
403 s
= inet_dgram_socket();
409 bridges
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
411 for (ifp
= ifap
; ifp
!= NULL
; ifp
= ifp
->ifa_next
) {
413 SCBridgeInterfaceRef bridge
;
414 CFStringRef bridge_if
;
415 struct ifbifconf
*ibc_p
;
416 struct if_data
*if_data
;
417 CFMutableArrayRef members
= NULL
;
420 if_data
= (struct if_data
*)ifp
->ifa_data
;
422 || ifp
->ifa_addr
->sa_family
!= AF_LINK
423 || if_data
->ifi_type
!= IFT_BRIDGE
) {
427 // make sure that we leave non-SC configured bridge
428 // interfaces (those with unit #'s >= 100) alone.
429 n
= strlen(ifp
->ifa_name
);
431 isdigit(ifp
->ifa_name
[n
- 1]) &&
432 isdigit(ifp
->ifa_name
[n
- 2]) &&
433 isdigit(ifp
->ifa_name
[n
- 3])) {
434 // if not SC managed bridge interface
438 ibc_p
= ifbifconf_copy(s
, ifp
->ifa_name
);
440 if (errno
== EBUSY
) {
444 SC_log(LOG_NOTICE
, "ifbifconf_copy(%s) failed: %s",
452 // create the bridge interface
453 bridge_if
= CFStringCreateWithCString(NULL
, ifp
->ifa_name
, kCFStringEncodingASCII
);
454 bridge
= (SCBridgeInterfaceRef
)_SCBridgeInterfaceCreatePrivate(NULL
, bridge_if
);
455 CFRelease(bridge_if
);
457 // add member interfaces
458 if (ibc_p
->ifbic_len
> 0) {
459 // iterate over each member interface
460 for (size_t i
= 0; i
< ibc_p
->ifbic_len
/ sizeof(struct ifbreq
); i
++) {
461 struct ifbreq
*ibr_p
;
464 ibr_p
= ibc_p
->ifbic_req
+ i
;
465 member
= CFStringCreateWithCString(NULL
, ibr_p
->ifbr_ifsname
, kCFStringEncodingASCII
);
466 add_interface(&members
, member
, NULL
);
472 if (members
!= NULL
) {
473 __SCBridgeInterfaceSetMemberInterfaces(bridge
, members
);
478 CFArrayAppendValue(bridges
, bridge
);
494 SCBridgeInterfaceCreate(SCPreferencesRef prefs
)
496 CFAllocatorRef allocator
;
497 SCBridgeInterfaceRef bridge
= NULL
;
501 _SCErrorSet(kSCStatusInvalidArgument
);
505 allocator
= CFGetAllocator(prefs
);
507 // create a new bridge using an unused interface name
508 for (i
= 0; bridge
== NULL
; i
++) {
509 CFDictionaryRef dict
;
510 CFStringRef bridge_if
;
511 SCNetworkInterfacePrivateRef interfacePrivate
;
512 CFMutableDictionaryRef newDict
;
513 CFArrayRef newInterfaces
;
517 bridge_if
= CFStringCreateWithFormat(allocator
, NULL
, CFSTR("bridge%ld"), i
);
518 path
= CFStringCreateWithFormat(allocator
,
521 kSCPrefVirtualNetworkInterfaces
,
522 kSCNetworkInterfaceTypeBridge
,
524 dict
= SCPreferencesPathGetValue(prefs
, path
);
526 // if bridge interface name not available
528 CFRelease(bridge_if
);
532 // add the bridge to the stored preferences
533 newDict
= CFDictionaryCreateMutable(allocator
,
535 &kCFTypeDictionaryKeyCallBacks
,
536 &kCFTypeDictionaryValueCallBacks
);
537 newInterfaces
= CFArrayCreate(allocator
, NULL
, 0, &kCFTypeArrayCallBacks
);
538 CFDictionaryAddValue(newDict
, kSCPropVirtualNetworkInterfacesBridgeInterfaces
, newInterfaces
);
539 CFRelease(newInterfaces
);
540 ok
= SCPreferencesPathSetValue(prefs
, path
, newDict
);
544 // if the bridge could not be saved
545 CFRelease(bridge_if
);
549 // create the SCBridgeInterfaceRef
550 bridge
= (SCBridgeInterfaceRef
)_SCBridgeInterfaceCreatePrivate(allocator
, bridge_if
);
551 CFRelease(bridge_if
);
553 // estabish link to the stored configuration
554 interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
555 interfacePrivate
->prefs
= CFRetain(prefs
);
563 SCBridgeInterfaceRemove(SCBridgeInterfaceRef bridge
)
565 CFStringRef bridge_if
;
566 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
570 if (!isA_SCBridgeInterface(bridge
)) {
571 _SCErrorSet(kSCStatusInvalidArgument
);
575 if (interfacePrivate
->prefs
== NULL
) {
576 _SCErrorSet(kSCStatusInvalidArgument
);
580 bridge_if
= SCNetworkInterfaceGetBSDName(bridge
);
581 path
= CFStringCreateWithFormat(NULL
,
584 kSCPrefVirtualNetworkInterfaces
,
585 kSCNetworkInterfaceTypeBridge
,
587 ok
= SCPreferencesPathRemoveValue(interfacePrivate
->prefs
, path
);
595 SCBridgeInterfaceGetMemberInterfaces(SCBridgeInterfaceRef bridge
)
597 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
599 if (!isA_SCBridgeInterface(bridge
)) {
600 _SCErrorSet(kSCStatusInvalidArgument
);
604 return interfacePrivate
->bridge
.interfaces
;
609 SCBridgeInterfaceGetOptions(SCBridgeInterfaceRef bridge
)
611 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
613 if (!isA_SCBridgeInterface(bridge
)) {
614 _SCErrorSet(kSCStatusInvalidArgument
);
618 return interfacePrivate
->bridge
.options
;
624 __SCBridgeInterfaceSetMemberInterfaces(SCBridgeInterfaceRef bridge
, CFArrayRef members
)
627 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
629 CFMutableArrayRef newMembers
;
632 n
= (members
!= NULL
) ? CFArrayGetCount(members
) : 0;
634 // set member interfaces in the stored preferences
635 if (interfacePrivate
->prefs
!= NULL
) {
636 CFDictionaryRef dict
;
637 CFMutableDictionaryRef newDict
;
640 path
= CFStringCreateWithFormat(NULL
,
643 kSCPrefVirtualNetworkInterfaces
,
644 kSCNetworkInterfaceTypeBridge
,
645 interfacePrivate
->entity_device
);
646 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
647 if (!isA_CFDictionary(dict
)) {
648 // if the prefs are confused
650 _SCErrorSet(kSCStatusFailed
);
654 newMembers
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
655 for (i
= 0; i
< n
; i
++) {
656 SCNetworkInterfaceRef interface
;
657 CFStringRef memberName
;
659 interface
= CFArrayGetValueAtIndex(members
, i
);
660 memberName
= SCNetworkInterfaceGetBSDName(interface
);
661 CFArrayAppendValue(newMembers
, memberName
);
664 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
665 CFDictionarySetValue(newDict
, kSCPropVirtualNetworkInterfacesBridgeInterfaces
, newMembers
);
666 CFRelease(newMembers
);
667 if (!CFEqual(dict
, newDict
)) {
668 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
675 newMembers
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
676 for (i
= 0; i
< n
; i
++) {
677 SCNetworkInterfaceRef member
;
678 SCNetworkInterfacePrivateRef newMember
;
680 member
= CFArrayGetValueAtIndex(members
, i
);
681 newMember
= __SCNetworkInterfaceCreateCopy(NULL
,
683 interfacePrivate
->prefs
,
684 interfacePrivate
->serviceID
);
685 CFArrayAppendValue(newMembers
, newMember
);
686 CFRelease(newMember
);
688 CFRelease(interfacePrivate
->bridge
.interfaces
);
689 interfacePrivate
->bridge
.interfaces
= newMembers
;
697 SCBridgeInterfaceSetMemberInterfaces(SCBridgeInterfaceRef bridge
, CFArrayRef members
)
699 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
701 int sc_status
= kSCStatusOK
;
703 if (!isA_SCBridgeInterface(bridge
)) {
704 _SCErrorSet(kSCStatusInvalidArgument
);
708 if (members
!= NULL
) {
711 if (!isA_CFArray(members
)) {
712 _SCErrorSet(kSCStatusInvalidArgument
);
716 n_members
= CFArrayGetCount(members
);
717 for (CFIndex i
= 0; i
< n_members
; i
++) {
718 SCNetworkInterfaceRef member
;
719 CFStringRef memberName
;
721 member
= CFArrayGetValueAtIndex(members
, i
);
722 if (!isA_SCNetworkInterface(member
)) {
723 _SCErrorSet(kSCStatusInvalidArgument
);
727 memberName
= SCNetworkInterfaceGetBSDName(member
);
728 if (memberName
== NULL
) {
729 _SCErrorSet(kSCStatusInvalidArgument
);
735 if (interfacePrivate
->prefs
!= NULL
) {
736 CFArrayRef available
;
741 CFArrayRef services
= NULL
;
743 current
= SCBridgeInterfaceGetMemberInterfaces(bridge
);
744 n_current
= (current
!= NULL
) ? CFArrayGetCount(current
) : 0;
746 available
= SCBridgeInterfaceCopyAvailableMemberInterfaces(interfacePrivate
->prefs
);
747 n_available
= (available
!= NULL
) ? CFArrayGetCount(available
) : 0;
749 n_members
= (members
!= NULL
) ? CFArrayGetCount(members
) : 0;
750 for (CFIndex i
= 0; i
< n_members
; i
++) {
751 SCNetworkInterfaceRef member
;
753 member
= CFArrayGetValueAtIndex(members
, i
);
755 if ((current
!= NULL
) &&
756 CFArrayContainsValue(current
, CFRangeMake(0, n_current
), member
)) {
757 // current members are allowed
761 if ((available
!= NULL
) &&
762 CFArrayContainsValue(available
, CFRangeMake(0, n_available
), member
)) {
763 // available members are allowed but cannot be associated
764 // with any other network services.
766 if (services
== NULL
) {
767 services
= __SCNetworkServiceCopyAllEnabled(interfacePrivate
->prefs
);
769 if ((services
!= NULL
) &&
770 __SCNetworkServiceExistsForInterface(services
, member
)) {
771 sc_status
= kSCStatusKeyExists
;
779 // if member not allowed
780 sc_status
= kSCStatusInvalidArgument
;
784 if (available
!= NULL
) CFRelease(available
);
785 if (services
!= NULL
) CFRelease(services
);
788 if (sc_status
!= kSCStatusOK
) {
789 _SCErrorSet(sc_status
);
793 ok
= __SCBridgeInterfaceSetMemberInterfaces(bridge
, members
);
799 SCBridgeInterfaceSetLocalizedDisplayName(SCBridgeInterfaceRef bridge
, CFStringRef newName
)
801 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
804 if (!isA_SCBridgeInterface(bridge
)) {
805 _SCErrorSet(kSCStatusInvalidArgument
);
809 if ((newName
!= NULL
) && !isA_CFString(newName
)) {
810 _SCErrorSet(kSCStatusInvalidArgument
);
814 // set name in the stored preferences
815 if (interfacePrivate
->prefs
!= NULL
) {
816 CFDictionaryRef dict
;
817 CFMutableDictionaryRef newDict
;
820 path
= CFStringCreateWithFormat(NULL
,
823 kSCPrefVirtualNetworkInterfaces
,
824 kSCNetworkInterfaceTypeBridge
,
825 interfacePrivate
->entity_device
);
826 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
827 if (!isA_CFDictionary(dict
)) {
828 // if the prefs are confused
830 _SCErrorSet(kSCStatusFailed
);
834 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
835 if (newName
!= NULL
) {
836 CFDictionarySetValue(newDict
, kSCPropUserDefinedName
, newName
);
838 CFDictionaryRemoveValue(newDict
, kSCPropUserDefinedName
);
840 if (!CFEqual(dict
, newDict
)) {
841 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
847 // set name in the SCBridgeInterfaceRef
849 if (interfacePrivate
->localized_name
!= NULL
) {
850 CFRelease(interfacePrivate
->localized_name
);
851 interfacePrivate
->localized_name
= NULL
;
853 if (newName
!= NULL
) {
854 interfacePrivate
->localized_name
= CFStringCreateCopy(NULL
, newName
);
863 SCBridgeInterfaceSetOptions(SCBridgeInterfaceRef bridge
, CFDictionaryRef newOptions
)
865 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
868 if (!isA_SCBridgeInterface(bridge
)) {
869 _SCErrorSet(kSCStatusInvalidArgument
);
873 if ((newOptions
!= NULL
) && !isA_CFDictionary(newOptions
)) {
874 _SCErrorSet(kSCStatusInvalidArgument
);
878 // set options in the stored preferences
879 if (interfacePrivate
->prefs
!= NULL
) {
880 CFDictionaryRef dict
;
881 CFMutableDictionaryRef newDict
;
884 path
= CFStringCreateWithFormat(NULL
,
887 kSCPrefVirtualNetworkInterfaces
,
888 kSCNetworkInterfaceTypeBridge
,
889 interfacePrivate
->entity_device
);
890 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
891 if (!isA_CFDictionary(dict
)) {
892 // if the prefs are confused
894 _SCErrorSet(kSCStatusFailed
);
898 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
899 if (newOptions
!= NULL
) {
900 CFDictionarySetValue(newDict
, kSCPropVirtualNetworkInterfacesBridgeOptions
, newOptions
);
902 CFDictionaryRemoveValue(newDict
, kSCPropVirtualNetworkInterfacesBridgeOptions
);
904 if (!CFEqual(dict
, newDict
)) {
905 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
911 // set options in the SCBridgeInterfaceRef
913 if (interfacePrivate
->bridge
.options
!= NULL
) {
914 CFRelease(interfacePrivate
->bridge
.options
);
915 interfacePrivate
->bridge
.options
= NULL
;
917 if (newOptions
!= NULL
) {
918 CFStringRef name_auto
= NULL
;
920 interfacePrivate
->bridge
.options
= CFDictionaryCreateCopy(NULL
, newOptions
);
922 // set [auto] display name from options
923 if ((interfacePrivate
->localized_name
== NULL
) &&
924 CFDictionaryGetValueIfPresent(newOptions
,
926 (const void **)&name_auto
) &&
927 isA_CFString(name_auto
)) {
929 interfacePrivate
->localized_key
= name_auto
;
930 if (interfacePrivate
->localized_arg1
!= NULL
) {
931 CFRelease(interfacePrivate
->localized_arg1
);
932 interfacePrivate
->localized_arg1
= NULL
;
943 #pragma mark SCBridgeInterface management
948 __bridge_add_interface(int s
, CFStringRef bridge_if
, CFStringRef interface_if
)
954 memset(&ifd
, 0, sizeof(ifd
));
955 (void) _SC_cfstring_to_cstring(bridge_if
,
957 sizeof(ifd
.ifd_name
),
958 kCFStringEncodingASCII
);
959 ifd
.ifd_cmd
= BRDGADD
;
960 ifd
.ifd_len
= sizeof(breq
);
961 ifd
.ifd_data
= (caddr_t
)&breq
;
964 memset(&breq
, 0, sizeof(breq
));
965 (void) _SC_cfstring_to_cstring(interface_if
,
967 sizeof(breq
.ifbr_ifsname
),
968 kCFStringEncodingASCII
);
970 // add new bridge member
971 if (ioctl(s
, SIOCSDRVSPEC
, (caddr_t
)&ifd
) == -1) {
973 SC_log(LOG_ERR
, "could not add interface \"%@\" to bridge \"%@\": %s",
980 SC_log(LOG_INFO
, "%@: added bridge member: %@", bridge_if
, interface_if
);
986 __bridge_remove_interface(int s
, CFStringRef bridge_if
, CFStringRef interface_if
)
992 memset(&ifd
, 0, sizeof(ifd
));
993 (void) _SC_cfstring_to_cstring(bridge_if
,
995 sizeof(ifd
.ifd_name
),
996 kCFStringEncodingASCII
);
997 ifd
.ifd_cmd
= BRDGDEL
;
998 ifd
.ifd_len
= sizeof(breq
);
999 ifd
.ifd_data
= (caddr_t
)&breq
;
1001 // bridge member to remove
1002 memset(&breq
, 0, sizeof(breq
));
1003 (void) _SC_cfstring_to_cstring(interface_if
,
1005 sizeof(breq
.ifbr_ifsname
),
1006 kCFStringEncodingASCII
);
1008 // remove bridge member
1009 if (ioctl(s
, SIOCSDRVSPEC
, (caddr_t
)&ifd
) == -1) {
1011 SC_log(LOG_ERR
, "could not remove interface \"%@\" from bridge \"%@\": %s",
1018 SC_log(LOG_INFO
, "%@: removed bridge member: %@", bridge_if
, interface_if
);
1024 __bridge_set_mac(int s
, CFStringRef bridge_if
, CFDataRef macAddr
)
1028 memset(&ifr
, 0, sizeof(ifr
));
1029 (void) _SC_cfstring_to_cstring(bridge_if
,
1031 sizeof(ifr
.ifr_name
),
1032 kCFStringEncodingASCII
);
1033 ifr
.ifr_addr
.sa_len
= CFDataGetLength(macAddr
);
1034 if (ifr
.ifr_addr
.sa_len
> sizeof(ifr
.ifr_addr
.sa_data
)) {
1035 _SCErrorSet(kSCStatusInvalidArgument
);
1036 SC_log(LOG_ERR
, "%@: maformed MAC address (%d > %lu)",
1038 ifr
.ifr_addr
.sa_len
,
1039 sizeof(ifr
.ifr_addr
.sa_data
));
1042 CFDataGetBytes(macAddr
, CFRangeMake(0, ifr
.ifr_addr
.sa_len
), (UInt8
*)ifr
.ifr_addr
.sa_data
);
1044 if (ioctl(s
, SIOCSIFLLADDR
, &ifr
) == -1) {
1046 SC_log(LOG_ERR
, "%@: could not set MAC address: %s",
1052 SC_log(LOG_INFO
, "%@: updated MAC address: %{ private }@", bridge_if
, macAddr
);
1055 #endif // IFT_BRIDGE
1059 _SCBridgeInterfaceUpdateConfiguration(SCPreferencesRef prefs
)
1062 CFArrayRef active
= NULL
;
1063 CFArrayRef config
= NULL
;
1070 if (prefs
== NULL
) {
1071 _SCErrorSet(kSCStatusInvalidArgument
);
1075 /* configured Bridges */
1076 config
= SCBridgeInterfaceCopyAll(prefs
);
1077 nConfig
= (config
!= NULL
) ? CFArrayGetCount(config
) : 0;
1079 /* active Bridges */
1080 active
= _SCBridgeInterfaceCopyActive();
1081 nActive
= (active
!= NULL
) ? CFArrayGetCount(active
) : 0;
1084 * remove any no-longer-configured bridge interfaces and
1085 * any members associated with a bridge that are no longer
1086 * associated with a bridge.
1088 for (i
= 0; i
< nActive
; i
++) {
1089 SCBridgeInterfaceRef a_bridge
;
1090 CFStringRef a_bridge_if
;
1092 Boolean found
= FALSE
;
1094 a_bridge
= CFArrayGetValueAtIndex(active
, i
);
1095 a_bridge_if
= SCNetworkInterfaceGetBSDName(a_bridge
);
1097 for (j
= 0; j
< nConfig
; j
++) {
1098 SCBridgeInterfaceRef c_bridge
;
1099 CFStringRef c_bridge_if
;
1101 c_bridge
= CFArrayGetValueAtIndex(config
, j
);
1102 c_bridge_if
= SCNetworkInterfaceGetBSDName(c_bridge
);
1104 if (CFEqual(a_bridge_if
, c_bridge_if
)) {
1106 CFArrayRef a_bridge_interfaces
;
1108 CFArrayRef c_bridge_interfaces
;
1111 c_bridge_interfaces
= SCBridgeInterfaceGetMemberInterfaces(c_bridge
);
1112 c_count
= (c_bridge_interfaces
!= NULL
) ? CFArrayGetCount(c_bridge_interfaces
) : 0;
1114 a_bridge_interfaces
= SCBridgeInterfaceGetMemberInterfaces(a_bridge
);
1115 a_count
= (a_bridge_interfaces
!= NULL
) ? CFArrayGetCount(a_bridge_interfaces
) : 0;
1117 for (a
= 0; a
< a_count
; a
++) {
1118 SCNetworkInterfaceRef a_interface
;
1119 CFStringRef a_interface_if
;
1121 a_interface
= CFArrayGetValueAtIndex(a_bridge_interfaces
, a
);
1122 if ((c_count
== 0) ||
1123 !CFArrayContainsValue(c_bridge_interfaces
,
1124 CFRangeMake(0, c_count
),
1127 * if this member is no longer part
1131 s
= inet_dgram_socket();
1139 a_interface_if
= SCNetworkInterfaceGetBSDName(a_interface
);
1140 if (!__bridge_remove_interface(s
, a_bridge_if
, a_interface_if
)) {
1153 * if this interface is no longer configured
1156 s
= inet_dgram_socket();
1164 if (!__destroyInterface(s
, a_bridge_if
)) {
1172 * add any newly-configured bridge interfaces and add any
1173 * members that should now be associated with the bridge.
1175 for (i
= 0; i
< nConfig
; i
++) {
1176 SCBridgeInterfaceRef c_bridge
;
1177 CFArrayRef c_bridge_interfaces
;
1178 CFStringRef c_bridge_if
;
1180 Boolean found
= FALSE
;
1182 Boolean setMAC
= FALSE
;
1184 c_bridge
= CFArrayGetValueAtIndex(config
, i
);
1185 c_bridge_if
= SCNetworkInterfaceGetBSDName(c_bridge
);
1186 c_bridge_interfaces
= SCBridgeInterfaceGetMemberInterfaces(c_bridge
);
1187 c_count
= (c_bridge_interfaces
!= NULL
) ? CFArrayGetCount(c_bridge_interfaces
) : 0;
1189 for (j
= 0; j
< nActive
; j
++) {
1190 SCBridgeInterfaceRef a_bridge
;
1191 CFArrayRef a_bridge_interfaces
;
1192 CFStringRef a_bridge_if
;
1195 a_bridge
= CFArrayGetValueAtIndex(active
, j
);
1196 a_bridge_if
= SCNetworkInterfaceGetBSDName(a_bridge
);
1197 a_bridge_interfaces
= SCBridgeInterfaceGetMemberInterfaces(a_bridge
);
1198 a_count
= (a_bridge_interfaces
!= NULL
) ? CFArrayGetCount(a_bridge_interfaces
) : 0;
1200 if (CFEqual(c_bridge_if
, a_bridge_if
)) {
1205 if (_SC_CFEqual(c_bridge_interfaces
, a_bridge_interfaces
)) {
1206 break; // if no change
1210 s
= inet_dgram_socket();
1219 * ensure that the first member of the bridge matches, if
1220 * not then we remove all current members and add them
1221 * back in the preferred order.
1223 if ((c_count
> 0) &&
1225 !CFEqual(CFArrayGetValueAtIndex(c_bridge_interfaces
, 0),
1226 CFArrayGetValueAtIndex(a_bridge_interfaces
, 0))) {
1229 for (a
= 0; a
< a_count
; a
++) {
1230 SCNetworkInterfaceRef a_interface
;
1231 CFStringRef a_interface_if
;
1233 a_interface
= CFArrayGetValueAtIndex(a_bridge_interfaces
, a
);
1234 if (!CFArrayContainsValue(c_bridge_interfaces
,
1235 CFRangeMake(0, c_count
),
1237 continue; // if already removed
1240 a_interface_if
= SCNetworkInterfaceGetBSDName(a_interface
);
1241 if (!__bridge_remove_interface(s
, a_bridge_if
, a_interface_if
)) {
1246 a_count
= 0; // all active members have been removed
1254 * add any members which are not currently associated
1255 * with the bridge interface.
1257 for (c
= 0; c
< c_count
; c
++) {
1258 SCNetworkInterfaceRef c_interface
;
1259 SCNetworkInterfacePrivateRef c_interfacePrivate
;
1260 CFStringRef c_interface_if
;
1262 c_interface
= CFArrayGetValueAtIndex(c_bridge_interfaces
, c
);
1263 if ((a_count
== 0) ||
1264 !CFArrayContainsValue(a_bridge_interfaces
,
1265 CFRangeMake(0, a_count
),
1268 * check if this member interface can be added to a bridge.
1270 c_interfacePrivate
= (SCNetworkInterfacePrivateRef
)c_interface
;
1271 if (!c_interfacePrivate
->supportsBridge
) {
1272 // if member not supported
1277 * if this is the first member interface, set the MAC address
1283 macAddr
= _SCNetworkInterfaceGetHardwareAddress(c_interface
);
1284 if (!__bridge_set_mac(s
, c_bridge_if
, macAddr
)) {
1285 // if bridge MAC could not be set
1292 * add the member interface to the bridge.
1294 c_interface_if
= SCNetworkInterfaceGetBSDName(c_interface
);
1295 if (!__bridge_add_interface(s
, c_bridge_if
, c_interface_if
)) {
1296 // if member could not be added
1310 s
= inet_dgram_socket();
1319 * establish the new bridge interface.
1321 if (!__createInterface(s
, c_bridge_if
)) {
1330 * add the member interfaces
1332 for (c
= 0; c
< c_count
; c
++) {
1333 SCNetworkInterfaceRef c_interface
;
1334 SCNetworkInterfacePrivateRef c_interfacePrivate
;
1335 CFStringRef c_interface_if
;
1337 c_interface
= CFArrayGetValueAtIndex(c_bridge_interfaces
, c
);
1338 c_interfacePrivate
= (SCNetworkInterfacePrivateRef
)c_interface
;
1339 if (!c_interfacePrivate
->supportsBridge
) {
1340 // if member not supported
1345 * if this is the first member interface, set the MAC address
1351 macAddr
= _SCNetworkInterfaceGetHardwareAddress(c_interface
);
1352 if (!__bridge_set_mac(s
, c_bridge_if
, macAddr
)) {
1353 // if bridge MAC could not be set
1360 * add the member interface to the bridge.
1362 c_interface_if
= SCNetworkInterfaceGetBSDName(c_interface
);
1363 if (!__bridge_add_interface(s
, c_bridge_if
, c_interface_if
)) {
1364 // if member could not be added
1373 if (active
!= NULL
) CFRelease(active
);
1374 if (config
!= NULL
) CFRelease(config
);
1375 if (s
!= -1) (void) close(s
);
1380 #endif // IFT_BRIDGE