2 * Copyright (c) 2009-2015 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 "SCPreferencesInternal.h"
38 #include <SystemConfiguration/SCValidation.h>
39 #include <SystemConfiguration/SCPrivate.h>
44 #include <sys/types.h>
45 #include <sys/ioctl.h>
46 #include <sys/socket.h>
47 #include <sys/sysctl.h>
48 #include <net/ethernet.h>
49 #define KERNEL_PRIVATE
51 #include <net/if_var.h>
53 #include <net/if_types.h>
54 #include <net/if_media.h>
55 #include <net/route.h>
58 #include <net/if_bridgevar.h>
61 /* ---------- Bridge support ---------- */
68 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
70 SC_log(LOG_ERR
, "socket() failed: %s", strerror(errno
));
77 static struct ifbifconf
*
78 ifbifconf_copy(int s
, const char * ifname
)
82 struct ifbifconf
* ibc_p
= NULL
;
84 uint32_t len
= sizeof(struct ifbreq
) * 16;
86 bzero(&ifd
, sizeof(ifd
));
87 strncpy(ifd
.ifd_name
, ifname
, sizeof(ifd
.ifd_name
));
88 ifd
.ifd_cmd
= BRDGGIFS
;
90 buflen
= sizeof(struct ifbifconf
) + len
;
94 ibc_p
= (struct ifbifconf
*)buf
;
95 ibc_p
->ifbic_len
= len
;
96 ibc_p
->ifbic_buf
= buf
+ sizeof(*ibc_p
);
98 ifd
.ifd_len
= sizeof(*ibc_p
);
100 if (ioctl(s
, SIOCGDRVSPEC
, (caddr_t
)&ifd
) == -1) {
104 if ((ibc_p
->ifbic_len
+ sizeof(struct ifbreq
)) < len
) {
105 // if we have room for all of the member interfaces
110 buflen
= sizeof(struct ifbifconf
) + len
;
111 buf
= reallocf(buf
, buflen
);
130 add_interface(CFMutableArrayRef
*interfaces
, CFStringRef if_name
, SCPreferencesRef ni_prefs
)
132 SCNetworkInterfaceRef interface
= NULL
;
134 if (*interfaces
== NULL
) {
135 *interfaces
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
137 if (ni_prefs
!= NULL
) {
138 interface
= __SCNetworkInterfaceCreateWithNIPreferencesUsingBSDName(NULL
, ni_prefs
, if_name
);
140 if (interface
== NULL
) {
141 interface
= _SCNetworkInterfaceCreateWithBSDName(NULL
, if_name
,
142 kIncludeNoVirtualInterfaces
);
145 if (interface
!= NULL
) {
146 CFArrayAppendValue(*interfaces
, interface
);
147 CFRelease(interface
);
152 CFMutableArrayRef bridges
;
153 SCPreferencesRef ni_prefs
;
154 SCPreferencesRef prefs
;
155 } addContext
, *addContextRef
;
159 add_configured_interface(const void *key
, const void *value
, void *context
)
161 SCBridgeInterfaceRef bridge
;
162 CFStringRef bridge_if
= (CFStringRef
)key
;
163 CFDictionaryRef bridge_info
= (CFDictionaryRef
)value
;
164 CFDictionaryRef bridge_options
;
166 CFArrayRef interfaces
;
167 SCNetworkInterfacePrivateRef interfacePrivate
;
168 CFMutableArrayRef members
= NULL
;
169 addContextRef myContext
= (addContextRef
)context
;
171 CFStringRef name_auto
= NULL
;
174 // create the bridge interface
175 bridge
= (SCBridgeInterfaceRef
)_SCBridgeInterfaceCreatePrivate(NULL
, bridge_if
);
176 assert(bridge
!= NULL
);
178 // estabish link to the stored configuration
179 interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
180 interfacePrivate
->prefs
= CFRetain(myContext
->prefs
);
182 // add member interfaces
183 interfaces
= CFDictionaryGetValue(bridge_info
, kSCPropVirtualNetworkInterfacesBridgeInterfaces
);
184 n
= isA_CFArray(interfaces
) ? CFArrayGetCount(interfaces
) : 0;
185 for (i
= 0; i
< n
; i
++) {
188 member
= CFArrayGetValueAtIndex(interfaces
, i
);
189 if (isA_CFString(member
)) {
190 add_interface(&members
, member
, myContext
->ni_prefs
);
193 if (members
!= NULL
) {
194 __SCBridgeInterfaceSetMemberInterfaces(bridge
, members
);
199 bridge_options
= CFDictionaryGetValue(bridge_info
, kSCPropVirtualNetworkInterfacesBridgeOptions
);
200 if (isA_CFDictionary(bridge_options
)) {
201 SCBridgeInterfaceSetOptions(bridge
, bridge_options
);
202 name_auto
= CFDictionaryGetValue(bridge_options
, CFSTR("__AUTO__"));
206 name
= CFDictionaryGetValue(bridge_info
, kSCPropUserDefinedName
);
207 if (isA_CFString(name
)) {
208 SCBridgeInterfaceSetLocalizedDisplayName(bridge
, name
);
209 } else if (isA_CFString(name_auto
)) {
210 interfacePrivate
->localized_key
= name_auto
;
211 if (interfacePrivate
->localized_arg1
!= NULL
) {
212 CFRelease(interfacePrivate
->localized_arg1
);
213 interfacePrivate
->localized_arg1
= NULL
;
217 CFArrayAppendValue(myContext
->bridges
, bridge
);
225 #pragma mark SCBridgeInterface APIs
228 static __inline__
void
229 my_CFDictionaryApplyFunction(CFDictionaryRef theDict
,
230 CFDictionaryApplierFunction applier
,
233 CFAllocatorRef myAllocator
;
234 CFDictionaryRef myDict
;
236 myAllocator
= CFGetAllocator(theDict
);
237 myDict
= CFDictionaryCreateCopy(myAllocator
, theDict
);
238 CFDictionaryApplyFunction(myDict
, applier
, context
);
245 SCBridgeInterfaceCopyAll(SCPreferencesRef prefs
)
248 CFDictionaryRef dict
;
249 SCPreferencesRef ni_prefs
;
252 if ((prefs
== NULL
) ||
253 (__SCPreferencesUsingDefaultPrefs(prefs
) == TRUE
)) {
257 ni_prefs
= __SCPreferencesCreateNIPrefsFromPrefs(prefs
);
259 context
.bridges
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
260 context
.prefs
= prefs
;
261 context
.ni_prefs
= ni_prefs
;
263 path
= CFStringCreateWithFormat(NULL
,
266 kSCPrefVirtualNetworkInterfaces
,
267 kSCNetworkInterfaceTypeBridge
);
268 dict
= SCPreferencesPathGetValue(prefs
, path
);
269 if (isA_CFDictionary(dict
)) {
270 my_CFDictionaryApplyFunction(dict
, add_configured_interface
, &context
);
273 if (ni_prefs
!= NULL
) {
276 return context
.bridges
;
280 __private_extern__
void
281 __SCBridgeInterfaceListCollectMembers(CFArrayRef interfaces
, CFMutableSetRef set
)
286 n
= CFArrayGetCount(interfaces
);
287 for (i
= 0; i
< n
; i
++) {
288 SCBridgeInterfaceRef bridgeInterface
;
291 bridgeInterface
= CFArrayGetValueAtIndex(interfaces
, i
);
292 members
= SCBridgeInterfaceGetMemberInterfaces(bridgeInterface
);
293 if (members
!= NULL
) {
297 // exclude the member interfaces of this bridge
298 n_members
= CFArrayGetCount(members
);
299 for (j
= 0; j
< n_members
; j
++) {
300 SCNetworkInterfaceRef member
;
302 member
= CFArrayGetValueAtIndex(members
, j
);
303 CFSetAddValue(set
, member
);
312 CFArrayRef
/* of SCNetworkInterfaceRef's */
313 SCBridgeInterfaceCopyAvailableMemberInterfaces(SCPreferencesRef prefs
)
315 CFMutableArrayRef available
;
316 CFMutableSetRef excluded
;
317 CFArrayRef interfaces
;
319 available
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
320 excluded
= CFSetCreateMutable (NULL
, 0, &kCFTypeSetCallBacks
);
322 #if !TARGET_OS_IPHONE
323 // exclude Bond [member] interfaces
324 interfaces
= SCBondInterfaceCopyAll(prefs
);
325 if (interfaces
!= NULL
) {
326 __SCBondInterfaceListCollectMembers(interfaces
, excluded
);
327 CFRelease(interfaces
);
329 #endif // !TARGET_OS_IPHONE
331 // exclude Bridge [member] interfaces
332 interfaces
= SCBridgeInterfaceCopyAll(prefs
);
333 if (interfaces
!= NULL
) {
334 __SCBridgeInterfaceListCollectMembers(interfaces
, excluded
);
335 CFRelease(interfaces
);
338 // exclude VLAN [physical] interfaces
339 interfaces
= SCVLANInterfaceCopyAll(prefs
);
340 if (interfaces
!= NULL
) {
344 n
= CFArrayGetCount(interfaces
);
345 for (i
= 0; i
< n
; i
++) {
346 SCVLANInterfaceRef vlanInterface
;
347 SCNetworkInterfaceRef physical
;
349 // exclude the physical interface of this VLAN
350 vlanInterface
= CFArrayGetValueAtIndex(interfaces
, i
);
351 physical
= SCVLANInterfaceGetPhysicalInterface(vlanInterface
);
352 CFSetAddValue(excluded
, physical
);
354 CFRelease(interfaces
);
357 // identify available interfaces
358 interfaces
= __SCNetworkInterfaceCopyAll_IONetworkInterface();
359 if (interfaces
!= NULL
) {
363 n
= CFArrayGetCount(interfaces
);
364 for (i
= 0; i
< n
; i
++) {
365 SCNetworkInterfaceRef interface
;
366 SCNetworkInterfacePrivateRef interfacePrivate
;
368 interface
= CFArrayGetValueAtIndex(interfaces
, i
);
369 interfacePrivate
= (SCNetworkInterfacePrivateRef
)interface
;
371 if (!interfacePrivate
->supportsBridge
) {
372 // if this interface is not available
376 if (CFSetContainsValue(excluded
, interface
)) {
381 CFArrayAppendValue(available
, interface
);
383 CFRelease(interfaces
);
393 _SCBridgeInterfaceCopyActive(void)
395 struct ifaddrs
*ifap
;
398 CFMutableArrayRef bridges
= NULL
;
400 if (getifaddrs(&ifap
) == -1) {
402 SC_log(LOG_NOTICE
, "getifaddrs() failed: %s", strerror(errno
));
406 s
= inet_dgram_socket();
412 bridges
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
414 for (ifp
= ifap
; ifp
!= NULL
; ifp
= ifp
->ifa_next
) {
416 SCBridgeInterfaceRef bridge
;
417 CFStringRef bridge_if
;
418 struct ifbifconf
*ibc_p
;
419 struct if_data
*if_data
;
420 CFMutableArrayRef members
= NULL
;
423 if_data
= (struct if_data
*)ifp
->ifa_data
;
425 || ifp
->ifa_addr
->sa_family
!= AF_LINK
426 || if_data
->ifi_type
!= IFT_BRIDGE
) {
430 // make sure that we leave non-SC configured bridge
431 // interfaces (those with unit #'s >= 100) alone.
432 n
= strlen(ifp
->ifa_name
);
434 isdigit(ifp
->ifa_name
[n
- 1]) &&
435 isdigit(ifp
->ifa_name
[n
- 2]) &&
436 isdigit(ifp
->ifa_name
[n
- 3])) {
437 // if not SC managed bridge interface
441 ibc_p
= ifbifconf_copy(s
, ifp
->ifa_name
);
443 if (errno
== EBUSY
) {
447 SC_log(LOG_NOTICE
, "ifbifconf_copy(%s) failed: %s",
455 // create the bridge interface
456 bridge_if
= CFStringCreateWithCString(NULL
, ifp
->ifa_name
, kCFStringEncodingASCII
);
457 bridge
= (SCBridgeInterfaceRef
)_SCBridgeInterfaceCreatePrivate(NULL
, bridge_if
);
458 CFRelease(bridge_if
);
460 // add member interfaces
461 if (ibc_p
->ifbic_len
> 0) {
464 // iterate over each member interface
465 for (i
= 0; i
< ibc_p
->ifbic_len
/ sizeof(struct ifbreq
); i
++) {
466 struct ifbreq
*ibr_p
;
469 ibr_p
= ibc_p
->ifbic_req
+ i
;
470 member
= CFStringCreateWithCString(NULL
, ibr_p
->ifbr_ifsname
, kCFStringEncodingASCII
);
471 add_interface(&members
, member
, NULL
);
477 if (members
!= NULL
) {
478 __SCBridgeInterfaceSetMemberInterfaces(bridge
, members
);
483 CFArrayAppendValue(bridges
, bridge
);
499 SCBridgeInterfaceCreate(SCPreferencesRef prefs
)
501 CFAllocatorRef allocator
;
502 SCBridgeInterfaceRef bridge
= NULL
;
506 _SCErrorSet(kSCStatusInvalidArgument
);
510 allocator
= CFGetAllocator(prefs
);
512 // create a new bridge using an unused interface name
513 for (i
= 0; bridge
== NULL
; i
++) {
514 CFDictionaryRef dict
;
515 CFStringRef bridge_if
;
516 SCNetworkInterfacePrivateRef interfacePrivate
;
517 CFMutableDictionaryRef newDict
;
518 CFArrayRef newInterfaces
;
522 bridge_if
= CFStringCreateWithFormat(allocator
, NULL
, CFSTR("bridge%ld"), i
);
523 path
= CFStringCreateWithFormat(allocator
,
526 kSCPrefVirtualNetworkInterfaces
,
527 kSCNetworkInterfaceTypeBridge
,
529 dict
= SCPreferencesPathGetValue(prefs
, path
);
531 // if bridge interface name not available
533 CFRelease(bridge_if
);
537 // add the bridge to the stored preferences
538 newDict
= CFDictionaryCreateMutable(allocator
,
540 &kCFTypeDictionaryKeyCallBacks
,
541 &kCFTypeDictionaryValueCallBacks
);
542 newInterfaces
= CFArrayCreate(allocator
, NULL
, 0, &kCFTypeArrayCallBacks
);
543 CFDictionaryAddValue(newDict
, kSCPropVirtualNetworkInterfacesBridgeInterfaces
, newInterfaces
);
544 CFRelease(newInterfaces
);
545 ok
= SCPreferencesPathSetValue(prefs
, path
, newDict
);
549 // if the bridge could not be saved
550 CFRelease(bridge_if
);
554 // create the SCBridgeInterfaceRef
555 bridge
= (SCBridgeInterfaceRef
)_SCBridgeInterfaceCreatePrivate(allocator
, bridge_if
);
556 CFRelease(bridge_if
);
558 // estabish link to the stored configuration
559 interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
560 interfacePrivate
->prefs
= CFRetain(prefs
);
568 SCBridgeInterfaceRemove(SCBridgeInterfaceRef bridge
)
570 CFStringRef bridge_if
;
571 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
575 if (!isA_SCBridgeInterface(bridge
)) {
576 _SCErrorSet(kSCStatusInvalidArgument
);
580 if (interfacePrivate
->prefs
== NULL
) {
581 _SCErrorSet(kSCStatusInvalidArgument
);
585 bridge_if
= SCNetworkInterfaceGetBSDName(bridge
);
586 path
= CFStringCreateWithFormat(NULL
,
589 kSCPrefVirtualNetworkInterfaces
,
590 kSCNetworkInterfaceTypeBridge
,
592 ok
= SCPreferencesPathRemoveValue(interfacePrivate
->prefs
, path
);
600 SCBridgeInterfaceGetMemberInterfaces(SCBridgeInterfaceRef bridge
)
602 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
604 if (!isA_SCBridgeInterface(bridge
)) {
605 _SCErrorSet(kSCStatusInvalidArgument
);
609 return interfacePrivate
->bridge
.interfaces
;
614 SCBridgeInterfaceGetOptions(SCBridgeInterfaceRef bridge
)
616 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
618 if (!isA_SCBridgeInterface(bridge
)) {
619 _SCErrorSet(kSCStatusInvalidArgument
);
623 return interfacePrivate
->bridge
.options
;
629 __SCBridgeInterfaceSetMemberInterfaces(SCBridgeInterfaceRef bridge
, CFArrayRef members
)
632 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
634 CFMutableArrayRef newMembers
;
637 n
= (members
!= NULL
) ? CFArrayGetCount(members
) : 0;
639 // set member interfaces in the stored preferences
640 if (interfacePrivate
->prefs
!= NULL
) {
641 CFDictionaryRef dict
;
642 CFMutableDictionaryRef newDict
;
645 path
= CFStringCreateWithFormat(NULL
,
648 kSCPrefVirtualNetworkInterfaces
,
649 kSCNetworkInterfaceTypeBridge
,
650 interfacePrivate
->entity_device
);
651 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
652 if (!isA_CFDictionary(dict
)) {
653 // if the prefs are confused
655 _SCErrorSet(kSCStatusFailed
);
659 newMembers
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
660 for (i
= 0; i
< n
; i
++) {
661 SCNetworkInterfaceRef interface
;
662 CFStringRef memberName
;
664 interface
= CFArrayGetValueAtIndex(members
, i
);
665 memberName
= SCNetworkInterfaceGetBSDName(interface
);
666 CFArrayAppendValue(newMembers
, memberName
);
669 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
670 CFDictionarySetValue(newDict
, kSCPropVirtualNetworkInterfacesBridgeInterfaces
, newMembers
);
671 CFRelease(newMembers
);
672 if (!CFEqual(dict
, newDict
)) {
673 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
680 newMembers
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
681 for (i
= 0; i
< n
; i
++) {
682 SCNetworkInterfaceRef member
;
683 SCNetworkInterfacePrivateRef newMember
;
685 member
= CFArrayGetValueAtIndex(members
, i
);
686 newMember
= __SCNetworkInterfaceCreateCopy(NULL
,
688 interfacePrivate
->prefs
,
689 interfacePrivate
->serviceID
);
690 CFArrayAppendValue(newMembers
, newMember
);
691 CFRelease(newMember
);
693 CFRelease(interfacePrivate
->bridge
.interfaces
);
694 interfacePrivate
->bridge
.interfaces
= newMembers
;
702 SCBridgeInterfaceSetMemberInterfaces(SCBridgeInterfaceRef bridge
, CFArrayRef members
)
704 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
706 int sc_status
= kSCStatusOK
;
708 if (!isA_SCBridgeInterface(bridge
)) {
709 _SCErrorSet(kSCStatusInvalidArgument
);
713 if ((members
!= NULL
) && !isA_CFArray(members
)) {
714 _SCErrorSet(kSCStatusInvalidArgument
);
718 if (interfacePrivate
->prefs
!= NULL
) {
719 CFArrayRef available
;
725 CFArrayRef services
= NULL
;
727 current
= SCBridgeInterfaceGetMemberInterfaces(bridge
);
728 n_current
= (current
!= NULL
) ? CFArrayGetCount(current
) : 0;
730 available
= SCBridgeInterfaceCopyAvailableMemberInterfaces(interfacePrivate
->prefs
);
731 n_available
= (available
!= NULL
) ? CFArrayGetCount(available
) : 0;
733 n_members
= (members
!= NULL
) ? CFArrayGetCount(members
) : 0;
734 for (i
= 0; i
< n_members
; i
++) {
735 SCNetworkInterfaceRef member
;
737 member
= CFArrayGetValueAtIndex(members
, i
);
739 if ((current
!= NULL
) &&
740 CFArrayContainsValue(current
, CFRangeMake(0, n_current
), member
)) {
741 // current members are allowed
745 if ((available
!= NULL
) &&
746 CFArrayContainsValue(available
, CFRangeMake(0, n_available
), member
)) {
747 // available members are allowed but cannot be associated
748 // with any other network services.
750 if (services
== NULL
) {
751 services
= __SCNetworkServiceCopyAllEnabled(interfacePrivate
->prefs
);
753 if ((services
!= NULL
) &&
754 __SCNetworkServiceExistsForInterface(services
, member
)) {
755 sc_status
= kSCStatusKeyExists
;
763 // if member not allowed
764 sc_status
= kSCStatusInvalidArgument
;
768 if (available
!= NULL
) CFRelease(available
);
769 if (services
!= NULL
) CFRelease(services
);
772 if (sc_status
!= kSCStatusOK
) {
773 _SCErrorSet(sc_status
);
777 ok
= __SCBridgeInterfaceSetMemberInterfaces(bridge
, members
);
783 SCBridgeInterfaceSetLocalizedDisplayName(SCBridgeInterfaceRef bridge
, CFStringRef newName
)
785 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
788 if (!isA_SCBridgeInterface(bridge
)) {
789 _SCErrorSet(kSCStatusInvalidArgument
);
793 if ((newName
!= NULL
) && !isA_CFString(newName
)) {
794 _SCErrorSet(kSCStatusInvalidArgument
);
798 // set name in the stored preferences
799 if (interfacePrivate
->prefs
!= NULL
) {
800 CFDictionaryRef dict
;
801 CFMutableDictionaryRef newDict
;
804 path
= CFStringCreateWithFormat(NULL
,
807 kSCPrefVirtualNetworkInterfaces
,
808 kSCNetworkInterfaceTypeBridge
,
809 interfacePrivate
->entity_device
);
810 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
811 if (!isA_CFDictionary(dict
)) {
812 // if the prefs are confused
814 _SCErrorSet(kSCStatusFailed
);
818 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
819 if (newName
!= NULL
) {
820 CFDictionarySetValue(newDict
, kSCPropUserDefinedName
, newName
);
822 CFDictionaryRemoveValue(newDict
, kSCPropUserDefinedName
);
824 if (!CFEqual(dict
, newDict
)) {
825 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
831 // set name in the SCBridgeInterfaceRef
833 if (interfacePrivate
->localized_name
!= NULL
) {
834 CFRelease(interfacePrivate
->localized_name
);
835 interfacePrivate
->localized_name
= NULL
;
837 if (newName
!= NULL
) {
838 interfacePrivate
->localized_name
= CFStringCreateCopy(NULL
, newName
);
847 SCBridgeInterfaceSetOptions(SCBridgeInterfaceRef bridge
, CFDictionaryRef newOptions
)
849 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
852 if (!isA_SCBridgeInterface(bridge
)) {
853 _SCErrorSet(kSCStatusInvalidArgument
);
857 if ((newOptions
!= NULL
) && !isA_CFDictionary(newOptions
)) {
858 _SCErrorSet(kSCStatusInvalidArgument
);
862 // set options in the stored preferences
863 if (interfacePrivate
->prefs
!= NULL
) {
864 CFDictionaryRef dict
;
865 CFMutableDictionaryRef newDict
;
868 path
= CFStringCreateWithFormat(NULL
,
871 kSCPrefVirtualNetworkInterfaces
,
872 kSCNetworkInterfaceTypeBridge
,
873 interfacePrivate
->entity_device
);
874 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
875 if (!isA_CFDictionary(dict
)) {
876 // if the prefs are confused
878 _SCErrorSet(kSCStatusFailed
);
882 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
883 if (newOptions
!= NULL
) {
884 CFDictionarySetValue(newDict
, kSCPropVirtualNetworkInterfacesBridgeOptions
, newOptions
);
886 CFDictionaryRemoveValue(newDict
, kSCPropVirtualNetworkInterfacesBridgeOptions
);
888 if (!CFEqual(dict
, newDict
)) {
889 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
895 // set options in the SCBridgeInterfaceRef
897 if (interfacePrivate
->bridge
.options
!= NULL
) {
898 CFRelease(interfacePrivate
->bridge
.options
);
899 interfacePrivate
->bridge
.options
= NULL
;
901 if (newOptions
!= NULL
) {
902 CFStringRef name_auto
= NULL
;
904 interfacePrivate
->bridge
.options
= CFDictionaryCreateCopy(NULL
, newOptions
);
906 // set [auto] display name from options
907 if ((interfacePrivate
->localized_name
== NULL
) &&
908 CFDictionaryGetValueIfPresent(newOptions
,
910 (const void **)&name_auto
) &&
911 isA_CFString(name_auto
)) {
913 interfacePrivate
->localized_key
= name_auto
;
914 if (interfacePrivate
->localized_arg1
!= NULL
) {
915 CFRelease(interfacePrivate
->localized_arg1
);
916 interfacePrivate
->localized_arg1
= NULL
;
927 #pragma mark SCBridgeInterface management
932 __bridge_add_interface(int s
, CFStringRef bridge_if
, CFStringRef interface_if
)
938 bzero(&ifd
, sizeof(ifd
));
939 (void) _SC_cfstring_to_cstring(bridge_if
,
941 sizeof(ifd
.ifd_name
),
942 kCFStringEncodingASCII
);
943 ifd
.ifd_cmd
= BRDGADD
;
944 ifd
.ifd_len
= sizeof(breq
);
945 ifd
.ifd_data
= (caddr_t
)&breq
;
948 bzero(&breq
, sizeof(breq
));
949 (void) _SC_cfstring_to_cstring(interface_if
,
951 sizeof(breq
.ifbr_ifsname
),
952 kCFStringEncodingASCII
);
954 // add new bridge member
955 if (ioctl(s
, SIOCSDRVSPEC
, (caddr_t
)&ifd
) == -1) {
957 SC_log(LOG_ERR
, "could not add interface \"%@\" to bridge \"%@\": %s",
969 __bridge_remove_interface(int s
, CFStringRef bridge_if
, CFStringRef interface_if
)
975 bzero(&ifd
, sizeof(ifd
));
976 (void) _SC_cfstring_to_cstring(bridge_if
,
978 sizeof(ifd
.ifd_name
),
979 kCFStringEncodingASCII
);
980 ifd
.ifd_cmd
= BRDGDEL
;
981 ifd
.ifd_len
= sizeof(breq
);
982 ifd
.ifd_data
= (caddr_t
)&breq
;
984 // bridge member to remove
985 bzero(&breq
, sizeof(breq
));
986 (void) _SC_cfstring_to_cstring(interface_if
,
988 sizeof(breq
.ifbr_ifsname
),
989 kCFStringEncodingASCII
);
991 // remove bridge member
992 if (ioctl(s
, SIOCSDRVSPEC
, (caddr_t
)&ifd
) == -1) {
994 SC_log(LOG_ERR
, "could not remove interface \"%@\" from bridge \"%@\": %s",
1003 #endif // IFT_BRIDGE
1007 _SCBridgeInterfaceUpdateConfiguration(SCPreferencesRef prefs
)
1010 CFArrayRef active
= NULL
;
1011 CFArrayRef config
= NULL
;
1018 if (prefs
== NULL
) {
1019 _SCErrorSet(kSCStatusInvalidArgument
);
1023 /* configured Bridges */
1024 config
= SCBridgeInterfaceCopyAll(prefs
);
1025 nConfig
= (config
!= NULL
) ? CFArrayGetCount(config
) : 0;
1027 /* active Bridges */
1028 active
= _SCBridgeInterfaceCopyActive();
1029 nActive
= (active
!= NULL
) ? CFArrayGetCount(active
) : 0;
1032 * remove any no-longer-configured bridge interfaces and
1033 * any devices associated with a bridge that are no longer
1034 * associated with a bridge.
1036 for (i
= 0; i
< nActive
; i
++) {
1037 SCBridgeInterfaceRef a_bridge
;
1038 CFStringRef a_bridge_if
;
1040 Boolean found
= FALSE
;
1042 a_bridge
= CFArrayGetValueAtIndex(active
, i
);
1043 a_bridge_if
= SCNetworkInterfaceGetBSDName(a_bridge
);
1045 for (j
= 0; j
< nConfig
; j
++) {
1046 SCBridgeInterfaceRef c_bridge
;
1047 CFStringRef c_bridge_if
;
1049 c_bridge
= CFArrayGetValueAtIndex(config
, j
);
1050 c_bridge_if
= SCNetworkInterfaceGetBSDName(c_bridge
);
1052 if (CFEqual(a_bridge_if
, c_bridge_if
)) {
1054 CFArrayRef a_bridge_interfaces
;
1056 CFArrayRef c_bridge_interfaces
;
1059 c_bridge_interfaces
= SCBridgeInterfaceGetMemberInterfaces(c_bridge
);
1060 c_count
= (c_bridge_interfaces
!= NULL
) ? CFArrayGetCount(c_bridge_interfaces
) : 0;
1062 a_bridge_interfaces
= SCBridgeInterfaceGetMemberInterfaces(a_bridge
);
1063 a_count
= (a_bridge_interfaces
!= NULL
) ? CFArrayGetCount(a_bridge_interfaces
) : 0;
1065 for (a
= 0; a
< a_count
; a
++) {
1066 SCNetworkInterfaceRef a_interface
;
1067 CFStringRef a_interface_if
;
1069 a_interface
= CFArrayGetValueAtIndex(a_bridge_interfaces
, a
);
1070 if ((c_count
== 0) ||
1071 !CFArrayContainsValue(c_bridge_interfaces
,
1072 CFRangeMake(0, c_count
),
1075 * if this device is no longer part
1079 s
= inet_dgram_socket();
1087 a_interface_if
= SCNetworkInterfaceGetBSDName(a_interface
);
1088 if (!__bridge_remove_interface(s
, a_bridge_if
, a_interface_if
)) {
1101 * if this interface is no longer configured
1104 s
= inet_dgram_socket();
1112 if (!__destroyInterface(s
, a_bridge_if
)) {
1120 * add any newly-configured bridge interfaces and add any
1121 * devices that should now be associated with the bridge.
1123 for (i
= 0; i
< nConfig
; i
++) {
1124 SCBridgeInterfaceRef c_bridge
;
1125 CFArrayRef c_bridge_interfaces
;
1126 CFStringRef c_bridge_if
;
1128 Boolean found
= FALSE
;
1131 c_bridge
= CFArrayGetValueAtIndex(config
, i
);
1132 c_bridge_if
= SCNetworkInterfaceGetBSDName(c_bridge
);
1133 c_bridge_interfaces
= SCBridgeInterfaceGetMemberInterfaces(c_bridge
);
1134 c_count
= (c_bridge_interfaces
!= NULL
) ? CFArrayGetCount(c_bridge_interfaces
) : 0;
1136 for (j
= 0; j
< nActive
; j
++) {
1137 SCBridgeInterfaceRef a_bridge
;
1138 CFArrayRef a_bridge_interfaces
;
1139 CFStringRef a_bridge_if
;
1142 a_bridge
= CFArrayGetValueAtIndex(active
, j
);
1143 a_bridge_if
= SCNetworkInterfaceGetBSDName(a_bridge
);
1144 a_bridge_interfaces
= SCBridgeInterfaceGetMemberInterfaces(a_bridge
);
1145 a_count
= (a_bridge_interfaces
!= NULL
) ? CFArrayGetCount(a_bridge_interfaces
) : 0;
1147 if (CFEqual(c_bridge_if
, a_bridge_if
)) {
1149 Boolean if_list_change
= FALSE
;
1153 if (!_SC_CFEqual(c_bridge_interfaces
, a_bridge_interfaces
)) {
1154 if_list_change
= TRUE
;
1156 if (!if_list_change
) {
1157 break; // if no change
1160 s
= inet_dgram_socket();
1167 if (!if_list_change
) {
1168 break; // no if list changes
1172 * ensure that the first device of the bridge matches, if
1173 * not then we remove all current devices and add them
1174 * back in the preferred order.
1176 if ((c_count
> 0) &&
1178 !CFEqual(CFArrayGetValueAtIndex(c_bridge_interfaces
, 0),
1179 CFArrayGetValueAtIndex(a_bridge_interfaces
, 0))) {
1182 for (a
= 0; a
< a_count
; a
++) {
1183 SCNetworkInterfaceRef a_interface
;
1184 CFStringRef a_interface_if
;
1186 a_interface
= CFArrayGetValueAtIndex(a_bridge_interfaces
, a
);
1187 if (!CFArrayContainsValue(c_bridge_interfaces
,
1188 CFRangeMake(0, c_count
),
1190 continue; // if already removed
1193 a_interface_if
= SCNetworkInterfaceGetBSDName(a_interface
);
1194 if (!__bridge_remove_interface(s
, a_bridge_if
, a_interface_if
)) {
1199 a_count
= 0; // all active devices have been removed
1203 * add any devices which are not currently associated
1204 * with the bridge interface.
1206 for (c
= 0; c
< c_count
; c
++) {
1207 SCNetworkInterfaceRef c_interface
;
1208 SCNetworkInterfacePrivateRef c_interfacePrivate
;
1209 CFStringRef c_interface_if
;
1211 c_interface
= CFArrayGetValueAtIndex(c_bridge_interfaces
, c
);
1212 if ((a_count
== 0) ||
1213 !CFArrayContainsValue(a_bridge_interfaces
,
1214 CFRangeMake(0, a_count
),
1217 * check if this member interface can be added to a bridge.
1219 c_interfacePrivate
= (SCNetworkInterfacePrivateRef
)c_interface
;
1220 if (!c_interfacePrivate
->supportsBridge
) {
1221 // if member not supported
1226 * if this member interface is not currently part of the bridge.
1228 c_interface_if
= SCNetworkInterfaceGetBSDName(c_interface
);
1229 if (!__bridge_add_interface(s
, c_bridge_if
, c_interface_if
)) {
1230 // if member could not be added
1244 s
= inet_dgram_socket();
1253 * establish the new bridge interface.
1255 if (!__createInterface(s
, c_bridge_if
)) {
1262 * add the member interfaces
1264 for (c
= 0; c
< c_count
; c
++) {
1265 SCNetworkInterfaceRef c_interface
;
1266 SCNetworkInterfacePrivateRef c_interfacePrivate
;
1267 CFStringRef c_interface_if
;
1269 c_interface
= CFArrayGetValueAtIndex(c_bridge_interfaces
, c
);
1270 c_interfacePrivate
= (SCNetworkInterfacePrivateRef
)c_interface
;
1271 if (!c_interfacePrivate
->supportsBridge
) {
1272 // if member not supported
1276 c_interface_if
= SCNetworkInterfaceGetBSDName(c_interface
);
1277 if (!__bridge_add_interface(s
, c_bridge_if
, c_interface_if
)) {
1278 // if member could not be added
1288 if (active
!= NULL
) CFRelease(active
);
1289 if (config
!= NULL
) CFRelease(config
);
1290 if (s
!= -1) (void) close(s
);
1295 #endif // IFT_BRIDGE