2 * Copyright (c) 2004-2017 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 * May 13, 2004 Allan Nathanson <ajn@apple.com>
32 #include <CoreFoundation/CoreFoundation.h>
33 #include <CoreFoundation/CFRuntime.h>
34 #include "SCNetworkConfigurationInternal.h"
39 static CFStringRef
__SCNetworkSetCopyDescription (CFTypeRef cf
);
40 static void __SCNetworkSetDeallocate (CFTypeRef cf
);
41 static Boolean
__SCNetworkSetEqual (CFTypeRef cf1
, CFTypeRef cf2
);
42 static CFHashCode
__SCNetworkSetHash (CFTypeRef cf
);
45 static CFTypeID __kSCNetworkSetTypeID
= _kCFRuntimeNotATypeID
;
48 static const CFRuntimeClass __SCNetworkSetClass
= {
50 "SCNetworkSet", // className
53 __SCNetworkSetDeallocate
, // dealloc
54 __SCNetworkSetEqual
, // equal
55 __SCNetworkSetHash
, // hash
56 NULL
, // copyFormattingDesc
57 __SCNetworkSetCopyDescription
// copyDebugDesc
61 static pthread_once_t initialized
= PTHREAD_ONCE_INIT
;
65 __SCNetworkSetCopyDescription(CFTypeRef cf
)
67 CFAllocatorRef allocator
= CFGetAllocator(cf
);
68 CFMutableStringRef result
;
69 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)cf
;
71 result
= CFStringCreateMutable(allocator
, 0);
72 CFStringAppendFormat(result
, NULL
, CFSTR("<SCNetworkSet %p [%p]> {"), cf
, allocator
);
73 CFStringAppendFormat(result
, NULL
, CFSTR("id = %@"), setPrivate
->setID
);
74 CFStringAppendFormat(result
, NULL
, CFSTR(", prefs = %p"), setPrivate
->prefs
);
75 if (setPrivate
->name
!= NULL
) {
76 CFStringAppendFormat(result
, NULL
, CFSTR(", name = %@"), setPrivate
->name
);
78 CFStringAppendFormat(result
, NULL
, CFSTR("}"));
85 __SCNetworkSetDeallocate(CFTypeRef cf
)
87 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)cf
;
89 /* release resources */
91 CFRelease(setPrivate
->setID
);
92 CFRelease(setPrivate
->prefs
);
93 if (setPrivate
->name
!= NULL
)
94 CFRelease(setPrivate
->name
);
101 __SCNetworkSetEqual(CFTypeRef cf1
, CFTypeRef cf2
)
103 SCNetworkSetPrivateRef s1
= (SCNetworkSetPrivateRef
)cf1
;
104 SCNetworkSetPrivateRef s2
= (SCNetworkSetPrivateRef
)cf2
;
109 if (s1
->prefs
!= s2
->prefs
)
110 return FALSE
; // if not the same prefs
112 if (!CFEqual(s1
->setID
, s2
->setID
))
113 return FALSE
; // if not the same set identifier
120 __SCNetworkSetHash(CFTypeRef cf
)
122 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)cf
;
124 return CFHash(setPrivate
->setID
);
129 __SCNetworkSetInitialize(void)
131 __kSCNetworkSetTypeID
= _CFRuntimeRegisterClass(&__SCNetworkSetClass
);
136 static SCNetworkSetPrivateRef
137 __SCNetworkSetCreatePrivate(CFAllocatorRef allocator
,
138 SCPreferencesRef prefs
,
141 SCNetworkSetPrivateRef setPrivate
;
144 /* initialize runtime */
145 pthread_once(&initialized
, __SCNetworkSetInitialize
);
147 /* allocate target */
148 size
= sizeof(SCNetworkSetPrivate
) - sizeof(CFRuntimeBase
);
149 setPrivate
= (SCNetworkSetPrivateRef
)_CFRuntimeCreateInstance(allocator
,
150 __kSCNetworkSetTypeID
,
153 if (setPrivate
== NULL
) {
157 /* initialize non-zero/NULL members */
158 setPrivate
->setID
= CFStringCreateCopy(NULL
, setID
);
159 setPrivate
->prefs
= CFRetain(prefs
);
169 _serviceOrder(SCNetworkServiceRef service
)
171 SCNetworkInterfaceRef interface
;
173 interface
= SCNetworkServiceGetInterface(service
);
174 if ((interface
== NULL
) || _SCNetworkServiceIsVPN(service
)) {
175 return 100000; // if unknown or VPN interface, sort last
178 return __SCNetworkInterfaceOrder(interface
);
183 _serviceOrder_add(SCNetworkSetRef set
, SCNetworkServiceRef service
)
187 CFMutableArrayRef newOrder
;
189 CFStringRef serviceID
;
190 CFIndex serviceOrder
;
191 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
194 order
= SCNetworkSetGetServiceOrder(set
);
196 newOrder
= CFArrayCreateMutableCopy(NULL
, 0, order
);
198 newOrder
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
200 assert(newOrder
!= NULL
);
201 n
= CFArrayGetCount(newOrder
);
203 serviceID
= SCNetworkServiceGetServiceID(service
);
204 if (CFArrayContainsValue(newOrder
, CFRangeMake(0, n
), serviceID
)) {
205 // if serviceID already present
209 serviceOrder
= _serviceOrder(service
);
212 for (i
= 0; i
< n
; i
++) {
214 SCNetworkServiceRef slotService
;
215 CFStringRef slotServiceID
;
217 slotServiceID
= CFArrayGetValueAtIndex(newOrder
, i
);
218 if (!isA_CFString(slotServiceID
)) {
223 slotService
= SCNetworkServiceCopy(setPrivate
->prefs
, slotServiceID
);
224 if (slotService
== NULL
) {
225 // if serviceID not valid
229 slotOrder
= _serviceOrder(slotService
);
230 if (serviceOrder
>= slotOrder
) {
231 // add the service *after* this one
235 CFRelease(slotService
);
238 CFArrayInsertValueAtIndex(newOrder
, slot
, serviceID
);
239 (void) SCNetworkSetSetServiceOrder(set
, newOrder
);
250 _serviceOrder_remove(SCNetworkSetRef set
, SCNetworkServiceRef service
)
252 CFMutableArrayRef newOrder
;
254 CFStringRef serviceID
;
256 order
= SCNetworkSetGetServiceOrder(set
);
261 serviceID
= SCNetworkServiceGetServiceID(service
);
263 newOrder
= CFArrayCreateMutableCopy(NULL
, 0, order
);
267 i
= CFArrayGetFirstIndexOfValue(newOrder
,
268 CFRangeMake(0, CFArrayGetCount(newOrder
)),
270 if (i
== kCFNotFound
) {
274 CFArrayRemoveValueAtIndex(newOrder
, i
);
276 (void) SCNetworkSetSetServiceOrder(set
, newOrder
);
284 #pragma mark SCNetworkSet APIs
290 #define PREVENT_DUPLICATE_SERVICE_NAMES
291 #ifdef PREVENT_DUPLICATE_SERVICE_NAMES
293 copy_next_name(CFStringRef name
)
295 CFArrayRef components
;
297 CFMutableArrayRef newComponents
;
304 components
= CFStringCreateArrayBySeparatingStrings(NULL
, name
, CFSTR(" "));
305 if (components
!= NULL
) {
306 newComponents
= CFArrayCreateMutableCopy(NULL
, 0, components
);
307 CFRelease(components
);
309 newComponents
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
310 CFArrayAppendValue(newComponents
, name
);
313 n
= CFArrayGetCount(newComponents
);
317 str
= CFArrayGetValueAtIndex(newComponents
, n
- 1);
318 suffix
= CFStringGetIntValue(str
);
320 CFArrayRemoveValueAtIndex(newComponents
, n
- 1);
326 name
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%d"), (int)suffix
);
327 CFArrayAppendValue(newComponents
, name
);
330 name
= CFStringCreateByCombiningStrings(NULL
, newComponents
, CFSTR(" "));
331 CFRelease(newComponents
);
338 ensure_unique_service_name(SCNetworkServiceRef service
)
340 SCNetworkInterfaceRef interface
;
344 interface
= SCNetworkServiceGetInterface(service
);
346 name
= SCNetworkServiceGetName(service
);
354 ok
= SCNetworkServiceSetName(service
, name
);
359 if (SCError() != kSCStatusKeyExists
) {
360 SC_log(LOG_INFO
, "could not update service name for \"%@\": %s",
361 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
362 SCErrorString(SCError()));
366 newName
= copy_next_name(name
);
367 if (newName
== NULL
) {
368 SC_log(LOG_INFO
, "could not create unique name for \"%@\": %s",
369 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
370 SCErrorString(SCError()));
374 // try again with the "new" name
387 #endif // PREVENT_DUPLICATE_SERVICE_NAMES
391 SCNetworkSetAddService(SCNetworkSetRef set
, SCNetworkServiceRef service
)
393 SCNetworkInterfaceRef interface
;
394 CFArrayRef interface_config
= NULL
;
398 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
399 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
401 if (!isA_SCNetworkSet(set
)) {
402 _SCErrorSet(kSCStatusInvalidArgument
);
406 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
407 _SCErrorSet(kSCStatusInvalidArgument
);
411 // make sure that we do not add an orphaned network service if its
412 // associated interface is a member of a bond or bridge.
413 interface
= SCNetworkServiceGetInterface(service
);
414 if ((interface
!= NULL
) &&
415 __SCNetworkInterfaceIsMember(servicePrivate
->prefs
, interface
)) {
416 _SCErrorSet(kSCStatusKeyExists
);
420 //#define PREVENT_DUPLICATE_SETS
421 #ifdef PREVENT_DUPLICATE_SETS
424 // ensure that each service is only a member of ONE set
425 sets
= SCNetworkSetCopyAll(setPrivate
->prefs
);
430 n
= CFArrayGetCount(sets
);
431 for (i
= 0; i
< n
; i
++) {
436 set
= CFArrayGetValueAtIndex(sets
, i
);
437 services
= SCNetworkSetCopyServices(set
);
438 found
= CFArrayContainsValue(services
,
439 CFRangeMake(0, CFArrayGetCount(services
)),
445 _SCErrorSet(kSCStatusKeyExists
);
451 #endif /* PREVENT_DUPLICATE_SETS */
453 // get the [deep] interface configuration settings
454 interface
= SCNetworkServiceGetInterface(service
);
455 if (interface
!= NULL
) {
456 interface_config
= __SCNetworkInterfaceCopyDeepConfiguration(set
, interface
);
459 // create the link between "set" and the "service"
460 path
= SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL
, // allocator
461 setPrivate
->setID
, // set
462 servicePrivate
->serviceID
, // service
464 link
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
465 servicePrivate
->serviceID
, // service
467 ok
= SCPreferencesPathSetLink(setPrivate
->prefs
, path
, link
);
468 #ifdef PREVENT_DUPLICATE_SERVICE_NAMES
470 // We use the interface cache here to not reach into the
471 // IORegistry for every service we go through
472 _SCNetworkInterfaceCacheOpen();
473 ok
= ensure_unique_service_name(service
);
474 _SCNetworkInterfaceCacheClose();
477 // if we could not ensure a unique name, remove the (just added)
478 // link between the "set" and the "service"
479 (void) SCPreferencesPathRemoveValue(setPrivate
->prefs
, path
);
482 #endif // PREVENT_DUPLICATE_SERVICE_NAMES
489 // push the [deep] interface configuration into all sets which contain this service.
490 if (interface
!= NULL
) {
491 __SCNetworkInterfaceSetDeepConfiguration(set
, interface
, interface_config
);
494 // add service to ServiceOrder
495 _serviceOrder_add(set
, service
);
497 // mark set as no longer "new"
498 setPrivate
->established
= TRUE
;
503 SC_log(LOG_DEBUG
, "SCNetworkSetAddService(): %@, %@", set
, service
);
506 if (interface_config
!= NULL
) CFRelease(interface_config
);
512 SCNetworkSetCopy(SCPreferencesRef prefs
, CFStringRef setID
)
514 CFDictionaryRef entity
;
516 SCNetworkSetPrivateRef setPrivate
;
518 if (!isA_CFString(setID
)) {
519 _SCErrorSet(kSCStatusInvalidArgument
);
523 path
= SCPreferencesPathKeyCreateSet(NULL
, setID
);
524 entity
= SCPreferencesPathGetValue(prefs
, path
);
527 if (!isA_CFDictionary(entity
)) {
528 _SCErrorSet(kSCStatusNoKey
);
532 setPrivate
= __SCNetworkSetCreatePrivate(NULL
, prefs
, setID
);
533 assert(setPrivate
!= NULL
);
535 // mark set as "old" (already established)
536 setPrivate
->established
= TRUE
;
538 return (SCNetworkSetRef
)setPrivate
;
543 SCNetworkSetContainsInterface(SCNetworkSetRef set
, SCNetworkInterfaceRef interface
)
545 Boolean found
= FALSE
;
548 services
= SCNetworkSetCopyServices(set
);
549 if (services
!= NULL
) {
550 found
= __SCNetworkServiceExistsForInterface(services
, interface
);
558 CFArrayRef
/* of SCNetworkSetRef's */
559 SCNetworkSetCopyAll(SCPreferencesRef prefs
)
561 CFMutableArrayRef array
;
564 CFDictionaryRef sets
;
566 path
= SCPreferencesPathKeyCreateSets(NULL
);
567 sets
= SCPreferencesPathGetValue(prefs
, path
);
570 if ((sets
!= NULL
) && !isA_CFDictionary(sets
)) {
574 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
576 n
= (sets
!= NULL
) ? CFDictionaryGetCount(sets
) : 0;
579 const void * keys_q
[N_QUICK
];
580 const void ** keys
= keys_q
;
581 const void * vals_q
[N_QUICK
];
582 const void ** vals
= vals_q
;
584 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
585 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
586 vals
= CFAllocatorAllocate(NULL
, n
* sizeof(CFPropertyListRef
), 0);
588 CFDictionaryGetKeysAndValues(sets
, keys
, vals
);
589 for (i
= 0; i
< n
; i
++) {
590 SCNetworkSetPrivateRef setPrivate
;
592 if (!isA_CFDictionary(vals
[i
])) {
593 SC_log(LOG_INFO
, "error w/set \"%@\"", keys
[i
]);
597 setPrivate
= __SCNetworkSetCreatePrivate(NULL
, prefs
, keys
[i
]);
598 assert(setPrivate
!= NULL
);
600 // mark set as "old" (already established)
601 setPrivate
->established
= TRUE
;
603 CFArrayAppendValue(array
, (SCNetworkSetRef
)setPrivate
);
604 CFRelease(setPrivate
);
606 if (keys
!= keys_q
) {
607 CFAllocatorDeallocate(NULL
, keys
);
608 CFAllocatorDeallocate(NULL
, vals
);
616 CFArrayRef
/* of SCNetworkInterfaceRef's */
617 SCNetworkSetCopyAvailableInterfaces(SCNetworkSetRef set
)
619 CFMutableArrayRef available
;
620 CFMutableSetRef excluded
= NULL
;
622 CFArrayRef interfaces
;
623 CFIndex n_interfaces
;
624 CFIndex n_exclusions
= 0;
625 SCPreferencesRef prefs
;
626 SCNetworkSetPrivateRef setPrivate
;
628 setPrivate
= (SCNetworkSetPrivateRef
)set
;
629 prefs
= setPrivate
->prefs
;
631 interfaces
= _SCNetworkInterfaceCopyAllWithPreferences(prefs
);
632 n_interfaces
= CFArrayGetCount(interfaces
);
633 if (n_interfaces
== 0) {
638 CFArrayRef bridges
= NULL
;
640 excluded
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
642 #if !TARGET_OS_IPHONE
643 CFArrayRef bonds
= NULL
;
645 bonds
= SCBondInterfaceCopyAll(prefs
);
647 __SCBondInterfaceListCollectMembers(bonds
, excluded
);
650 #endif /* !TARGET_OS_IPHONE */
652 bridges
= SCBridgeInterfaceCopyAll(prefs
);
653 if (bridges
!= NULL
) {
654 __SCBridgeInterfaceListCollectMembers(bridges
, excluded
);
658 n_exclusions
= CFSetGetCount(excluded
);
661 if (n_exclusions
== 0) {
662 if (excluded
!= NULL
) {
669 available
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
671 for (i
= 0; i
< n_interfaces
; i
++) {
672 SCNetworkInterfaceRef interface
;
674 interface
= CFArrayGetValueAtIndex(interfaces
, i
);
675 if (CFSetContainsValue(excluded
, interface
)) {
680 CFArrayAppendValue(available
, interface
);
683 CFRelease(interfaces
);
691 SCNetworkSetCopyCurrent(SCPreferencesRef prefs
)
693 CFArrayRef components
;
694 CFStringRef currentID
;
695 SCNetworkSetPrivateRef setPrivate
= NULL
;
697 currentID
= SCPreferencesGetValue(prefs
, kSCPrefCurrentSet
);
698 if (!isA_CFString(currentID
)) {
702 components
= CFStringCreateArrayBySeparatingStrings(NULL
, currentID
, CFSTR("/"));
703 if (CFArrayGetCount(components
) == 3) {
707 setID
= CFArrayGetValueAtIndex(components
, 2);
708 path
= SCPreferencesPathKeyCreateSet(NULL
, setID
);
709 if (CFEqual(path
, currentID
)) {
710 setPrivate
= __SCNetworkSetCreatePrivate(NULL
, prefs
, setID
);
711 assert(setPrivate
!= NULL
);
713 // mark set as "old" (already established)
714 setPrivate
->established
= TRUE
;
716 SC_log(LOG_NOTICE
, "SCNetworkSetCopyCurrent(): preferences are non-conformant");
720 CFRelease(components
);
722 return (SCNetworkSetRef
)setPrivate
;
726 CFArrayRef
/* of SCNetworkServiceRef's */
727 SCNetworkSetCopyServices(SCNetworkSetRef set
)
729 CFMutableArrayRef array
;
730 CFDictionaryRef dict
;
733 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
735 if (!isA_SCNetworkSet(set
)) {
736 _SCErrorSet(kSCStatusInvalidArgument
);
740 path
= SCPreferencesPathKeyCreateSetNetworkService(NULL
, setPrivate
->setID
, NULL
);
741 dict
= SCPreferencesPathGetValue(setPrivate
->prefs
, path
);
743 if ((dict
!= NULL
) && !isA_CFDictionary(dict
)) {
747 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
749 n
= (dict
!= NULL
) ? CFDictionaryGetCount(dict
) : 0;
752 const void * keys_q
[N_QUICK
];
753 const void ** keys
= keys_q
;
755 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
756 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
758 CFDictionaryGetKeysAndValues(dict
, keys
, NULL
);
759 for (i
= 0; i
< n
; i
++) {
760 CFArrayRef components
;
763 path
= SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL
,
765 (CFStringRef
)keys
[i
],
767 link
= SCPreferencesPathGetLink(setPrivate
->prefs
, path
);
770 SC_log(LOG_INFO
, "service \"%@\" for set \"%@\" is not a link",
773 continue; // if the service is not a link
776 components
= CFStringCreateArrayBySeparatingStrings(NULL
, link
, CFSTR("/"));
777 if (CFArrayGetCount(components
) == 3) {
778 CFStringRef serviceID
;
780 serviceID
= CFArrayGetValueAtIndex(components
, 2);
781 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
782 serviceID
, // service
784 if (CFEqual(path
, link
)) {
785 CFDictionaryRef entity
;
786 CFStringRef interfacePath
;
787 Boolean skip
= FALSE
;
789 interfacePath
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
790 serviceID
, // service
791 kSCEntNetInterface
); // entity
792 entity
= SCPreferencesPathGetValue(setPrivate
->prefs
, interfacePath
);
793 CFRelease(interfacePath
);
795 if (__SCNetworkInterfaceEntityIsPPTP(entity
)) {
796 SC_log(LOG_INFO
, "PPTP services are no longer supported");
801 SCNetworkServicePrivateRef servicePrivate
;
803 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
,
807 CFArrayAppendValue(array
, (SCNetworkServiceRef
)servicePrivate
);
808 CFRelease(servicePrivate
);
813 CFRelease(components
);
815 if (keys
!= keys_q
) {
816 CFAllocatorDeallocate(NULL
, keys
);
825 SCNetworkSetCreate(SCPreferencesRef prefs
)
827 CFArrayRef components
;
828 CFDictionaryRef entity
;
833 SCNetworkSetPrivateRef setPrivate
;
835 prefix
= SCPreferencesPathKeyCreateSets(NULL
);
836 path
= __SCPreferencesPathCreateUniqueChild_WithMoreSCFCompatibility(prefs
, prefix
);
837 if (path
== NULL
) path
= SCPreferencesPathCreateUniqueChild(prefs
, prefix
);
843 components
= CFStringCreateArrayBySeparatingStrings(NULL
, path
, CFSTR("/"));
844 setID
= CFArrayGetValueAtIndex(components
, 2);
845 setPrivate
= __SCNetworkSetCreatePrivate(NULL
, prefs
, setID
);
846 assert(setPrivate
!= NULL
);
847 CFRelease(components
);
849 // mark set as "new" (not yet established)
850 setPrivate
->established
= FALSE
;
852 // establish the set in the preferences
853 entity
= CFDictionaryCreate(NULL
,
855 &kCFTypeDictionaryKeyCallBacks
,
856 &kCFTypeDictionaryValueCallBacks
);
857 ok
= SCPreferencesPathSetValue(prefs
, path
, entity
);
861 CFRelease(setPrivate
);
865 if (setPrivate
!= NULL
) {
866 SC_log(LOG_DEBUG
, "SCNetworkSetCreate(): %@", setPrivate
);
869 return (SCNetworkSetRef
)setPrivate
;
874 _SCNetworkSetCreateDefault(SCPreferencesRef prefs
)
879 CFStringRef setName
= NULL
;
881 set
= SCNetworkSetCopyCurrent(prefs
);
883 SC_log(LOG_NOTICE
, "creating default set w/already existing set");
885 _SCErrorSet(kSCStatusKeyExists
);
889 // create a new ("Automatic") set
890 set
= SCNetworkSetCreate(prefs
);
892 SC_log(LOG_NOTICE
, "could not create \"new\" set: %s",
893 SCErrorString(SCError()));
897 bundle
= _SC_CFBundleGet();
898 if (bundle
!= NULL
) {
899 setName
= CFBundleCopyLocalizedString(bundle
,
900 CFSTR("DEFAULT_SET_NAME"),
905 ok
= SCNetworkSetSetName(set
, (setName
!= NULL
) ? setName
: CFSTR("Automatic"));
907 // if we could not save the new set's "name"
908 SC_log(LOG_NOTICE
, "could not save the new set's name: %s",
909 SCErrorString(SCError()));
913 ok
= SCNetworkSetSetCurrent(set
);
915 // if we could not make this the "current" set
916 SC_log(LOG_NOTICE
, "could not establish new set as current: %s",
917 SCErrorString(SCError()));
923 if (!ok
&& (set
!= NULL
)) {
924 SCNetworkSetRemove(set
);
928 if (setName
!= NULL
) CFRelease(setName
);
934 SCNetworkSetGetSetID(SCNetworkSetRef set
)
936 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
938 if (!isA_SCNetworkSet(set
)) {
939 _SCErrorSet(kSCStatusInvalidArgument
);
943 return setPrivate
->setID
;
948 SCNetworkSetGetName(SCNetworkSetRef set
)
951 CFDictionaryRef entity
;
953 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
955 if (!isA_SCNetworkSet(set
)) {
956 _SCErrorSet(kSCStatusInvalidArgument
);
960 if (setPrivate
->name
!= NULL
) {
961 return setPrivate
->name
;
964 path
= SCPreferencesPathKeyCreateSet(NULL
, setPrivate
->setID
);
965 entity
= SCPreferencesPathGetValue(setPrivate
->prefs
, path
);
968 if (isA_CFDictionary(entity
)) {
971 name
= CFDictionaryGetValue(entity
, kSCPropUserDefinedName
);
972 if (isA_CFString(name
)) {
973 setPrivate
->name
= CFRetain(name
);
977 bundle
= _SC_CFBundleGet();
978 if (bundle
!= NULL
) {
979 if (setPrivate
->name
!= NULL
) {
980 CFStringRef non_localized
;
982 non_localized
= _SC_CFBundleCopyNonLocalizedString(bundle
,
983 CFSTR("DEFAULT_SET_NAME"),
986 if (non_localized
!= NULL
) {
987 if (CFEqual(setPrivate
->name
, non_localized
)) {
988 CFStringRef localized
;
990 // if "Automatic", return localized name
991 localized
= CFBundleCopyLocalizedString(bundle
,
992 CFSTR("DEFAULT_SET_NAME"),
995 if (localized
!= NULL
) {
996 CFRelease(setPrivate
->name
);
997 setPrivate
->name
= localized
;
1001 CFRelease(non_localized
);
1006 return setPrivate
->name
;
1010 CFArrayRef
/* of serviceID CFStringRef's */
1011 SCNetworkSetGetServiceOrder(SCNetworkSetRef set
)
1013 CFDictionaryRef dict
;
1015 CFArrayRef serviceOrder
;
1016 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1018 if (!isA_SCNetworkSet(set
)) {
1019 _SCErrorSet(kSCStatusInvalidArgument
);
1023 path
= SCPreferencesPathKeyCreateSetNetworkGlobalEntity(NULL
, setPrivate
->setID
, kSCEntNetIPv4
);
1028 dict
= SCPreferencesPathGetValue(setPrivate
->prefs
, path
);
1030 if (!isA_CFDictionary(dict
)) {
1034 serviceOrder
= CFDictionaryGetValue(dict
, kSCPropNetServiceOrder
);
1035 serviceOrder
= isA_CFArray(serviceOrder
);
1037 return serviceOrder
;
1042 SCNetworkSetGetTypeID(void)
1044 pthread_once(&initialized
, __SCNetworkSetInitialize
); /* initialize runtime */
1045 return __kSCNetworkSetTypeID
;
1050 SCNetworkSetRemove(SCNetworkSetRef set
)
1052 CFStringRef currentPath
;
1055 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1057 if (!isA_SCNetworkSet(set
)) {
1058 _SCErrorSet(kSCStatusInvalidArgument
);
1062 currentPath
= SCPreferencesGetValue(setPrivate
->prefs
, kSCPrefCurrentSet
);
1063 path
= SCPreferencesPathKeyCreateSet(NULL
, setPrivate
->setID
);
1064 if (!isA_CFString(currentPath
) || !CFEqual(currentPath
, path
)) {
1065 ok
= SCPreferencesPathRemoveValue(setPrivate
->prefs
, path
);
1067 SC_log(LOG_DEBUG
, "SCNetworkSetRemove() failed, currently active: %@", setPrivate
->setID
);
1068 _SCErrorSet(kSCStatusInvalidArgument
);
1073 SC_log(LOG_DEBUG
, "SCNetworkSetRemove(): %@", set
);
1081 SCNetworkSetRemoveService(SCNetworkSetRef set
, SCNetworkServiceRef service
)
1083 SCNetworkInterfaceRef interface
;
1084 CFArrayRef interface_config
= NULL
;
1087 int sc_status
= kSCStatusOK
;
1088 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1089 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1091 if (!isA_SCNetworkSet(set
)) {
1092 _SCErrorSet(kSCStatusInvalidArgument
);
1096 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1097 _SCErrorSet(kSCStatusInvalidArgument
);
1101 // remove service from ServiceOrder
1102 _serviceOrder_remove(set
, service
);
1104 // get the [deep] interface configuration settings
1105 interface
= SCNetworkServiceGetInterface(service
);
1106 if (interface
!= NULL
) {
1107 interface_config
= __SCNetworkInterfaceCopyDeepConfiguration(set
, interface
);
1108 if (interface_config
!= NULL
) {
1109 // remove the interface configuration from all sets which contain this service.
1110 __SCNetworkInterfaceSetDeepConfiguration(set
, interface
, NULL
);
1114 // remove the link between "set" and the "service"
1115 path
= SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL
,
1117 servicePrivate
->serviceID
,
1119 ok
= SCPreferencesPathRemoveValue(setPrivate
->prefs
, path
);
1121 sc_status
= SCError(); // preserve the error
1125 // push the [deep] interface configuration [back] into all sets which contain the service.
1126 if (interface_config
!= NULL
) {
1127 __SCNetworkInterfaceSetDeepConfiguration(set
, interface
, interface_config
);
1128 CFRelease(interface_config
);
1132 SC_log(LOG_DEBUG
, "SCNetworkSetRemoveService(): %@, %@", set
, service
);
1134 _SCErrorSet(sc_status
);
1142 SCNetworkSetSetCurrent(SCNetworkSetRef set
)
1146 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1148 if (!isA_SCNetworkSet(set
)) {
1149 _SCErrorSet(kSCStatusInvalidArgument
);
1153 path
= SCPreferencesPathKeyCreateSet(NULL
, setPrivate
->setID
);
1154 ok
= SCPreferencesSetValue(setPrivate
->prefs
, kSCPrefCurrentSet
, path
);
1158 SC_log(LOG_DEBUG
, "SCNetworkSetSetCurrent(): %@", set
);
1166 SCNetworkSetSetName(SCNetworkSetRef set
, CFStringRef name
)
1168 CFBundleRef bundle
= NULL
;
1169 CFDictionaryRef entity
;
1170 CFStringRef localized
= NULL
;
1171 CFStringRef non_localized
= NULL
;
1174 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1176 if (!isA_SCNetworkSet(set
)) {
1177 _SCErrorSet(kSCStatusInvalidArgument
);
1181 if ((name
!= NULL
) && !isA_CFString(name
)) {
1182 _SCErrorSet(kSCStatusInvalidArgument
);
1186 // if known, compare against localized name
1189 bundle
= _SC_CFBundleGet();
1190 if (bundle
!= NULL
) {
1191 non_localized
= _SC_CFBundleCopyNonLocalizedString(bundle
,
1192 CFSTR("DEFAULT_SET_NAME"),
1195 if (non_localized
!= NULL
) {
1196 if (CFEqual(name
, non_localized
)) {
1197 localized
= CFBundleCopyLocalizedString(bundle
,
1198 CFSTR("DEFAULT_SET_NAME"),
1201 if (localized
!= NULL
) {
1209 #define PREVENT_DUPLICATE_SET_NAMES
1210 #ifdef PREVENT_DUPLICATE_SET_NAMES
1214 // ensure that each set is uniquely named
1216 sets
= SCNetworkSetCopyAll(setPrivate
->prefs
);
1221 n
= CFArrayGetCount(sets
);
1222 for (i
= 0; i
< n
; i
++) {
1223 CFStringRef otherID
;
1224 CFStringRef otherName
;
1225 SCNetworkSetRef set
= CFArrayGetValueAtIndex(sets
, i
);
1227 otherID
= SCNetworkSetGetSetID(set
);
1228 if (CFEqual(setPrivate
->setID
, otherID
)) {
1229 continue; // skip current set
1232 otherName
= SCNetworkSetGetName(set
);
1233 if ((otherName
!= NULL
) && CFEqual(name
, otherName
)) {
1234 // if "name" not unique
1236 _SCErrorSet(kSCStatusKeyExists
);
1243 #endif /* PREVENT_DUPLICATE_SET_NAMES */
1245 // if known, store non-localized name
1247 if ((name
!= NULL
) && (bundle
!= NULL
) && (non_localized
!= NULL
)) {
1248 if (localized
== NULL
) {
1249 localized
= CFBundleCopyLocalizedString(bundle
,
1250 CFSTR("DEFAULT_SET_NAME"),
1255 if (localized
!= NULL
) {
1256 if (CFEqual(name
, localized
)) {
1257 name
= non_localized
;
1262 // update the "name"
1264 path
= SCPreferencesPathKeyCreateSet(NULL
, setPrivate
->setID
);
1265 entity
= SCPreferencesPathGetValue(setPrivate
->prefs
, path
);
1266 if (isA_CFDictionary(entity
) ||
1267 ((entity
== NULL
) && (name
!= NULL
))) {
1268 CFMutableDictionaryRef newEntity
;
1270 if (entity
!= NULL
) {
1271 newEntity
= CFDictionaryCreateMutableCopy(NULL
, 0, entity
);
1273 newEntity
= CFDictionaryCreateMutable(NULL
,
1275 &kCFTypeDictionaryKeyCallBacks
,
1276 &kCFTypeDictionaryValueCallBacks
);
1279 CFDictionarySetValue(newEntity
, kSCPropUserDefinedName
, name
);
1281 CFDictionaryRemoveValue(newEntity
, kSCPropUserDefinedName
);
1283 ok
= SCPreferencesPathSetValue(setPrivate
->prefs
, path
, newEntity
);
1284 CFRelease(newEntity
);
1291 SC_log(LOG_DEBUG
, "SCNetworkSetSetName(): %@", set
);
1294 if (localized
!= NULL
) CFRelease(localized
);
1295 if (non_localized
!= NULL
) CFRelease(non_localized
);
1301 SCNetworkSetSetServiceOrder(SCNetworkSetRef set
, CFArrayRef newOrder
)
1303 CFDictionaryRef dict
;
1304 CFMutableDictionaryRef newDict
;
1307 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1309 if (!isA_SCNetworkSet(set
)) {
1310 _SCErrorSet(kSCStatusInvalidArgument
);
1314 if (isA_CFArray(newOrder
)) {
1316 CFIndex n
= CFArrayGetCount(newOrder
);
1318 for (i
= 0; i
< n
; i
++) {
1319 CFStringRef serviceID
;
1321 serviceID
= CFArrayGetValueAtIndex(newOrder
, i
);
1322 if (!isA_CFString(serviceID
)) {
1323 _SCErrorSet(kSCStatusInvalidArgument
);
1328 _SCErrorSet(kSCStatusInvalidArgument
);
1332 path
= SCPreferencesPathKeyCreateSetNetworkGlobalEntity(NULL
, setPrivate
->setID
, kSCEntNetIPv4
);
1337 dict
= SCPreferencesPathGetValue(setPrivate
->prefs
, path
);
1339 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
1341 newDict
= CFDictionaryCreateMutable(NULL
,
1343 &kCFTypeDictionaryKeyCallBacks
,
1344 &kCFTypeDictionaryValueCallBacks
);
1347 CFDictionarySetValue(newDict
, kSCPropNetServiceOrder
, newOrder
);
1348 ok
= SCPreferencesPathSetValue(setPrivate
->prefs
, path
, newDict
);
1357 #pragma mark SCNetworkSet SPIs
1361 add_supported_interfaces(CFMutableArrayRef interface_list
, SCNetworkInterfaceRef interface
)
1364 CFArrayRef interface_types
;
1367 interface_types
= SCNetworkInterfaceGetSupportedInterfaceTypes(interface
);
1368 n
= (interface_types
!= NULL
) ? CFArrayGetCount(interface_types
) : 0;
1369 for (i
= 0; i
< n
; i
++) {
1370 SCNetworkInterfaceRef parent
;
1371 CFStringRef interface_type
;
1373 interface_type
= CFArrayGetValueAtIndex(interface_types
, i
);
1374 parent
= SCNetworkInterfaceCreateWithInterface(interface
, interface_type
);
1375 if (parent
!= NULL
) {
1376 CFArrayAppendValue(interface_list
, parent
);
1385 static CFSetRef
/* of SCNetworkInterfaceRef's */
1386 copyExcludedInterfaces(SCPreferencesRef prefs
)
1388 CFMutableSetRef excluded
;
1389 CFArrayRef interfaces
;
1391 excluded
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
1393 #if !TARGET_OS_IPHONE
1394 // exclude Bond [member] interfaces
1395 interfaces
= SCBondInterfaceCopyAll(prefs
);
1396 if (interfaces
!= NULL
) {
1397 __SCBondInterfaceListCollectMembers(interfaces
, excluded
);
1398 CFRelease(interfaces
);
1400 #endif // !TARGET_OS_IPHONE
1402 // exclude Bridge [member] interfaces
1403 interfaces
= SCBridgeInterfaceCopyAll(prefs
);
1404 if (interfaces
!= NULL
) {
1405 __SCBridgeInterfaceListCollectMembers(interfaces
, excluded
);
1406 CFRelease(interfaces
);
1413 #if !TARGET_OS_IPHONE
1414 static SCBridgeInterfaceRef
1415 copyAutoBridgeInterface(SCPreferencesRef prefs
, CFStringRef bridgeName
)
1417 SCBridgeInterfaceRef bridge
= NULL
;
1418 CFArrayRef interfaces
;
1420 // exclude Bridge [member] interfaces
1421 interfaces
= SCBridgeInterfaceCopyAll(prefs
);
1422 if (interfaces
!= NULL
) {
1426 n
= CFArrayGetCount(interfaces
);
1427 for (i
= 0; i
< n
; i
++) {
1428 SCBridgeInterfaceRef interface
;
1429 CFStringRef name
= NULL
;
1430 CFDictionaryRef options
;
1432 interface
= CFArrayGetValueAtIndex(interfaces
, i
);
1433 options
= SCBridgeInterfaceGetOptions(interface
);
1434 if ((options
!= NULL
) &&
1435 CFDictionaryGetValueIfPresent(options
,
1437 (const void **)&name
) &&
1438 _SC_CFEqual(name
, bridgeName
)) {
1445 CFRelease(interfaces
);
1448 if (bridge
== NULL
) {
1449 bridge
= SCBridgeInterfaceCreate(prefs
);
1450 if (bridge
!= NULL
) {
1451 CFMutableDictionaryRef newOptions
;
1454 newOptions
= CFDictionaryCreateMutable(NULL
, 0,
1455 &kCFTypeDictionaryKeyCallBacks
,
1456 &kCFTypeDictionaryValueCallBacks
);
1457 CFDictionarySetValue(newOptions
, CFSTR("__AUTO__"), bridgeName
);
1458 ok
= SCBridgeInterfaceSetOptions(bridge
, newOptions
);
1459 CFRelease(newOptions
);
1469 #endif // !TARGET_OS_IPHONE
1473 copyServices(SCNetworkSetRef set
)
1475 CFArrayRef services
;
1476 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1478 // first, assume that we only want to add new services
1479 // for those interfaces that are not represented in the
1481 services
= SCNetworkSetCopyServices(set
);
1482 if ((services
!= NULL
) && setPrivate
->established
) {
1483 // but, if we are given an existing (or "established") set
1484 // than we only want to add new services for those interfaces
1485 // that are not represented in *any* set.
1486 CFRelease(services
);
1487 services
= SCNetworkServiceCopyAll(setPrivate
->prefs
);
1494 #if !TARGET_OS_IPHONE
1496 updateServices(CFArrayRef services
, SCNetworkInterfaceRef interface
)
1498 CFStringRef bsdName
;
1501 CFMutableArrayRef newServices
;
1503 if (services
== NULL
) {
1507 bsdName
= SCNetworkInterfaceGetBSDName(interface
);
1509 newServices
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1511 n
= CFArrayGetCount(services
);
1512 for (i
= 0; i
< n
; i
++) {
1513 SCNetworkInterfaceRef interface
;
1514 CFStringRef interfaceName
;
1515 SCNetworkServiceRef newService
;
1516 SCNetworkServiceRef service
;
1517 CFStringRef serviceID
;
1518 SCNetworkServicePrivateRef servicePrivate
;
1520 service
= CFArrayGetValueAtIndex(services
, i
);
1521 interface
= SCNetworkServiceGetInterface(service
);
1522 interfaceName
= SCNetworkInterfaceGetBSDName(interface
);
1523 if (!_SC_CFEqual(interfaceName
, bsdName
)) {
1524 // if not a match, retain
1525 CFArrayAppendValue(newServices
, service
);
1529 // if a match, update
1530 serviceID
= SCNetworkServiceGetServiceID(service
);
1531 servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1532 newService
= SCNetworkServiceCopy(servicePrivate
->prefs
, serviceID
);
1533 if (newService
!= NULL
) {
1534 CFArrayAppendValue(newServices
, newService
);
1535 CFRelease(newService
);
1541 #endif // !TARGET_OS_IPHONE
1544 static __inline__ Boolean
1545 skipInterface(SCNetworkInterfaceRef interface
)
1549 action
= _SCNetworkInterfaceGetConfigurationAction(interface
);
1550 if (isA_CFString(action
) &&
1551 CFEqual(action
, kSCNetworkInterfaceConfigurationActionValueNone
)) {
1560 _SCNetworkSetCompare(const void *val1
, const void *val2
, void *context
)
1562 #pragma unused(context)
1567 SCNetworkSetRef s1
= (SCNetworkSetRef
)val1
;
1568 SCNetworkSetRef s2
= (SCNetworkSetRef
)val2
;
1570 name1
= SCNetworkSetGetName(s1
);
1571 name2
= SCNetworkSetGetName(s2
);
1573 if (name1
!= NULL
) {
1574 if (name2
!= NULL
) {
1575 return CFStringCompare(name1
, name2
, 0);
1577 return kCFCompareLessThan
;
1581 if (name2
!= NULL
) {
1582 return kCFCompareGreaterThan
;
1585 id1
= SCNetworkSetGetSetID(s1
);
1586 id2
= SCNetworkSetGetSetID(s2
);
1587 return CFStringCompare(id1
, id2
, 0);
1592 __SCNetworkSetEstablishDefaultConfigurationForInterfaces(SCNetworkSetRef set
, CFArrayRef interfaces
, Boolean excludeHidden
)
1594 CFSetRef excluded
= NULL
;
1598 CFArrayRef services
;
1599 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1600 Boolean updated
= FALSE
;
1601 #if !TARGET_OS_IPHONE
1602 Boolean updatedIFs
= FALSE
;
1603 #endif // !TARGET_OS_IPHONE
1605 #if TARGET_OS_IPHONE
1606 CFArrayRef orphans
= NULL
;
1609 sets
= SCNetworkSetCopyAll(setPrivate
->prefs
);
1611 if (CFArrayGetCount(sets
) == 1) {
1612 services
= SCNetworkSetCopyServices(set
);
1613 if (services
!= NULL
) {
1614 n
= CFArrayGetCount(services
);
1615 CFRelease(services
);
1618 if ((n
== 0) && CFEqual(set
, CFArrayGetValueAtIndex(sets
, 0))) {
1619 // after a "Reset Network Settings" we need to find (and
1620 // add back) any VPN services that were orphaned.
1621 orphans
= SCNetworkServiceCopyAll(setPrivate
->prefs
);
1627 #endif // TARGET_OS_IPHONE
1629 // copy network services
1630 services
= copyServices(set
);
1632 // copy network interfaces to be excluded
1633 excluded
= copyExcludedInterfaces(setPrivate
->prefs
);
1635 #if !TARGET_OS_IPHONE
1636 // look for interfaces that should auto-magically be added
1637 // to an Ethernet bridge
1638 n
= (interfaces
!= NULL
) ? CFArrayGetCount(interfaces
) : 0;
1639 for (i
= 0; i
< n
; i
++) {
1640 SCBridgeInterfaceRef bridge
= NULL
;
1641 SCNetworkInterfaceRef interface
;
1643 interface
= CFArrayGetValueAtIndex(interfaces
, i
);
1645 if (excludeHidden
&& skipInterface(interface
)) {
1646 // if not auto-configure
1650 if ((excluded
!= NULL
)
1651 && CFSetContainsValue(excluded
, interface
)) {
1652 // if this interface is a member of a Bond or Bridge
1656 if (__SCNetworkServiceExistsForInterface(services
, interface
)) {
1657 // if this is not a new interface
1661 if (_SCNetworkInterfaceIsBuiltin(interface
) &&
1662 _SCNetworkInterfaceIsThunderbolt(interface
) &&
1663 !isA_SCBridgeInterface(interface
)) {
1664 // add built-in Thunderbolt interfaces to bridge
1665 bridge
= copyAutoBridgeInterface(setPrivate
->prefs
, CFSTR("thunderbolt-bridge"));
1668 if (bridge
!= NULL
) {
1669 CFIndex bridgeIndex
;
1671 CFMutableArrayRef newMembers
;
1672 CFMutableSetRef newExcluded
;
1673 CFMutableArrayRef newInterfaces
;
1674 CFArrayRef newServices
;
1676 // track the bridge interface (if it's in our list)
1677 bridgeIndex
= CFArrayGetFirstIndexOfValue(interfaces
,
1678 CFRangeMake(0, CFArrayGetCount(interfaces
)),
1681 // add new member interface
1682 members
= SCBridgeInterfaceGetMemberInterfaces(bridge
);
1683 if ((members
!= NULL
) && (CFArrayGetCount(members
) > 0)) {
1684 newMembers
= CFArrayCreateMutableCopy(NULL
, 0, members
);
1685 updated
= TRUE
; // if we're updating an existing bridge
1687 newMembers
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1689 CFArrayAppendValue(newMembers
, interface
);
1690 ok
= SCBridgeInterfaceSetMemberInterfaces(bridge
, newMembers
);
1691 CFRelease(newMembers
);
1693 SC_log(LOG_INFO
, "could not update bridge with \"%@\": %s",
1694 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
1695 SCErrorString(SCError()));
1700 // exclude the new member interface
1701 newExcluded
= CFSetCreateMutableCopy(NULL
, 0, excluded
);
1702 CFRelease(excluded
);
1703 CFSetAddValue(newExcluded
, interface
);
1704 excluded
= newExcluded
;
1706 // update the list of interfaces to include the [new or updated] bridge
1707 newInterfaces
= CFArrayCreateMutableCopy(NULL
, 0, interfaces
);
1708 if (bridgeIndex
!= kCFNotFound
) {
1709 CFArraySetValueAtIndex(newInterfaces
, bridgeIndex
, bridge
);
1711 CFArrayAppendValue(newInterfaces
, bridge
);
1714 CFRelease(interfaces
);
1716 interfaces
= newInterfaces
;
1719 // refresh [existing] services
1720 newServices
= updateServices(services
, bridge
);
1721 if (newServices
!= NULL
) {
1722 CFRelease(services
);
1723 services
= newServices
;
1729 #endif // !TARGET_OS_IPHONE
1731 n
= (interfaces
!= NULL
) ? CFArrayGetCount(interfaces
) : 0;
1732 for (i
= 0; i
< n
; i
++) {
1733 SCNetworkInterfaceRef interface
;
1734 CFMutableArrayRef interface_list
;
1736 interface
= CFArrayGetValueAtIndex(interfaces
, i
);
1738 if (excludeHidden
&& skipInterface(interface
)) {
1739 // if not auto-configure
1743 if ((excluded
!= NULL
)
1744 && CFSetContainsValue(excluded
, interface
)) {
1745 // if this interface is a member of a Bond or Bridge
1749 if (__SCNetworkServiceExistsForInterface(services
, interface
)) {
1750 // if this is not a new interface
1754 interface_list
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1755 CFArrayAppendValue(interface_list
, interface
);
1757 while (ok
&& (CFArrayGetCount(interface_list
) > 0)) {
1758 CFArrayRef protocol_types
;
1760 interface
= CFArrayGetValueAtIndex(interface_list
, 0);
1762 protocol_types
= SCNetworkInterfaceGetSupportedProtocolTypes(interface
);
1763 if ((protocol_types
!= NULL
) && (CFArrayGetCount(protocol_types
) > 0)) {
1764 SCNetworkServiceRef service
;
1766 service
= SCNetworkServiceCreate(setPrivate
->prefs
, interface
);
1767 if (service
== NULL
) {
1768 SC_log(LOG_ERR
, "could not create service for \"%@\": %s",
1769 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
1770 SCErrorString(SCError()));
1775 ok
= SCNetworkServiceEstablishDefaultConfiguration(service
);
1777 SC_log(LOG_ERR
, "could not estabish default configuration for \"%@\": %s",
1778 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
1779 SCErrorString(SCError()));
1780 SCNetworkServiceRemove(service
);
1785 ok
= SCNetworkSetAddService(set
, service
);
1787 SC_log(LOG_ERR
, "could not add service for \"%@\": %s",
1788 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
1789 SCErrorString(SCError()));
1790 SCNetworkServiceRemove(service
);
1798 add_supported_interfaces(interface_list
, interface
);
1803 CFArrayRemoveValueAtIndex(interface_list
, 0);
1805 CFRelease(interface_list
);
1807 #if !TARGET_OS_IPHONE
1808 if (updatedIFs
) CFRelease(interfaces
);
1809 #endif // !TARGET_OS_IPHONE
1810 if (services
!= NULL
) CFRelease(services
);
1811 if (excluded
!= NULL
) CFRelease(excluded
);
1813 #if TARGET_OS_IPHONE
1814 if (orphans
!= NULL
) {
1815 if (ok
&& updated
) {
1817 CFIndex n
= CFArrayGetCount(orphans
);
1819 for (i
= 0; i
< n
; i
++) {
1820 SCNetworkServiceRef service
;
1822 service
= CFArrayGetValueAtIndex(orphans
, i
);
1823 if (_SCNetworkServiceIsVPN(service
)) {
1824 ok
= SCNetworkSetAddService(set
, service
);
1834 #endif // TARGET_OS_IPHONE
1836 if (ok
&& !updated
) {
1837 // if no changes were made
1838 _SCErrorSet(kSCStatusOK
);
1846 SCNetworkSetEstablishDefaultConfiguration(SCNetworkSetRef set
)
1848 CFArrayRef interfaces
;
1849 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1850 Boolean updated
= FALSE
;
1852 if (!isA_SCNetworkSet(set
)) {
1853 _SCErrorSet(kSCStatusInvalidArgument
);
1857 interfaces
= _SCNetworkInterfaceCopyAllWithPreferences(setPrivate
->prefs
);
1858 if (interfaces
!= NULL
) {
1859 updated
= __SCNetworkSetEstablishDefaultConfigurationForInterfaces(set
, interfaces
, TRUE
);
1860 CFRelease(interfaces
);
1868 SCNetworkSetEstablishDefaultInterfaceConfiguration(SCNetworkSetRef set
, SCNetworkInterfaceRef interface
)
1870 CFArrayRef interfaces
;
1873 if (!isA_SCNetworkSet(set
)) {
1874 _SCErrorSet(kSCStatusInvalidArgument
);
1878 if (!isA_SCNetworkInterface(interface
)) {
1879 _SCErrorSet(kSCStatusInvalidArgument
);
1883 interfaces
= CFArrayCreate(NULL
, (const void **)&interface
, 1, &kCFTypeArrayCallBacks
);
1884 assert(interfaces
!= NULL
);
1885 updated
= __SCNetworkSetEstablishDefaultConfigurationForInterfaces(set
, interfaces
, FALSE
);
1886 CFRelease(interfaces
);
1893 SCNetworkSetCopySelectedVPNService(SCNetworkSetRef set
)
1897 SCNetworkServiceRef selected
= NULL
;
1898 CFArrayRef services
;
1899 CFMutableArrayRef services_vpn
= NULL
;
1901 if (!isA_SCNetworkSet(set
)) {
1902 _SCErrorSet(kSCStatusInvalidArgument
);
1906 services
= SCNetworkSetCopyServices(set
);
1907 if (services
!= NULL
) {
1908 n
= CFArrayGetCount(services
);
1909 for (i
= 0; i
< n
; i
++) {
1910 SCNetworkServiceRef service
;
1912 service
= CFArrayGetValueAtIndex(services
, i
);
1913 if (!SCNetworkServiceGetEnabled(service
)) {
1918 if (!_SCNetworkServiceIsVPN(service
)) {
1919 // if not VPN service
1923 if (services_vpn
== NULL
) {
1924 services_vpn
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1926 CFArrayAppendValue(services_vpn
, service
);
1929 CFRelease(services
);
1932 if (services_vpn
== NULL
) {
1933 // if no VPN services
1937 n
= CFArrayGetCount(services_vpn
);
1940 CFMutableArrayRef sorted
;
1942 order
= SCNetworkSetGetServiceOrder(set
);
1943 sorted
= CFArrayCreateMutableCopy(NULL
, 0, services_vpn
);
1944 CFArraySortValues(sorted
,
1945 CFRangeMake(0, CFArrayGetCount(sorted
)),
1946 _SCNetworkServiceCompare
,
1948 CFRelease(services_vpn
);
1949 services_vpn
= sorted
;
1952 #if TARGET_OS_IPHONE
1954 CFStringRef serviceID_prefs
;
1956 #define VPN_PREFERENCES CFSTR("com.apple.mobilevpn")
1957 #define VPN_SERVICE_ID CFSTR("activeVPNID")
1959 CFPreferencesAppSynchronize(VPN_PREFERENCES
);
1960 serviceID_prefs
= CFPreferencesCopyAppValue(VPN_SERVICE_ID
, VPN_PREFERENCES
);
1961 if (serviceID_prefs
!= NULL
) {
1962 for (i
= 0; i
< n
; i
++) {
1963 SCNetworkServiceRef service
;
1964 CFStringRef serviceID
;
1966 service
= CFArrayGetValueAtIndex(services_vpn
, i
);
1967 serviceID
= SCNetworkServiceGetServiceID(service
);
1968 if (CFEqual(serviceID
, serviceID_prefs
)) {
1976 CFRelease(serviceID_prefs
);
1979 #endif // TARGET_OS_IPHONE
1981 if (selected
== NULL
) {
1982 selected
= CFArrayGetValueAtIndex(services_vpn
, 0);
1986 CFRelease(services_vpn
);
1992 SCNetworkSetSetSelectedVPNService(SCNetworkSetRef set
, SCNetworkServiceRef service
)
1995 CFArrayRef services
;
1997 if (!isA_SCNetworkSet(set
)) {
1998 _SCErrorSet(kSCStatusInvalidArgument
);
2002 if (!isA_SCNetworkService(service
) || !_SCNetworkServiceIsVPN(service
)) {
2003 _SCErrorSet(kSCStatusInvalidArgument
);
2007 services
= SCNetworkSetCopyServices(set
);
2008 if (services
!= NULL
) {
2010 CFIndex n
= CFArrayGetCount(services
);
2012 if (!CFArrayContainsValue(services
, CFRangeMake(0, n
), service
)) {
2013 // if selected service not a member of the current set
2014 _SCErrorSet(kSCStatusInvalidArgument
);
2019 for (i
= 0; ok
&& (i
< n
); i
++) {
2020 SCNetworkServiceRef vpn
;
2022 vpn
= CFArrayGetValueAtIndex(services
, i
);
2023 if (!_SCNetworkServiceIsVPN(vpn
)) {
2024 // if not VPN service
2028 ok
= SCNetworkServiceSetEnabled(vpn
, CFEqual(service
, vpn
));
2034 if (services
!= NULL
) CFRelease(services
);
2040 _SCNetworkSetSetSetID(SCNetworkSetRef set
, CFStringRef newSetID
)
2042 SCNetworkSetRef currentSet
= NULL
;
2043 SCNetworkSetPrivateRef currentSetPrivate
= NULL
;
2044 CFDictionaryRef entity
;
2045 CFStringRef newPath
;
2047 CFStringRef oldPath
= NULL
;
2048 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
2049 Boolean updateCurrentSet
= FALSE
;
2051 if (!isA_SCNetworkSet(set
)) {
2052 _SCErrorSet(kSCStatusInvalidArgument
);
2056 if (!isA_CFString(newSetID
)) {
2057 _SCErrorSet(kSCStatusInvalidArgument
);
2061 // If newSetID is equal to current setID, our work is done
2062 if (CFEqual(newSetID
, setPrivate
->setID
)) {
2066 newPath
= SCPreferencesPathKeyCreateSet(NULL
, newSetID
);
2067 entity
= SCPreferencesPathGetValue(setPrivate
->prefs
, newPath
);
2068 if (isA_CFDictionary(entity
)) {
2069 // if the new set already exists
2070 _SCErrorSet(kSCStatusKeyExists
);
2074 oldPath
= SCPreferencesPathKeyCreateSet(NULL
, setPrivate
->setID
);
2075 entity
= SCPreferencesPathGetValue(setPrivate
->prefs
, oldPath
);
2076 if (!isA_CFDictionary(entity
)) {
2077 // if the set has already been removed
2078 _SCErrorSet(kSCStatusNoKey
);
2082 ok
= SCPreferencesPathSetValue(setPrivate
->prefs
, newPath
, entity
);
2087 ok
= SCPreferencesPathRemoveValue(setPrivate
->prefs
, oldPath
);
2092 // update current set (if needed)
2093 currentSet
= SCNetworkSetCopyCurrent(setPrivate
->prefs
);
2094 if (currentSet
!= NULL
) {
2095 currentSetPrivate
= (SCNetworkSetPrivateRef
)currentSet
;
2096 if (CFEqual(currentSetPrivate
->setID
, setPrivate
->setID
)) {
2097 updateCurrentSet
= TRUE
;
2099 CFRelease(currentSet
);
2102 SC_log(LOG_DEBUG
, "_SCNetworkSetSetID(): %@ --> %@", set
, newSetID
);
2104 // replace setID with new one
2106 CFRelease(setPrivate
->setID
);
2107 setPrivate
->setID
= newSetID
;
2109 if (updateCurrentSet
) {
2110 SCNetworkSetSetCurrent(set
);
2115 if (oldPath
!= NULL
) {
2118 if (newPath
!= NULL
) {