2 * Copyright (c) 2009-2014 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 SCLog(TRUE
, LOG_ERR
, CFSTR("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 SCLog(TRUE
, LOG_ERR
, CFSTR("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
) {
448 CFSTR("ifbifconf_copy(%s) failed: %s"),
456 // create the bridge interface
457 bridge_if
= CFStringCreateWithCString(NULL
, ifp
->ifa_name
, kCFStringEncodingASCII
);
458 bridge
= (SCBridgeInterfaceRef
)_SCBridgeInterfaceCreatePrivate(NULL
, bridge_if
);
459 CFRelease(bridge_if
);
461 // add member interfaces
462 if (ibc_p
->ifbic_len
> 0) {
465 // iterate over each member interface
466 for (i
= 0; i
< ibc_p
->ifbic_len
/ sizeof(struct ifbreq
); i
++) {
467 struct ifbreq
*ibr_p
;
470 ibr_p
= ibc_p
->ifbic_req
+ i
;
471 member
= CFStringCreateWithCString(NULL
, ibr_p
->ifbr_ifsname
, kCFStringEncodingASCII
);
472 add_interface(&members
, member
, NULL
);
478 if (members
!= NULL
) {
479 __SCBridgeInterfaceSetMemberInterfaces(bridge
, members
);
484 CFArrayAppendValue(bridges
, bridge
);
500 SCBridgeInterfaceCreate(SCPreferencesRef prefs
)
502 CFAllocatorRef allocator
;
503 SCBridgeInterfaceRef bridge
= NULL
;
507 _SCErrorSet(kSCStatusInvalidArgument
);
511 allocator
= CFGetAllocator(prefs
);
513 // create a new bridge using an unused interface name
514 for (i
= 0; bridge
== NULL
; i
++) {
515 CFDictionaryRef dict
;
516 CFStringRef bridge_if
;
517 SCNetworkInterfacePrivateRef interfacePrivate
;
518 CFMutableDictionaryRef newDict
;
519 CFArrayRef newInterfaces
;
523 bridge_if
= CFStringCreateWithFormat(allocator
, NULL
, CFSTR("bridge%ld"), i
);
524 path
= CFStringCreateWithFormat(allocator
,
527 kSCPrefVirtualNetworkInterfaces
,
528 kSCNetworkInterfaceTypeBridge
,
530 dict
= SCPreferencesPathGetValue(prefs
, path
);
532 // if bridge interface name not available
534 CFRelease(bridge_if
);
538 // add the bridge to the stored preferences
539 newDict
= CFDictionaryCreateMutable(allocator
,
541 &kCFTypeDictionaryKeyCallBacks
,
542 &kCFTypeDictionaryValueCallBacks
);
543 newInterfaces
= CFArrayCreate(allocator
, NULL
, 0, &kCFTypeArrayCallBacks
);
544 CFDictionaryAddValue(newDict
, kSCPropVirtualNetworkInterfacesBridgeInterfaces
, newInterfaces
);
545 CFRelease(newInterfaces
);
546 ok
= SCPreferencesPathSetValue(prefs
, path
, newDict
);
550 // if the bridge could not be saved
551 CFRelease(bridge_if
);
555 // create the SCBridgeInterfaceRef
556 bridge
= (SCBridgeInterfaceRef
)_SCBridgeInterfaceCreatePrivate(allocator
, bridge_if
);
557 CFRelease(bridge_if
);
559 // estabish link to the stored configuration
560 interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
561 interfacePrivate
->prefs
= CFRetain(prefs
);
569 SCBridgeInterfaceRemove(SCBridgeInterfaceRef bridge
)
571 CFStringRef bridge_if
;
572 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
576 if (!isA_SCBridgeInterface(bridge
)) {
577 _SCErrorSet(kSCStatusInvalidArgument
);
581 if (interfacePrivate
->prefs
== NULL
) {
582 _SCErrorSet(kSCStatusInvalidArgument
);
586 bridge_if
= SCNetworkInterfaceGetBSDName(bridge
);
587 path
= CFStringCreateWithFormat(NULL
,
590 kSCPrefVirtualNetworkInterfaces
,
591 kSCNetworkInterfaceTypeBridge
,
593 ok
= SCPreferencesPathRemoveValue(interfacePrivate
->prefs
, path
);
601 SCBridgeInterfaceGetMemberInterfaces(SCBridgeInterfaceRef bridge
)
603 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
605 if (!isA_SCBridgeInterface(bridge
)) {
606 _SCErrorSet(kSCStatusInvalidArgument
);
610 return interfacePrivate
->bridge
.interfaces
;
615 SCBridgeInterfaceGetOptions(SCBridgeInterfaceRef bridge
)
617 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
619 if (!isA_SCBridgeInterface(bridge
)) {
620 _SCErrorSet(kSCStatusInvalidArgument
);
624 return interfacePrivate
->bridge
.options
;
630 __SCBridgeInterfaceSetMemberInterfaces(SCBridgeInterfaceRef bridge
, CFArrayRef members
)
633 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
635 CFMutableArrayRef newMembers
;
638 n
= (members
!= NULL
) ? CFArrayGetCount(members
) : 0;
640 // set member interfaces in the stored preferences
641 if (interfacePrivate
->prefs
!= NULL
) {
642 CFDictionaryRef dict
;
643 CFMutableDictionaryRef newDict
;
646 path
= CFStringCreateWithFormat(NULL
,
649 kSCPrefVirtualNetworkInterfaces
,
650 kSCNetworkInterfaceTypeBridge
,
651 interfacePrivate
->entity_device
);
652 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
653 if (!isA_CFDictionary(dict
)) {
654 // if the prefs are confused
656 _SCErrorSet(kSCStatusFailed
);
660 newMembers
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
661 for (i
= 0; i
< n
; i
++) {
662 SCNetworkInterfaceRef interface
;
663 CFStringRef memberName
;
665 interface
= CFArrayGetValueAtIndex(members
, i
);
666 memberName
= SCNetworkInterfaceGetBSDName(interface
);
667 CFArrayAppendValue(newMembers
, memberName
);
670 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
671 CFDictionarySetValue(newDict
, kSCPropVirtualNetworkInterfacesBridgeInterfaces
, newMembers
);
672 CFRelease(newMembers
);
673 if (!CFEqual(dict
, newDict
)) {
674 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
681 newMembers
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
682 for (i
= 0; i
< n
; i
++) {
683 SCNetworkInterfaceRef member
;
684 SCNetworkInterfacePrivateRef newMember
;
686 member
= CFArrayGetValueAtIndex(members
, i
);
687 newMember
= __SCNetworkInterfaceCreateCopy(NULL
,
689 interfacePrivate
->prefs
,
690 interfacePrivate
->serviceID
);
691 CFArrayAppendValue(newMembers
, newMember
);
692 CFRelease(newMember
);
694 CFRelease(interfacePrivate
->bridge
.interfaces
);
695 interfacePrivate
->bridge
.interfaces
= newMembers
;
703 SCBridgeInterfaceSetMemberInterfaces(SCBridgeInterfaceRef bridge
, CFArrayRef members
)
705 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
707 int sc_status
= kSCStatusOK
;
709 if (!isA_SCBridgeInterface(bridge
)) {
710 _SCErrorSet(kSCStatusInvalidArgument
);
714 if ((members
!= NULL
) && !isA_CFArray(members
)) {
715 _SCErrorSet(kSCStatusInvalidArgument
);
719 if (interfacePrivate
->prefs
!= NULL
) {
720 CFArrayRef available
;
726 CFArrayRef services
= NULL
;
728 current
= SCBridgeInterfaceGetMemberInterfaces(bridge
);
729 n_current
= (current
!= NULL
) ? CFArrayGetCount(current
) : 0;
731 available
= SCBridgeInterfaceCopyAvailableMemberInterfaces(interfacePrivate
->prefs
);
732 n_available
= (available
!= NULL
) ? CFArrayGetCount(available
) : 0;
734 n_members
= (members
!= NULL
) ? CFArrayGetCount(members
) : 0;
735 for (i
= 0; i
< n_members
; i
++) {
736 SCNetworkInterfaceRef member
;
738 member
= CFArrayGetValueAtIndex(members
, i
);
740 if ((current
!= NULL
) &&
741 CFArrayContainsValue(current
, CFRangeMake(0, n_current
), member
)) {
742 // current members are allowed
746 if ((available
!= NULL
) &&
747 CFArrayContainsValue(available
, CFRangeMake(0, n_available
), member
)) {
748 // available members are allowed but cannot be associated
749 // with any other network services.
751 if (services
== NULL
) {
752 services
= __SCNetworkServiceCopyAllEnabled(interfacePrivate
->prefs
);
754 if ((services
!= NULL
) &&
755 __SCNetworkServiceExistsForInterface(services
, member
)) {
756 sc_status
= kSCStatusKeyExists
;
764 // if member not allowed
765 sc_status
= kSCStatusInvalidArgument
;
769 if (available
!= NULL
) CFRelease(available
);
770 if (services
!= NULL
) CFRelease(services
);
773 if (sc_status
!= kSCStatusOK
) {
774 _SCErrorSet(sc_status
);
778 ok
= __SCBridgeInterfaceSetMemberInterfaces(bridge
, members
);
784 SCBridgeInterfaceSetLocalizedDisplayName(SCBridgeInterfaceRef bridge
, CFStringRef newName
)
786 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
789 if (!isA_SCBridgeInterface(bridge
)) {
790 _SCErrorSet(kSCStatusInvalidArgument
);
794 if ((newName
!= NULL
) && !isA_CFString(newName
)) {
795 _SCErrorSet(kSCStatusInvalidArgument
);
799 // set name in the stored preferences
800 if (interfacePrivate
->prefs
!= NULL
) {
801 CFDictionaryRef dict
;
802 CFMutableDictionaryRef newDict
;
805 path
= CFStringCreateWithFormat(NULL
,
808 kSCPrefVirtualNetworkInterfaces
,
809 kSCNetworkInterfaceTypeBridge
,
810 interfacePrivate
->entity_device
);
811 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
812 if (!isA_CFDictionary(dict
)) {
813 // if the prefs are confused
815 _SCErrorSet(kSCStatusFailed
);
819 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
820 if (newName
!= NULL
) {
821 CFDictionarySetValue(newDict
, kSCPropUserDefinedName
, newName
);
823 CFDictionaryRemoveValue(newDict
, kSCPropUserDefinedName
);
825 if (!CFEqual(dict
, newDict
)) {
826 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
832 // set name in the SCBridgeInterfaceRef
834 if (interfacePrivate
->localized_name
!= NULL
) {
835 CFRelease(interfacePrivate
->localized_name
);
836 interfacePrivate
->localized_name
= NULL
;
838 if (newName
!= NULL
) {
839 interfacePrivate
->localized_name
= CFStringCreateCopy(NULL
, newName
);
848 SCBridgeInterfaceSetOptions(SCBridgeInterfaceRef bridge
, CFDictionaryRef newOptions
)
850 SCNetworkInterfacePrivateRef interfacePrivate
= (SCNetworkInterfacePrivateRef
)bridge
;
853 if (!isA_SCBridgeInterface(bridge
)) {
854 _SCErrorSet(kSCStatusInvalidArgument
);
858 if ((newOptions
!= NULL
) && !isA_CFDictionary(newOptions
)) {
859 _SCErrorSet(kSCStatusInvalidArgument
);
863 // set options in the stored preferences
864 if (interfacePrivate
->prefs
!= NULL
) {
865 CFDictionaryRef dict
;
866 CFMutableDictionaryRef newDict
;
869 path
= CFStringCreateWithFormat(NULL
,
872 kSCPrefVirtualNetworkInterfaces
,
873 kSCNetworkInterfaceTypeBridge
,
874 interfacePrivate
->entity_device
);
875 dict
= SCPreferencesPathGetValue(interfacePrivate
->prefs
, path
);
876 if (!isA_CFDictionary(dict
)) {
877 // if the prefs are confused
879 _SCErrorSet(kSCStatusFailed
);
883 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
884 if (newOptions
!= NULL
) {
885 CFDictionarySetValue(newDict
, kSCPropVirtualNetworkInterfacesBridgeOptions
, newOptions
);
887 CFDictionaryRemoveValue(newDict
, kSCPropVirtualNetworkInterfacesBridgeOptions
);
889 if (!CFEqual(dict
, newDict
)) {
890 ok
= SCPreferencesPathSetValue(interfacePrivate
->prefs
, path
, newDict
);
896 // set options in the SCBridgeInterfaceRef
898 if (interfacePrivate
->bridge
.options
!= NULL
) {
899 CFRelease(interfacePrivate
->bridge
.options
);
900 interfacePrivate
->bridge
.options
= NULL
;
902 if (newOptions
!= NULL
) {
903 CFStringRef name_auto
= NULL
;
905 interfacePrivate
->bridge
.options
= CFDictionaryCreateCopy(NULL
, newOptions
);
907 // set [auto] display name from options
908 if ((interfacePrivate
->localized_name
== NULL
) &&
909 CFDictionaryGetValueIfPresent(newOptions
,
911 (const void **)&name_auto
) &&
912 isA_CFString(name_auto
)) {
914 interfacePrivate
->localized_key
= name_auto
;
915 if (interfacePrivate
->localized_arg1
!= NULL
) {
916 CFRelease(interfacePrivate
->localized_arg1
);
917 interfacePrivate
->localized_arg1
= NULL
;
928 #pragma mark SCBridgeInterface management
933 __bridge_add_interface(int s
, CFStringRef bridge_if
, CFStringRef interface_if
)
939 bzero(&ifd
, sizeof(ifd
));
940 (void) _SC_cfstring_to_cstring(bridge_if
,
942 sizeof(ifd
.ifd_name
),
943 kCFStringEncodingASCII
);
944 ifd
.ifd_cmd
= BRDGADD
;
945 ifd
.ifd_len
= sizeof(breq
);
946 ifd
.ifd_data
= (caddr_t
)&breq
;
949 bzero(&breq
, sizeof(breq
));
950 (void) _SC_cfstring_to_cstring(interface_if
,
952 sizeof(breq
.ifbr_ifsname
),
953 kCFStringEncodingASCII
);
955 // add new bridge member
956 if (ioctl(s
, SIOCSDRVSPEC
, (caddr_t
)&ifd
) == -1) {
959 CFSTR("could not add interface \"%@\" to bridge \"%@\": %s"),
971 __bridge_remove_interface(int s
, CFStringRef bridge_if
, CFStringRef interface_if
)
977 bzero(&ifd
, sizeof(ifd
));
978 (void) _SC_cfstring_to_cstring(bridge_if
,
980 sizeof(ifd
.ifd_name
),
981 kCFStringEncodingASCII
);
982 ifd
.ifd_cmd
= BRDGDEL
;
983 ifd
.ifd_len
= sizeof(breq
);
984 ifd
.ifd_data
= (caddr_t
)&breq
;
986 // bridge member to remove
987 bzero(&breq
, sizeof(breq
));
988 (void) _SC_cfstring_to_cstring(interface_if
,
990 sizeof(breq
.ifbr_ifsname
),
991 kCFStringEncodingASCII
);
993 // remove bridge member
994 if (ioctl(s
, SIOCSDRVSPEC
, (caddr_t
)&ifd
) == -1) {
997 CFSTR("could not add interface \"%@\" to bridge \"%@\": %s"),
1006 #endif // IFT_BRIDGE
1010 _SCBridgeInterfaceUpdateConfiguration(SCPreferencesRef prefs
)
1013 CFArrayRef active
= NULL
;
1014 CFArrayRef config
= NULL
;
1021 if (prefs
== NULL
) {
1022 _SCErrorSet(kSCStatusInvalidArgument
);
1026 /* configured Bridges */
1027 config
= SCBridgeInterfaceCopyAll(prefs
);
1028 nConfig
= (config
!= NULL
) ? CFArrayGetCount(config
) : 0;
1030 /* active Bridges */
1031 active
= _SCBridgeInterfaceCopyActive();
1032 nActive
= (active
!= NULL
) ? CFArrayGetCount(active
) : 0;
1035 * remove any no-longer-configured bridge interfaces and
1036 * any devices associated with a bridge that are no longer
1037 * associated with a bridge.
1039 for (i
= 0; i
< nActive
; i
++) {
1040 SCBridgeInterfaceRef a_bridge
;
1041 CFStringRef a_bridge_if
;
1043 Boolean found
= FALSE
;
1045 a_bridge
= CFArrayGetValueAtIndex(active
, i
);
1046 a_bridge_if
= SCNetworkInterfaceGetBSDName(a_bridge
);
1048 for (j
= 0; j
< nConfig
; j
++) {
1049 SCBridgeInterfaceRef c_bridge
;
1050 CFStringRef c_bridge_if
;
1052 c_bridge
= CFArrayGetValueAtIndex(config
, j
);
1053 c_bridge_if
= SCNetworkInterfaceGetBSDName(c_bridge
);
1055 if (CFEqual(a_bridge_if
, c_bridge_if
)) {
1057 CFArrayRef a_bridge_interfaces
;
1059 CFArrayRef c_bridge_interfaces
;
1062 c_bridge_interfaces
= SCBridgeInterfaceGetMemberInterfaces(c_bridge
);
1063 c_count
= (c_bridge_interfaces
!= NULL
) ? CFArrayGetCount(c_bridge_interfaces
) : 0;
1065 a_bridge_interfaces
= SCBridgeInterfaceGetMemberInterfaces(a_bridge
);
1066 a_count
= (a_bridge_interfaces
!= NULL
) ? CFArrayGetCount(a_bridge_interfaces
) : 0;
1068 for (a
= 0; a
< a_count
; a
++) {
1069 SCNetworkInterfaceRef a_interface
;
1070 CFStringRef a_interface_if
;
1072 a_interface
= CFArrayGetValueAtIndex(a_bridge_interfaces
, a
);
1073 if ((c_count
== 0) ||
1074 !CFArrayContainsValue(c_bridge_interfaces
,
1075 CFRangeMake(0, c_count
),
1078 * if this device is no longer part
1082 s
= inet_dgram_socket();
1090 a_interface_if
= SCNetworkInterfaceGetBSDName(a_interface
);
1091 if (!__bridge_remove_interface(s
, a_bridge_if
, a_interface_if
)) {
1104 * if this interface is no longer configured
1107 s
= inet_dgram_socket();
1115 if (!__destroyInterface(s
, a_bridge_if
)) {
1123 * add any newly-configured bridge interfaces and add any
1124 * devices that should now be associated with the bridge.
1126 for (i
= 0; i
< nConfig
; i
++) {
1127 SCBridgeInterfaceRef c_bridge
;
1128 CFArrayRef c_bridge_interfaces
;
1129 CFStringRef c_bridge_if
;
1131 Boolean found
= FALSE
;
1134 c_bridge
= CFArrayGetValueAtIndex(config
, i
);
1135 c_bridge_if
= SCNetworkInterfaceGetBSDName(c_bridge
);
1136 c_bridge_interfaces
= SCBridgeInterfaceGetMemberInterfaces(c_bridge
);
1137 c_count
= (c_bridge_interfaces
!= NULL
) ? CFArrayGetCount(c_bridge_interfaces
) : 0;
1139 for (j
= 0; j
< nActive
; j
++) {
1140 SCBridgeInterfaceRef a_bridge
;
1141 CFArrayRef a_bridge_interfaces
;
1142 CFStringRef a_bridge_if
;
1145 a_bridge
= CFArrayGetValueAtIndex(active
, j
);
1146 a_bridge_if
= SCNetworkInterfaceGetBSDName(a_bridge
);
1147 a_bridge_interfaces
= SCBridgeInterfaceGetMemberInterfaces(a_bridge
);
1148 a_count
= (a_bridge_interfaces
!= NULL
) ? CFArrayGetCount(a_bridge_interfaces
) : 0;
1150 if (CFEqual(c_bridge_if
, a_bridge_if
)) {
1152 Boolean if_list_change
= FALSE
;
1156 if (!_SC_CFEqual(c_bridge_interfaces
, a_bridge_interfaces
)) {
1157 if_list_change
= TRUE
;
1159 if (!if_list_change
) {
1160 break; // if no change
1163 s
= inet_dgram_socket();
1170 if (!if_list_change
) {
1171 break; // no if list changes
1175 * ensure that the first device of the bridge matches, if
1176 * not then we remove all current devices and add them
1177 * back in the preferred order.
1179 if ((c_count
> 0) &&
1181 !CFEqual(CFArrayGetValueAtIndex(c_bridge_interfaces
, 0),
1182 CFArrayGetValueAtIndex(a_bridge_interfaces
, 0))) {
1185 for (a
= 0; a
< a_count
; a
++) {
1186 SCNetworkInterfaceRef a_interface
;
1187 CFStringRef a_interface_if
;
1189 a_interface
= CFArrayGetValueAtIndex(a_bridge_interfaces
, a
);
1190 if (!CFArrayContainsValue(c_bridge_interfaces
,
1191 CFRangeMake(0, c_count
),
1193 continue; // if already removed
1196 a_interface_if
= SCNetworkInterfaceGetBSDName(a_interface
);
1197 if (!__bridge_remove_interface(s
, a_bridge_if
, a_interface_if
)) {
1202 a_count
= 0; // all active devices have been removed
1206 * add any devices which are not currently associated
1207 * with the bridge interface.
1209 for (c
= 0; c
< c_count
; c
++) {
1210 SCNetworkInterfaceRef c_interface
;
1211 SCNetworkInterfacePrivateRef c_interfacePrivate
;
1212 CFStringRef c_interface_if
;
1214 c_interface
= CFArrayGetValueAtIndex(c_bridge_interfaces
, c
);
1215 if ((a_count
== 0) ||
1216 !CFArrayContainsValue(a_bridge_interfaces
,
1217 CFRangeMake(0, a_count
),
1220 * check if this member interface can be added to a bridge.
1222 c_interfacePrivate
= (SCNetworkInterfacePrivateRef
)c_interface
;
1223 if (!c_interfacePrivate
->supportsBridge
) {
1224 // if member not supported
1229 * if this member interface is not currently part of the bridge.
1231 c_interface_if
= SCNetworkInterfaceGetBSDName(c_interface
);
1232 if (!__bridge_add_interface(s
, c_bridge_if
, c_interface_if
)) {
1233 // if member could not be added
1247 s
= inet_dgram_socket();
1256 * establish the new bridge interface.
1258 if (!__createInterface(s
, c_bridge_if
)) {
1265 * add the member interfaces
1267 for (c
= 0; c
< c_count
; c
++) {
1268 SCNetworkInterfaceRef c_interface
;
1269 SCNetworkInterfacePrivateRef c_interfacePrivate
;
1270 CFStringRef c_interface_if
;
1272 c_interface
= CFArrayGetValueAtIndex(c_bridge_interfaces
, c
);
1273 c_interfacePrivate
= (SCNetworkInterfacePrivateRef
)c_interface
;
1274 if (!c_interfacePrivate
->supportsBridge
) {
1275 // if member not supported
1279 c_interface_if
= SCNetworkInterfaceGetBSDName(c_interface
);
1280 if (!__bridge_add_interface(s
, c_bridge_if
, c_interface_if
)) {
1281 // if member could not be added
1291 if (active
!= NULL
) CFRelease(active
);
1292 if (config
!= NULL
) CFRelease(config
);
1293 if (s
!= -1) (void) close(s
);
1298 #endif // IFT_BRIDGE