2 * Copyright (c) 2009-2016 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 bzero(&ifd
, sizeof(ifd
));
84 strlcpy(ifd
.ifd_name
, ifname
, sizeof(ifd
.ifd_name
));
85 ifd
.ifd_cmd
= BRDGGIFS
;
87 buflen
= sizeof(struct ifbifconf
) + len
;
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();
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) {
459 // iterate over each member interface
460 for (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
) && !isA_CFArray(members
)) {
709 _SCErrorSet(kSCStatusInvalidArgument
);
713 if (interfacePrivate
->prefs
!= NULL
) {
714 CFArrayRef available
;
720 CFArrayRef services
= NULL
;
722 current
= SCBridgeInterfaceGetMemberInterfaces(bridge
);
723 n_current
= (current
!= NULL
) ? CFArrayGetCount(current
) : 0;
725 available
= SCBridgeInterfaceCopyAvailableMemberInterfaces(interfacePrivate
->prefs
);
726 n_available
= (available
!= NULL
) ? CFArrayGetCount(available
) : 0;
728 n_members
= (members
!= NULL
) ? CFArrayGetCount(members
) : 0;
729 for (i
= 0; i
< n_members
; i
++) {
730 SCNetworkInterfaceRef member
;
732 member
= CFArrayGetValueAtIndex(members
, i
);
734 if ((current
!= NULL
) &&
735 CFArrayContainsValue(current
, CFRangeMake(0, n_current
), member
)) {
736 // current members are allowed
740 if ((available
!= NULL
) &&
741 CFArrayContainsValue(available
, CFRangeMake(0, n_available
), member
)) {
742 // available members are allowed but cannot be associated
743 // with any other network services.
745 if (services
== NULL
) {
746 services
= __SCNetworkServiceCopyAllEnabled(interfacePrivate
->prefs
);
748 if ((services
!= NULL
) &&
749 __SCNetworkServiceExistsForInterface(services
, member
)) {
750 sc_status
= kSCStatusKeyExists
;
758 // if member not allowed
759 sc_status
= kSCStatusInvalidArgument
;
763 if (available
!= NULL
) CFRelease(available
);
764 if (services
!= NULL
) CFRelease(services
);
767 if (sc_status
!= kSCStatusOK
) {
768 _SCErrorSet(sc_status
);
772 ok
= __SCBridgeInterfaceSetMemberInterfaces(bridge
, members
);
778 SCBridgeInterfaceSetLocalizedDisplayName(SCBridgeInterfaceRef bridge
, CFStringRef newName
)
780 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
783 if (!isA_SCBridgeInterface(bridge
)) {
784 _SCErrorSet(kSCStatusInvalidArgument
);
788 if ((newName
!= NULL
) && !isA_CFString(newName
)) {
789 _SCErrorSet(kSCStatusInvalidArgument
);
793 // set name in the stored preferences
794 if (interfacePrivate
->prefs
!= NULL
) {
795 CFDictionaryRef dict
;
796 CFMutableDictionaryRef newDict
;
799 path
= CFStringCreateWithFormat(NULL
,
802 kSCPrefVirtualNetworkInterfaces
,
803 kSCNetworkInterfaceTypeBridge
,
804 interfacePrivate
->entity_device
);
805 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
806 if (!isA_CFDictionary(dict
)) {
807 // if the prefs are confused
809 _SCErrorSet(kSCStatusFailed
);
813 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
814 if (newName
!= NULL
) {
815 CFDictionarySetValue(newDict
, kSCPropUserDefinedName
, newName
);
817 CFDictionaryRemoveValue(newDict
, kSCPropUserDefinedName
);
819 if (!CFEqual(dict
, newDict
)) {
820 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
826 // set name in the SCBridgeInterfaceRef
828 if (interfacePrivate
->localized_name
!= NULL
) {
829 CFRelease(interfacePrivate
->localized_name
);
830 interfacePrivate
->localized_name
= NULL
;
832 if (newName
!= NULL
) {
833 interfacePrivate
->localized_name
= CFStringCreateCopy(NULL
, newName
);
842 SCBridgeInterfaceSetOptions(SCBridgeInterfaceRef bridge
, CFDictionaryRef newOptions
)
844 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
847 if (!isA_SCBridgeInterface(bridge
)) {
848 _SCErrorSet(kSCStatusInvalidArgument
);
852 if ((newOptions
!= NULL
) && !isA_CFDictionary(newOptions
)) {
853 _SCErrorSet(kSCStatusInvalidArgument
);
857 // set options in the stored preferences
858 if (interfacePrivate
->prefs
!= NULL
) {
859 CFDictionaryRef dict
;
860 CFMutableDictionaryRef newDict
;
863 path
= CFStringCreateWithFormat(NULL
,
866 kSCPrefVirtualNetworkInterfaces
,
867 kSCNetworkInterfaceTypeBridge
,
868 interfacePrivate
->entity_device
);
869 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
870 if (!isA_CFDictionary(dict
)) {
871 // if the prefs are confused
873 _SCErrorSet(kSCStatusFailed
);
877 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
878 if (newOptions
!= NULL
) {
879 CFDictionarySetValue(newDict
, kSCPropVirtualNetworkInterfacesBridgeOptions
, newOptions
);
881 CFDictionaryRemoveValue(newDict
, kSCPropVirtualNetworkInterfacesBridgeOptions
);
883 if (!CFEqual(dict
, newDict
)) {
884 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
890 // set options in the SCBridgeInterfaceRef
892 if (interfacePrivate
->bridge
.options
!= NULL
) {
893 CFRelease(interfacePrivate
->bridge
.options
);
894 interfacePrivate
->bridge
.options
= NULL
;
896 if (newOptions
!= NULL
) {
897 CFStringRef name_auto
= NULL
;
899 interfacePrivate
->bridge
.options
= CFDictionaryCreateCopy(NULL
, newOptions
);
901 // set [auto] display name from options
902 if ((interfacePrivate
->localized_name
== NULL
) &&
903 CFDictionaryGetValueIfPresent(newOptions
,
905 (const void **)&name_auto
) &&
906 isA_CFString(name_auto
)) {
908 interfacePrivate
->localized_key
= name_auto
;
909 if (interfacePrivate
->localized_arg1
!= NULL
) {
910 CFRelease(interfacePrivate
->localized_arg1
);
911 interfacePrivate
->localized_arg1
= NULL
;
922 #pragma mark SCBridgeInterface management
927 __bridge_add_interface(int s
, CFStringRef bridge_if
, CFStringRef interface_if
)
933 bzero(&ifd
, sizeof(ifd
));
934 (void) _SC_cfstring_to_cstring(bridge_if
,
936 sizeof(ifd
.ifd_name
),
937 kCFStringEncodingASCII
);
938 ifd
.ifd_cmd
= BRDGADD
;
939 ifd
.ifd_len
= sizeof(breq
);
940 ifd
.ifd_data
= (caddr_t
)&breq
;
943 bzero(&breq
, sizeof(breq
));
944 (void) _SC_cfstring_to_cstring(interface_if
,
946 sizeof(breq
.ifbr_ifsname
),
947 kCFStringEncodingASCII
);
949 // add new bridge member
950 if (ioctl(s
, SIOCSDRVSPEC
, (caddr_t
)&ifd
) == -1) {
952 SC_log(LOG_ERR
, "could not add interface \"%@\" to bridge \"%@\": %s",
959 SC_log(LOG_INFO
, "%@: added bridge member: %@", bridge_if
, interface_if
);
965 __bridge_remove_interface(int s
, CFStringRef bridge_if
, CFStringRef interface_if
)
971 bzero(&ifd
, sizeof(ifd
));
972 (void) _SC_cfstring_to_cstring(bridge_if
,
974 sizeof(ifd
.ifd_name
),
975 kCFStringEncodingASCII
);
976 ifd
.ifd_cmd
= BRDGDEL
;
977 ifd
.ifd_len
= sizeof(breq
);
978 ifd
.ifd_data
= (caddr_t
)&breq
;
980 // bridge member to remove
981 bzero(&breq
, sizeof(breq
));
982 (void) _SC_cfstring_to_cstring(interface_if
,
984 sizeof(breq
.ifbr_ifsname
),
985 kCFStringEncodingASCII
);
987 // remove bridge member
988 if (ioctl(s
, SIOCSDRVSPEC
, (caddr_t
)&ifd
) == -1) {
990 SC_log(LOG_ERR
, "could not remove interface \"%@\" from bridge \"%@\": %s",
997 SC_log(LOG_INFO
, "%@: removed bridge member: %@", bridge_if
, interface_if
);
1003 __bridge_set_mac(int s
, CFStringRef bridge_if
, CFDataRef macAddr
)
1007 bzero(&ifr
, sizeof(ifr
));
1008 (void) _SC_cfstring_to_cstring(bridge_if
,
1010 sizeof(ifr
.ifr_name
),
1011 kCFStringEncodingASCII
);
1012 ifr
.ifr_addr
.sa_len
= CFDataGetLength(macAddr
);
1013 if (ifr
.ifr_addr
.sa_len
> sizeof(ifr
.ifr_addr
.sa_data
)) {
1014 _SCErrorSet(kSCStatusInvalidArgument
);
1015 SC_log(LOG_ERR
, "%@: maformed MAC address (%d > %lu)",
1017 ifr
.ifr_addr
.sa_len
,
1018 sizeof(ifr
.ifr_addr
.sa_data
));
1021 CFDataGetBytes(macAddr
, CFRangeMake(0, ifr
.ifr_addr
.sa_len
), (UInt8
*)ifr
.ifr_addr
.sa_data
);
1023 if (ioctl(s
, SIOCSIFLLADDR
, &ifr
) == -1) {
1025 SC_log(LOG_ERR
, "%@: could not set MAC address: %s",
1031 SC_log(LOG_INFO
, "%@: updated MAC address: %{ private }@", bridge_if
, macAddr
);
1034 #endif // IFT_BRIDGE
1038 _SCBridgeInterfaceUpdateConfiguration(SCPreferencesRef prefs
)
1041 CFArrayRef active
= NULL
;
1042 CFArrayRef config
= NULL
;
1049 if (prefs
== NULL
) {
1050 _SCErrorSet(kSCStatusInvalidArgument
);
1054 /* configured Bridges */
1055 config
= SCBridgeInterfaceCopyAll(prefs
);
1056 nConfig
= (config
!= NULL
) ? CFArrayGetCount(config
) : 0;
1058 /* active Bridges */
1059 active
= _SCBridgeInterfaceCopyActive();
1060 nActive
= (active
!= NULL
) ? CFArrayGetCount(active
) : 0;
1063 * remove any no-longer-configured bridge interfaces and
1064 * any members associated with a bridge that are no longer
1065 * associated with a bridge.
1067 for (i
= 0; i
< nActive
; i
++) {
1068 SCBridgeInterfaceRef a_bridge
;
1069 CFStringRef a_bridge_if
;
1071 Boolean found
= FALSE
;
1073 a_bridge
= CFArrayGetValueAtIndex(active
, i
);
1074 a_bridge_if
= SCNetworkInterfaceGetBSDName(a_bridge
);
1076 for (j
= 0; j
< nConfig
; j
++) {
1077 SCBridgeInterfaceRef c_bridge
;
1078 CFStringRef c_bridge_if
;
1080 c_bridge
= CFArrayGetValueAtIndex(config
, j
);
1081 c_bridge_if
= SCNetworkInterfaceGetBSDName(c_bridge
);
1083 if (CFEqual(a_bridge_if
, c_bridge_if
)) {
1085 CFArrayRef a_bridge_interfaces
;
1087 CFArrayRef c_bridge_interfaces
;
1090 c_bridge_interfaces
= SCBridgeInterfaceGetMemberInterfaces(c_bridge
);
1091 c_count
= (c_bridge_interfaces
!= NULL
) ? CFArrayGetCount(c_bridge_interfaces
) : 0;
1093 a_bridge_interfaces
= SCBridgeInterfaceGetMemberInterfaces(a_bridge
);
1094 a_count
= (a_bridge_interfaces
!= NULL
) ? CFArrayGetCount(a_bridge_interfaces
) : 0;
1096 for (a
= 0; a
< a_count
; a
++) {
1097 SCNetworkInterfaceRef a_interface
;
1098 CFStringRef a_interface_if
;
1100 a_interface
= CFArrayGetValueAtIndex(a_bridge_interfaces
, a
);
1101 if ((c_count
== 0) ||
1102 !CFArrayContainsValue(c_bridge_interfaces
,
1103 CFRangeMake(0, c_count
),
1106 * if this member is no longer part
1110 s
= inet_dgram_socket();
1118 a_interface_if
= SCNetworkInterfaceGetBSDName(a_interface
);
1119 if (!__bridge_remove_interface(s
, a_bridge_if
, a_interface_if
)) {
1132 * if this interface is no longer configured
1135 s
= inet_dgram_socket();
1143 if (!__destroyInterface(s
, a_bridge_if
)) {
1151 * add any newly-configured bridge interfaces and add any
1152 * members that should now be associated with the bridge.
1154 for (i
= 0; i
< nConfig
; i
++) {
1155 SCBridgeInterfaceRef c_bridge
;
1156 CFArrayRef c_bridge_interfaces
;
1157 CFStringRef c_bridge_if
;
1159 Boolean found
= FALSE
;
1161 Boolean setMAC
= FALSE
;
1163 c_bridge
= CFArrayGetValueAtIndex(config
, i
);
1164 c_bridge_if
= SCNetworkInterfaceGetBSDName(c_bridge
);
1165 c_bridge_interfaces
= SCBridgeInterfaceGetMemberInterfaces(c_bridge
);
1166 c_count
= (c_bridge_interfaces
!= NULL
) ? CFArrayGetCount(c_bridge_interfaces
) : 0;
1168 for (j
= 0; j
< nActive
; j
++) {
1169 SCBridgeInterfaceRef a_bridge
;
1170 CFArrayRef a_bridge_interfaces
;
1171 CFStringRef a_bridge_if
;
1174 a_bridge
= CFArrayGetValueAtIndex(active
, j
);
1175 a_bridge_if
= SCNetworkInterfaceGetBSDName(a_bridge
);
1176 a_bridge_interfaces
= SCBridgeInterfaceGetMemberInterfaces(a_bridge
);
1177 a_count
= (a_bridge_interfaces
!= NULL
) ? CFArrayGetCount(a_bridge_interfaces
) : 0;
1179 if (CFEqual(c_bridge_if
, a_bridge_if
)) {
1184 if (_SC_CFEqual(c_bridge_interfaces
, a_bridge_interfaces
)) {
1185 break; // if no change
1189 s
= inet_dgram_socket();
1198 * ensure that the first member of the bridge matches, if
1199 * not then we remove all current members and add them
1200 * back in the preferred order.
1202 if ((c_count
> 0) &&
1204 !CFEqual(CFArrayGetValueAtIndex(c_bridge_interfaces
, 0),
1205 CFArrayGetValueAtIndex(a_bridge_interfaces
, 0))) {
1208 for (a
= 0; a
< a_count
; a
++) {
1209 SCNetworkInterfaceRef a_interface
;
1210 CFStringRef a_interface_if
;
1212 a_interface
= CFArrayGetValueAtIndex(a_bridge_interfaces
, a
);
1213 if (!CFArrayContainsValue(c_bridge_interfaces
,
1214 CFRangeMake(0, c_count
),
1216 continue; // if already removed
1219 a_interface_if
= SCNetworkInterfaceGetBSDName(a_interface
);
1220 if (!__bridge_remove_interface(s
, a_bridge_if
, a_interface_if
)) {
1225 a_count
= 0; // all active members have been removed
1233 * add any members which are not currently associated
1234 * with the bridge interface.
1236 for (c
= 0; c
< c_count
; c
++) {
1237 SCNetworkInterfaceRef c_interface
;
1238 SCNetworkInterfacePrivateRef c_interfacePrivate
;
1239 CFStringRef c_interface_if
;
1241 c_interface
= CFArrayGetValueAtIndex(c_bridge_interfaces
, c
);
1242 if ((a_count
== 0) ||
1243 !CFArrayContainsValue(a_bridge_interfaces
,
1244 CFRangeMake(0, a_count
),
1247 * check if this member interface can be added to a bridge.
1249 c_interfacePrivate
= (SCNetworkInterfacePrivateRef
)c_interface
;
1250 if (!c_interfacePrivate
->supportsBridge
) {
1251 // if member not supported
1256 * if this is the first member interface, set the MAC address
1262 macAddr
= _SCNetworkInterfaceGetHardwareAddress(c_interface
);
1263 if (!__bridge_set_mac(s
, c_bridge_if
, macAddr
)) {
1264 // if bridge MAC could not be set
1271 * add the member interface to the bridge.
1273 c_interface_if
= SCNetworkInterfaceGetBSDName(c_interface
);
1274 if (!__bridge_add_interface(s
, c_bridge_if
, c_interface_if
)) {
1275 // if member could not be added
1289 s
= inet_dgram_socket();
1298 * establish the new bridge interface.
1300 if (!__createInterface(s
, c_bridge_if
)) {
1309 * add the member interfaces
1311 for (c
= 0; c
< c_count
; c
++) {
1312 SCNetworkInterfaceRef c_interface
;
1313 SCNetworkInterfacePrivateRef c_interfacePrivate
;
1314 CFStringRef c_interface_if
;
1316 c_interface
= CFArrayGetValueAtIndex(c_bridge_interfaces
, c
);
1317 c_interfacePrivate
= (SCNetworkInterfacePrivateRef
)c_interface
;
1318 if (!c_interfacePrivate
->supportsBridge
) {
1319 // if member not supported
1324 * if this is the first member interface, set the MAC address
1330 macAddr
= _SCNetworkInterfaceGetHardwareAddress(c_interface
);
1331 if (!__bridge_set_mac(s
, c_bridge_if
, macAddr
)) {
1332 // if bridge MAC could not be set
1339 * add the member interface to the bridge.
1341 c_interface_if
= SCNetworkInterfaceGetBSDName(c_interface
);
1342 if (!__bridge_add_interface(s
, c_bridge_if
, c_interface_if
)) {
1343 // if member could not be added
1352 if (active
!= NULL
) CFRelease(active
);
1353 if (config
!= NULL
) CFRelease(config
);
1354 if (s
!= -1) (void) close(s
);
1359 #endif // IFT_BRIDGE