2 * Copyright (c) 2004-2007, 2009-2013 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 <SystemConfiguration/SystemConfiguration.h>
35 #include "SCNetworkConfigurationInternal.h"
36 #include <SystemConfiguration/SCValidation.h>
37 #include <SystemConfiguration/SCPrivate.h>
42 static CFStringRef
__SCNetworkSetCopyDescription (CFTypeRef cf
);
43 static void __SCNetworkSetDeallocate (CFTypeRef cf
);
44 static Boolean
__SCNetworkSetEqual (CFTypeRef cf1
, CFTypeRef cf2
);
45 static CFHashCode
__SCNetworkSetHash (CFTypeRef cf
);
48 static CFTypeID __kSCNetworkSetTypeID
= _kCFRuntimeNotATypeID
;
51 static const CFRuntimeClass __SCNetworkSetClass
= {
53 "SCNetworkSet", // className
56 __SCNetworkSetDeallocate
, // dealloc
57 __SCNetworkSetEqual
, // equal
58 __SCNetworkSetHash
, // hash
59 NULL
, // copyFormattingDesc
60 __SCNetworkSetCopyDescription
// copyDebugDesc
64 static pthread_once_t initialized
= PTHREAD_ONCE_INIT
;
68 __SCNetworkSetCopyDescription(CFTypeRef cf
)
70 CFAllocatorRef allocator
= CFGetAllocator(cf
);
71 CFMutableStringRef result
;
72 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)cf
;
74 result
= CFStringCreateMutable(allocator
, 0);
75 CFStringAppendFormat(result
, NULL
, CFSTR("<SCNetworkSet %p [%p]> {"), cf
, allocator
);
76 CFStringAppendFormat(result
, NULL
, CFSTR("id = %@"), setPrivate
->setID
);
77 CFStringAppendFormat(result
, NULL
, CFSTR(", prefs = %p"), setPrivate
->prefs
);
78 if (setPrivate
->name
!= NULL
) {
79 CFStringAppendFormat(result
, NULL
, CFSTR(", name = %@"), setPrivate
->name
);
81 CFStringAppendFormat(result
, NULL
, CFSTR("}"));
88 __SCNetworkSetDeallocate(CFTypeRef cf
)
90 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)cf
;
92 /* release resources */
94 CFRelease(setPrivate
->setID
);
95 CFRelease(setPrivate
->prefs
);
96 if (setPrivate
->name
!= NULL
)
97 CFRelease(setPrivate
->name
);
104 __SCNetworkSetEqual(CFTypeRef cf1
, CFTypeRef cf2
)
106 SCNetworkSetPrivateRef s1
= (SCNetworkSetPrivateRef
)cf1
;
107 SCNetworkSetPrivateRef s2
= (SCNetworkSetPrivateRef
)cf2
;
112 if (s1
->prefs
!= s2
->prefs
)
113 return FALSE
; // if not the same prefs
115 if (!CFEqual(s1
->setID
, s2
->setID
))
116 return FALSE
; // if not the same set identifier
123 __SCNetworkSetHash(CFTypeRef cf
)
125 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)cf
;
127 return CFHash(setPrivate
->setID
);
132 __SCNetworkSetInitialize(void)
134 __kSCNetworkSetTypeID
= _CFRuntimeRegisterClass(&__SCNetworkSetClass
);
139 static SCNetworkSetPrivateRef
140 __SCNetworkSetCreatePrivate(CFAllocatorRef allocator
,
141 SCPreferencesRef prefs
,
144 SCNetworkSetPrivateRef setPrivate
;
147 /* initialize runtime */
148 pthread_once(&initialized
, __SCNetworkSetInitialize
);
150 /* allocate target */
151 size
= sizeof(SCNetworkSetPrivate
) - sizeof(CFRuntimeBase
);
152 setPrivate
= (SCNetworkSetPrivateRef
)_CFRuntimeCreateInstance(allocator
,
153 __kSCNetworkSetTypeID
,
156 if (setPrivate
== NULL
) {
160 setPrivate
->setID
= CFStringCreateCopy(NULL
, setID
);
161 setPrivate
->prefs
= CFRetain(prefs
);
162 setPrivate
->name
= NULL
;
163 setPrivate
->established
= FALSE
; // "new" (not yet established) set
173 _serviceOrder(SCNetworkServiceRef service
)
175 SCNetworkInterfaceRef interface
;
177 interface
= SCNetworkServiceGetInterface(service
);
178 if ((interface
== NULL
) || _SCNetworkServiceIsVPN(service
)) {
179 return 100000; // if unknown or VPN interface, sort last
182 return __SCNetworkInterfaceOrder(interface
);
187 _serviceOrder_add(SCNetworkSetRef set
, SCNetworkServiceRef service
)
191 CFMutableArrayRef newOrder
;
193 CFStringRef serviceID
;
194 CFIndex serviceOrder
;
195 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
198 order
= SCNetworkSetGetServiceOrder(set
);
200 newOrder
= CFArrayCreateMutableCopy(NULL
, 0, order
);
202 newOrder
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
204 assert(newOrder
!= NULL
);
205 n
= CFArrayGetCount(newOrder
);
207 serviceID
= SCNetworkServiceGetServiceID(service
);
208 if (CFArrayContainsValue(newOrder
, CFRangeMake(0, n
), serviceID
)) {
209 // if serviceID already present
213 serviceOrder
= _serviceOrder(service
);
216 for (i
= 0; i
< n
; i
++) {
218 SCNetworkServiceRef slotService
;
219 CFStringRef slotServiceID
;
221 slotServiceID
= CFArrayGetValueAtIndex(newOrder
, i
);
222 if (!isA_CFString(slotServiceID
)) {
227 slotService
= SCNetworkServiceCopy(setPrivate
->prefs
, slotServiceID
);
228 if (slotService
== NULL
) {
229 // if serviceID not valid
233 slotOrder
= _serviceOrder(slotService
);
234 if (serviceOrder
>= slotOrder
) {
235 // add the service *after* this one
239 CFRelease(slotService
);
242 CFArrayInsertValueAtIndex(newOrder
, slot
, serviceID
);
243 (void) SCNetworkSetSetServiceOrder(set
, newOrder
);
254 _serviceOrder_remove(SCNetworkSetRef set
, SCNetworkServiceRef service
)
256 CFMutableArrayRef newOrder
;
258 CFStringRef serviceID
;
260 order
= SCNetworkSetGetServiceOrder(set
);
265 serviceID
= SCNetworkServiceGetServiceID(service
);
267 newOrder
= CFArrayCreateMutableCopy(NULL
, 0, order
);
271 i
= CFArrayGetFirstIndexOfValue(newOrder
,
272 CFRangeMake(0, CFArrayGetCount(newOrder
)),
274 if (i
== kCFNotFound
) {
278 CFArrayRemoveValueAtIndex(newOrder
, i
);
280 (void) SCNetworkSetSetServiceOrder(set
, newOrder
);
288 #pragma mark SCNetworkSet APIs
295 SCNetworkSetAddService(SCNetworkSetRef set
, SCNetworkServiceRef service
)
297 SCNetworkInterfaceRef interface
;
298 CFArrayRef interface_config
= NULL
;
302 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
303 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
305 if (!isA_SCNetworkSet(set
)) {
306 _SCErrorSet(kSCStatusInvalidArgument
);
310 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
311 _SCErrorSet(kSCStatusInvalidArgument
);
315 // make sure that we do not add an orphaned network service if its
316 // associated interface is a member of a bond or bridge.
317 interface
= SCNetworkServiceGetInterface(service
);
318 if ((interface
!= NULL
) &&
319 __SCNetworkInterfaceIsMember(servicePrivate
->prefs
, interface
)) {
320 _SCErrorSet(kSCStatusKeyExists
);
324 #define PREVENT_DUPLICATE_SERVICE_NAMES
325 #ifdef PREVENT_DUPLICATE_SERVICE_NAMES
328 name
= SCNetworkServiceGetName(service
);
332 services
= SCNetworkSetCopyServices(set
);
333 if (services
!= NULL
) {
337 n
= CFArrayGetCount(services
);
338 for (i
= 0; i
< n
; i
++) {
339 CFStringRef otherName
;
340 SCNetworkServiceRef otherService
;
342 otherService
= CFArrayGetValueAtIndex(services
, i
);
343 otherName
= SCNetworkServiceGetName(otherService
);
344 if ((otherName
!= NULL
) && CFEqual(name
, otherName
)) {
346 * if a service with the same "name" is
347 * already a member of the set.
350 _SCErrorSet(kSCStatusKeyExists
);
358 #endif // PREVENT_DUPLICATE_SERVICE_NAMES
360 //#define PREVENT_DUPLICATE_SETS
361 #ifdef PREVENT_DUPLICATE_SETS
364 // ensure that each service is only a member of ONE set
365 sets
= SCNetworkSetCopyAll(setPrivate
->prefs
);
370 n
= CFArrayGetCount(sets
);
371 for (i
= 0; i
< n
; i
++) {
376 set
= CFArrayGetValueAtIndex(sets
, i
);
377 services
= SCNetworkSetCopyServices(set
);
378 found
= CFArrayContainsValue(services
,
379 CFRangeMake(0, CFArrayGetCount(services
)),
385 _SCErrorSet(kSCStatusKeyExists
);
391 #endif /* PREVENT_DUPLICATE_SETS */
393 // get the [deep] interface configuration settings
394 interface
= SCNetworkServiceGetInterface(service
);
395 if (interface
!= NULL
) {
396 interface_config
= __SCNetworkInterfaceCopyDeepConfiguration(set
, interface
);
399 // create the link between "set" and the "service"
400 path
= SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL
, // allocator
401 setPrivate
->setID
, // set
402 servicePrivate
->serviceID
, // service
404 link
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
405 servicePrivate
->serviceID
, // service
407 ok
= SCPreferencesPathSetLink(setPrivate
->prefs
, path
, link
);
414 // push the [deep] interface configuration into all sets which contain this service.
415 if (interface
!= NULL
) {
416 __SCNetworkInterfaceSetDeepConfiguration(set
, interface
, interface_config
);
419 // add service to ServiceOrder
420 _serviceOrder_add(set
, service
);
422 // mark set as no longer "new"
423 setPrivate
->established
= TRUE
;
427 if (interface_config
!= NULL
) CFRelease(interface_config
);
433 SCNetworkSetCopy(SCPreferencesRef prefs
, CFStringRef setID
)
435 CFDictionaryRef entity
;
437 SCNetworkSetPrivateRef setPrivate
;
439 if (!isA_CFString(setID
)) {
440 _SCErrorSet(kSCStatusInvalidArgument
);
444 path
= SCPreferencesPathKeyCreateSet(NULL
, setID
);
445 entity
= SCPreferencesPathGetValue(prefs
, path
);
448 if (!isA_CFDictionary(entity
)) {
449 _SCErrorSet(kSCStatusNoKey
);
453 setPrivate
= __SCNetworkSetCreatePrivate(NULL
, prefs
, setID
);
454 assert(setPrivate
!= NULL
);
456 // mark set as "old" (already established)
457 setPrivate
->established
= TRUE
;
459 return (SCNetworkSetRef
)setPrivate
;
464 SCNetworkSetContainsInterface(SCNetworkSetRef set
, SCNetworkInterfaceRef interface
)
466 Boolean found
= FALSE
;
469 services
= SCNetworkSetCopyServices(set
);
470 if (services
!= NULL
) {
471 found
= __SCNetworkServiceExistsForInterface(services
, interface
);
479 CFArrayRef
/* of SCNetworkSetRef's */
480 SCNetworkSetCopyAll(SCPreferencesRef prefs
)
482 CFMutableArrayRef array
;
485 CFDictionaryRef sets
;
487 path
= SCPreferencesPathKeyCreateSets(NULL
);
488 sets
= SCPreferencesPathGetValue(prefs
, path
);
491 if ((sets
!= NULL
) && !isA_CFDictionary(sets
)) {
495 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
497 n
= (sets
!= NULL
) ? CFDictionaryGetCount(sets
) : 0;
500 const void * keys_q
[N_QUICK
];
501 const void ** keys
= keys_q
;
502 const void * vals_q
[N_QUICK
];
503 const void ** vals
= vals_q
;
505 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
506 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
507 vals
= CFAllocatorAllocate(NULL
, n
* sizeof(CFPropertyListRef
), 0);
509 CFDictionaryGetKeysAndValues(sets
, keys
, vals
);
510 for (i
= 0; i
< n
; i
++) {
511 SCNetworkSetPrivateRef setPrivate
;
513 if (!isA_CFDictionary(vals
[i
])) {
516 CFSTR("SCNetworkSetCopyAll(): error w/set \"%@\"\n"),
521 setPrivate
= __SCNetworkSetCreatePrivate(NULL
, prefs
, keys
[i
]);
522 assert(setPrivate
!= NULL
);
524 // mark set as "old" (already established)
525 setPrivate
->established
= TRUE
;
527 CFArrayAppendValue(array
, (SCNetworkSetRef
)setPrivate
);
528 CFRelease(setPrivate
);
530 if (keys
!= keys_q
) {
531 CFAllocatorDeallocate(NULL
, keys
);
532 CFAllocatorDeallocate(NULL
, vals
);
540 CFArrayRef
/* of SCNetworkInterfaceRef's */
541 SCNetworkSetCopyAvailableInterfaces(SCNetworkSetRef set
)
543 CFMutableArrayRef available
;
544 CFMutableSetRef excluded
= NULL
;
546 CFArrayRef interfaces
;
548 int n_exclusions
= 0;
549 SCPreferencesRef prefs
;
550 SCNetworkSetPrivateRef setPrivate
;
552 setPrivate
= (SCNetworkSetPrivateRef
)set
;
553 prefs
= setPrivate
->prefs
;
555 interfaces
= _SCNetworkInterfaceCopyAllWithPreferences(prefs
);
556 n_interfaces
= CFArrayGetCount(interfaces
);
557 if (n_interfaces
== 0) {
562 CFArrayRef bridges
= NULL
;
564 excluded
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
566 #if !TARGET_OS_IPHONE
567 CFArrayRef bonds
= NULL
;
569 bonds
= SCBondInterfaceCopyAll(prefs
);
571 __SCBondInterfaceListCollectMembers(bonds
, excluded
);
574 #endif /* !TARGET_OS_IPHONE */
576 bridges
= SCBridgeInterfaceCopyAll(prefs
);
577 if (bridges
!= NULL
) {
578 __SCBridgeInterfaceListCollectMembers(bridges
, excluded
);
582 n_exclusions
= CFSetGetCount(excluded
);
585 if (n_exclusions
== 0) {
586 if (excluded
!= NULL
) {
593 available
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
595 for (i
= 0; i
< n_interfaces
; i
++) {
596 SCNetworkInterfaceRef interface
;
598 interface
= CFArrayGetValueAtIndex(interfaces
, i
);
599 if (CFSetContainsValue(excluded
, interface
)) {
604 CFArrayAppendValue(available
, interface
);
607 CFRelease(interfaces
);
615 SCNetworkSetCopyCurrent(SCPreferencesRef prefs
)
617 CFArrayRef components
;
618 CFStringRef currentID
;
619 SCNetworkSetPrivateRef setPrivate
= NULL
;
621 currentID
= SCPreferencesGetValue(prefs
, kSCPrefCurrentSet
);
622 if (!isA_CFString(currentID
)) {
626 components
= CFStringCreateArrayBySeparatingStrings(NULL
, currentID
, CFSTR("/"));
627 if (CFArrayGetCount(components
) == 3) {
631 setID
= CFArrayGetValueAtIndex(components
, 2);
632 path
= SCPreferencesPathKeyCreateSet(NULL
, setID
);
633 if (CFEqual(path
, currentID
)) {
634 setPrivate
= __SCNetworkSetCreatePrivate(NULL
, prefs
, setID
);
635 assert(setPrivate
!= NULL
);
637 // mark set as "old" (already established)
638 setPrivate
->established
= TRUE
;
640 SCLog(TRUE
, LOG_ERR
, CFSTR("SCNetworkSetCopyCurrent(): preferences are non-conformant"));
644 CFRelease(components
);
646 return (SCNetworkSetRef
)setPrivate
;
650 CFArrayRef
/* of SCNetworkServiceRef's */
651 SCNetworkSetCopyServices(SCNetworkSetRef set
)
653 CFMutableArrayRef array
;
654 CFDictionaryRef dict
;
657 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
659 if (!isA_SCNetworkSet(set
)) {
660 _SCErrorSet(kSCStatusInvalidArgument
);
664 path
= SCPreferencesPathKeyCreateSetNetworkService(NULL
, setPrivate
->setID
, NULL
);
665 dict
= SCPreferencesPathGetValue(setPrivate
->prefs
, path
);
667 if ((dict
!= NULL
) && !isA_CFDictionary(dict
)) {
671 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
673 n
= (dict
!= NULL
) ? CFDictionaryGetCount(dict
) : 0;
676 const void * keys_q
[N_QUICK
];
677 const void ** keys
= keys_q
;
679 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
680 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
682 CFDictionaryGetKeysAndValues(dict
, keys
, NULL
);
683 for (i
= 0; i
< n
; i
++) {
684 CFArrayRef components
;
687 path
= SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL
,
689 (CFStringRef
)keys
[i
],
691 link
= SCPreferencesPathGetLink(setPrivate
->prefs
, path
);
696 CFSTR("SCNetworkSetCopyServices(): service \"%@\" for set \"%@\" is not a link\n"),
699 continue; // if the service is not a link
702 components
= CFStringCreateArrayBySeparatingStrings(NULL
, link
, CFSTR("/"));
703 if (CFArrayGetCount(components
) == 3) {
704 CFStringRef serviceID
;
706 serviceID
= CFArrayGetValueAtIndex(components
, 2);
707 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
708 serviceID
, // service
710 if (CFEqual(path
, link
)) {
711 SCNetworkServicePrivateRef servicePrivate
;
713 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
,
717 CFArrayAppendValue(array
, (SCNetworkServiceRef
)servicePrivate
);
718 CFRelease(servicePrivate
);
722 CFRelease(components
);
724 if (keys
!= keys_q
) {
725 CFAllocatorDeallocate(NULL
, keys
);
734 SCNetworkSetCreate(SCPreferencesRef prefs
)
736 CFArrayRef components
;
737 CFDictionaryRef entity
;
742 SCNetworkSetPrivateRef setPrivate
;
744 prefix
= SCPreferencesPathKeyCreateSets(NULL
);
745 path
= __SCPreferencesPathCreateUniqueChild_WithMoreSCFCompatibility(prefs
, prefix
);
746 if (path
== NULL
) path
= SCPreferencesPathCreateUniqueChild(prefs
, prefix
);
752 components
= CFStringCreateArrayBySeparatingStrings(NULL
, path
, CFSTR("/"));
753 setID
= CFArrayGetValueAtIndex(components
, 2);
754 setPrivate
= __SCNetworkSetCreatePrivate(NULL
, prefs
, setID
);
755 assert(setPrivate
!= NULL
);
756 CFRelease(components
);
758 // mark set as "new" (not yet established)
759 setPrivate
->established
= FALSE
;
761 // establish the set in the preferences
762 entity
= CFDictionaryCreate(NULL
,
764 &kCFTypeDictionaryKeyCallBacks
,
765 &kCFTypeDictionaryValueCallBacks
);
766 ok
= SCPreferencesPathSetValue(prefs
, path
, entity
);
770 CFRelease(setPrivate
);
774 return (SCNetworkSetRef
)setPrivate
;
779 SCNetworkSetGetSetID(SCNetworkSetRef set
)
781 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
783 if (!isA_SCNetworkSet(set
)) {
784 _SCErrorSet(kSCStatusInvalidArgument
);
788 return setPrivate
->setID
;
793 SCNetworkSetGetName(SCNetworkSetRef set
)
796 CFDictionaryRef entity
;
798 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
800 if (!isA_SCNetworkSet(set
)) {
801 _SCErrorSet(kSCStatusInvalidArgument
);
805 if (setPrivate
->name
!= NULL
) {
806 return setPrivate
->name
;
809 path
= SCPreferencesPathKeyCreateSet(NULL
, setPrivate
->setID
);
810 entity
= SCPreferencesPathGetValue(setPrivate
->prefs
, path
);
813 if (isA_CFDictionary(entity
)) {
816 name
= CFDictionaryGetValue(entity
, kSCPropUserDefinedName
);
817 if (isA_CFString(name
)) {
818 setPrivate
->name
= CFRetain(name
);
822 bundle
= _SC_CFBundleGet();
823 if (bundle
!= NULL
) {
824 if (setPrivate
->name
!= NULL
) {
825 CFStringRef non_localized
;
827 non_localized
= _SC_CFBundleCopyNonLocalizedString(bundle
,
828 CFSTR("DEFAULT_SET_NAME"),
831 if (non_localized
!= NULL
) {
832 if (CFEqual(setPrivate
->name
, non_localized
)) {
833 CFStringRef localized
;
835 // if "Automatic", return localized name
836 localized
= CFBundleCopyLocalizedString(bundle
,
837 CFSTR("DEFAULT_SET_NAME"),
840 if (localized
!= NULL
) {
841 CFRelease(setPrivate
->name
);
842 setPrivate
->name
= localized
;
846 CFRelease(non_localized
);
851 return setPrivate
->name
;
855 CFArrayRef
/* of serviceID CFStringRef's */
856 SCNetworkSetGetServiceOrder(SCNetworkSetRef set
)
858 CFDictionaryRef dict
;
860 CFArrayRef serviceOrder
;
861 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
863 if (!isA_SCNetworkSet(set
)) {
864 _SCErrorSet(kSCStatusInvalidArgument
);
868 path
= SCPreferencesPathKeyCreateSetNetworkGlobalEntity(NULL
, setPrivate
->setID
, kSCEntNetIPv4
);
873 dict
= SCPreferencesPathGetValue(setPrivate
->prefs
, path
);
875 if (!isA_CFDictionary(dict
)) {
879 serviceOrder
= CFDictionaryGetValue(dict
, kSCPropNetServiceOrder
);
880 serviceOrder
= isA_CFArray(serviceOrder
);
887 SCNetworkSetGetTypeID(void)
889 pthread_once(&initialized
, __SCNetworkSetInitialize
); /* initialize runtime */
890 return __kSCNetworkSetTypeID
;
895 SCNetworkSetRemove(SCNetworkSetRef set
)
897 CFStringRef currentPath
;
900 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
902 if (!isA_SCNetworkSet(set
)) {
903 _SCErrorSet(kSCStatusInvalidArgument
);
907 currentPath
= SCPreferencesGetValue(setPrivate
->prefs
, kSCPrefCurrentSet
);
908 path
= SCPreferencesPathKeyCreateSet(NULL
, setPrivate
->setID
);
909 if (!isA_CFString(currentPath
) || !CFEqual(currentPath
, path
)) {
910 ok
= SCPreferencesPathRemoveValue(setPrivate
->prefs
, path
);
912 _SCErrorSet(kSCStatusInvalidArgument
);
921 SCNetworkSetRemoveService(SCNetworkSetRef set
, SCNetworkServiceRef service
)
923 SCNetworkInterfaceRef interface
;
924 CFArrayRef interface_config
= NULL
;
927 int sc_status
= kSCStatusOK
;
928 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
929 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
931 if (!isA_SCNetworkSet(set
)) {
932 _SCErrorSet(kSCStatusInvalidArgument
);
936 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
937 _SCErrorSet(kSCStatusInvalidArgument
);
941 // remove service from ServiceOrder
942 _serviceOrder_remove(set
, service
);
944 // get the [deep] interface configuration settings
945 interface
= SCNetworkServiceGetInterface(service
);
946 if (interface
!= NULL
) {
947 interface_config
= __SCNetworkInterfaceCopyDeepConfiguration(set
, interface
);
948 if (interface_config
!= NULL
) {
949 // remove the interface configuration from all sets which contain this service.
950 __SCNetworkInterfaceSetDeepConfiguration(set
, interface
, NULL
);
954 // remove the link between "set" and the "service"
955 path
= SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL
,
957 servicePrivate
->serviceID
,
959 ok
= SCPreferencesPathRemoveValue(setPrivate
->prefs
, path
);
961 sc_status
= SCError(); // preserve the error
965 // push the [deep] interface configuration [back] into all sets which contain the service.
966 if (interface_config
!= NULL
) {
967 __SCNetworkInterfaceSetDeepConfiguration(set
, interface
, interface_config
);
970 if (interface_config
!= NULL
) CFRelease(interface_config
);
972 _SCErrorSet(sc_status
);
979 SCNetworkSetSetCurrent(SCNetworkSetRef set
)
983 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
985 if (!isA_SCNetworkSet(set
)) {
986 _SCErrorSet(kSCStatusInvalidArgument
);
990 path
= SCPreferencesPathKeyCreateSet(NULL
, setPrivate
->setID
);
991 ok
= SCPreferencesSetValue(setPrivate
->prefs
, kSCPrefCurrentSet
, path
);
998 SCNetworkSetSetName(SCNetworkSetRef set
, CFStringRef name
)
1000 CFBundleRef bundle
= NULL
;
1001 CFDictionaryRef entity
;
1002 CFStringRef localized
= NULL
;
1003 CFStringRef non_localized
= NULL
;
1006 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1008 if (!isA_SCNetworkSet(set
)) {
1009 _SCErrorSet(kSCStatusInvalidArgument
);
1013 if ((name
!= NULL
) && !isA_CFString(name
)) {
1014 _SCErrorSet(kSCStatusInvalidArgument
);
1018 // if known, compare against localized name
1021 bundle
= _SC_CFBundleGet();
1022 if (bundle
!= NULL
) {
1023 non_localized
= _SC_CFBundleCopyNonLocalizedString(bundle
,
1024 CFSTR("DEFAULT_SET_NAME"),
1027 if (non_localized
!= NULL
) {
1028 if (CFEqual(name
, non_localized
)) {
1029 localized
= CFBundleCopyLocalizedString(bundle
,
1030 CFSTR("DEFAULT_SET_NAME"),
1033 if (localized
!= NULL
) {
1041 #define PREVENT_DUPLICATE_SET_NAMES
1042 #ifdef PREVENT_DUPLICATE_SET_NAMES
1046 // ensure that each set is uniquely named
1048 sets
= SCNetworkSetCopyAll(setPrivate
->prefs
);
1053 n
= CFArrayGetCount(sets
);
1054 for (i
= 0; i
< n
; i
++) {
1055 CFStringRef otherID
;
1056 CFStringRef otherName
;
1057 SCNetworkSetRef set
= CFArrayGetValueAtIndex(sets
, i
);
1059 otherID
= SCNetworkSetGetSetID(set
);
1060 if (CFEqual(setPrivate
->setID
, otherID
)) {
1061 continue; // skip current set
1064 otherName
= SCNetworkSetGetName(set
);
1065 if ((otherName
!= NULL
) && CFEqual(name
, otherName
)) {
1066 // if "name" not unique
1068 _SCErrorSet(kSCStatusKeyExists
);
1075 #endif /* PREVENT_DUPLICATE_SET_NAMES */
1077 // if known, store non-localized name
1079 if ((name
!= NULL
) && (bundle
!= NULL
) && (non_localized
!= NULL
)) {
1080 if (localized
== NULL
) {
1081 localized
= CFBundleCopyLocalizedString(bundle
,
1082 CFSTR("DEFAULT_SET_NAME"),
1087 if (localized
!= NULL
) {
1088 if (CFEqual(name
, localized
)) {
1089 name
= non_localized
;
1094 // update the "name"
1096 path
= SCPreferencesPathKeyCreateSet(NULL
, setPrivate
->setID
);
1097 entity
= SCPreferencesPathGetValue(setPrivate
->prefs
, path
);
1098 if (isA_CFDictionary(entity
) ||
1099 ((entity
== NULL
) && (name
!= NULL
))) {
1100 CFMutableDictionaryRef newEntity
;
1102 if (entity
!= NULL
) {
1103 newEntity
= CFDictionaryCreateMutableCopy(NULL
, 0, entity
);
1105 newEntity
= CFDictionaryCreateMutable(NULL
,
1107 &kCFTypeDictionaryKeyCallBacks
,
1108 &kCFTypeDictionaryValueCallBacks
);
1111 CFDictionarySetValue(newEntity
, kSCPropUserDefinedName
, name
);
1113 CFDictionaryRemoveValue(newEntity
, kSCPropUserDefinedName
);
1115 ok
= SCPreferencesPathSetValue(setPrivate
->prefs
, path
, newEntity
);
1116 CFRelease(newEntity
);
1122 if (localized
!= NULL
) CFRelease(localized
);
1123 if (non_localized
!= NULL
) CFRelease(non_localized
);
1129 SCNetworkSetSetServiceOrder(SCNetworkSetRef set
, CFArrayRef newOrder
)
1131 CFDictionaryRef dict
;
1132 CFMutableDictionaryRef newDict
;
1135 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1137 if (!isA_SCNetworkSet(set
)) {
1138 _SCErrorSet(kSCStatusInvalidArgument
);
1142 if (isA_CFArray(newOrder
)) {
1144 CFIndex n
= CFArrayGetCount(newOrder
);
1146 for (i
= 0; i
< n
; i
++) {
1147 CFStringRef serviceID
;
1149 serviceID
= CFArrayGetValueAtIndex(newOrder
, i
);
1150 if (!isA_CFString(serviceID
)) {
1151 _SCErrorSet(kSCStatusInvalidArgument
);
1156 _SCErrorSet(kSCStatusInvalidArgument
);
1160 path
= SCPreferencesPathKeyCreateSetNetworkGlobalEntity(NULL
, setPrivate
->setID
, kSCEntNetIPv4
);
1165 dict
= SCPreferencesPathGetValue(setPrivate
->prefs
, path
);
1167 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
1169 newDict
= CFDictionaryCreateMutable(NULL
,
1171 &kCFTypeDictionaryKeyCallBacks
,
1172 &kCFTypeDictionaryValueCallBacks
);
1175 CFDictionarySetValue(newDict
, kSCPropNetServiceOrder
, newOrder
);
1176 ok
= SCPreferencesPathSetValue(setPrivate
->prefs
, path
, newDict
);
1185 #pragma mark SCNetworkSet SPIs
1189 add_supported_interfaces(CFMutableArrayRef interface_list
, SCNetworkInterfaceRef interface
)
1192 CFArrayRef interface_types
;
1195 interface_types
= SCNetworkInterfaceGetSupportedInterfaceTypes(interface
);
1196 n
= (interface_types
!= NULL
) ? CFArrayGetCount(interface_types
) : 0;
1197 for (i
= 0; i
< n
; i
++) {
1198 SCNetworkInterfaceRef parent
;
1199 CFStringRef interface_type
;
1201 interface_type
= CFArrayGetValueAtIndex(interface_types
, i
);
1202 parent
= SCNetworkInterfaceCreateWithInterface(interface
, interface_type
);
1203 if (parent
!= NULL
) {
1204 CFArrayAppendValue(interface_list
, parent
);
1213 static CFSetRef
/* of SCNetworkInterfaceRef's */
1214 copyExcludedInterfaces(SCPreferencesRef prefs
)
1216 CFMutableSetRef excluded
;
1217 CFArrayRef interfaces
;
1219 excluded
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
1221 #if !TARGET_OS_IPHONE
1222 // exclude Bond [member] interfaces
1223 interfaces
= SCBondInterfaceCopyAll(prefs
);
1224 if (interfaces
!= NULL
) {
1225 __SCBondInterfaceListCollectMembers(interfaces
, excluded
);
1226 CFRelease(interfaces
);
1228 #endif // !TARGET_OS_IPHONE
1230 // exclude Bridge [member] interfaces
1231 interfaces
= SCBridgeInterfaceCopyAll(prefs
);
1232 if (interfaces
!= NULL
) {
1233 __SCBridgeInterfaceListCollectMembers(interfaces
, excluded
);
1234 CFRelease(interfaces
);
1241 #if !TARGET_OS_IPHONE
1242 static SCBridgeInterfaceRef
1243 copyAutoBridgeInterface(SCPreferencesRef prefs
, CFStringRef bridgeName
)
1245 SCBridgeInterfaceRef bridge
= NULL
;
1246 CFArrayRef interfaces
;
1248 // exclude Bridge [member] interfaces
1249 interfaces
= SCBridgeInterfaceCopyAll(prefs
);
1250 if (interfaces
!= NULL
) {
1254 n
= CFArrayGetCount(interfaces
);
1255 for (i
= 0; i
< n
; i
++) {
1256 SCBridgeInterfaceRef interface
;
1257 CFStringRef name
= NULL
;
1258 CFDictionaryRef options
;
1260 interface
= CFArrayGetValueAtIndex(interfaces
, i
);
1261 options
= SCBridgeInterfaceGetOptions(interface
);
1262 if ((options
!= NULL
) &&
1263 CFDictionaryGetValueIfPresent(options
,
1265 (const void **)&name
) &&
1266 _SC_CFEqual(name
, bridgeName
)) {
1273 CFRelease(interfaces
);
1276 if (bridge
== NULL
) {
1277 bridge
= SCBridgeInterfaceCreate(prefs
);
1278 if (bridge
!= NULL
) {
1279 CFMutableDictionaryRef newOptions
;
1282 newOptions
= CFDictionaryCreateMutable(NULL
, 0,
1283 &kCFTypeDictionaryKeyCallBacks
,
1284 &kCFTypeDictionaryValueCallBacks
);
1285 CFDictionarySetValue(newOptions
, CFSTR("__AUTO__"), bridgeName
);
1286 ok
= SCBridgeInterfaceSetOptions(bridge
, newOptions
);
1287 CFRelease(newOptions
);
1297 #endif // !TARGET_OS_IPHONE
1301 copyServices(SCNetworkSetRef set
)
1303 CFArrayRef services
;
1304 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1306 // first, assume that we only want to add new services
1307 // for those interfaces that are not represented in the
1309 services
= SCNetworkSetCopyServices(set
);
1310 if ((services
!= NULL
) && setPrivate
->established
) {
1311 // but, if we are given an existing (or "established") set
1312 // than we only want to add new services for those interfaces
1313 // that are not represented in *any* set.
1314 CFRelease(services
);
1315 services
= SCNetworkServiceCopyAll(setPrivate
->prefs
);
1322 #if !TARGET_OS_IPHONE
1324 updateServices(CFArrayRef services
, SCNetworkInterfaceRef interface
)
1326 CFStringRef bsdName
;
1329 CFMutableArrayRef newServices
;
1331 if (services
== NULL
) {
1335 bsdName
= SCNetworkInterfaceGetBSDName(interface
);
1337 newServices
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1339 n
= CFArrayGetCount(services
);
1340 for (i
= 0; i
< n
; i
++) {
1341 SCNetworkInterfaceRef interface
;
1342 CFStringRef interfaceName
;
1343 SCNetworkServiceRef newService
;
1344 SCNetworkServiceRef service
;
1345 CFStringRef serviceID
;
1346 SCNetworkServicePrivateRef servicePrivate
;
1348 service
= CFArrayGetValueAtIndex(services
, i
);
1349 interface
= SCNetworkServiceGetInterface(service
);
1350 interfaceName
= SCNetworkInterfaceGetBSDName(interface
);
1351 if (!_SC_CFEqual(interfaceName
, bsdName
)) {
1352 // if not a match, retain
1353 CFArrayAppendValue(newServices
, service
);
1357 // if a match, update
1358 serviceID
= SCNetworkServiceGetServiceID(service
);
1359 servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1360 newService
= SCNetworkServiceCopy(servicePrivate
->prefs
, serviceID
);
1361 if (newService
!= NULL
) {
1362 CFArrayAppendValue(newServices
, newService
);
1363 CFRelease(newService
);
1369 #endif // !TARGET_OS_IPHONE
1373 __SCNetworkSetEstablishDefaultConfigurationForInterfaces(SCNetworkSetRef set
, CFArrayRef interfaces
)
1375 CFSetRef excluded
= NULL
;
1379 CFArrayRef services
;
1380 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1381 Boolean updated
= FALSE
;
1382 Boolean updatedIFs
= FALSE
;
1384 #if TARGET_OS_IPHONE
1385 CFArrayRef orphans
= NULL
;
1388 sets
= SCNetworkSetCopyAll(setPrivate
->prefs
);
1390 if (CFArrayGetCount(sets
) == 1) {
1391 services
= SCNetworkSetCopyServices(set
);
1392 if (services
!= NULL
) {
1393 n
= CFArrayGetCount(services
);
1394 CFRelease(services
);
1397 if ((n
== 0) && CFEqual(set
, CFArrayGetValueAtIndex(sets
, 0))) {
1398 // after a "Reset Network Settings" we need to find (and
1399 // add back) any VPN services that were orphaned.
1400 orphans
= SCNetworkServiceCopyAll(setPrivate
->prefs
);
1406 #endif // TARGET_OS_IPHONE
1408 // copy network services
1409 services
= copyServices(set
);
1411 // copy network interfaces to be excluded
1412 excluded
= copyExcludedInterfaces(setPrivate
->prefs
);
1414 #if !TARGET_OS_IPHONE
1415 // look for interfaces that should auto-magically be added
1416 // to an Ethernet bridge
1417 n
= (interfaces
!= NULL
) ? CFArrayGetCount(interfaces
) : 0;
1418 for (i
= 0; i
< n
; i
++) {
1419 SCBridgeInterfaceRef bridge
= NULL
;
1420 SCNetworkInterfaceRef interface
;
1422 interface
= CFArrayGetValueAtIndex(interfaces
, i
);
1423 if ((excluded
!= NULL
)
1424 && CFSetContainsValue(excluded
, interface
)) {
1425 // if this interface is a member of a Bond or Bridge
1429 if (__SCNetworkServiceExistsForInterface(services
, interface
)) {
1430 // if this is not a new interface
1434 if (_SCNetworkInterfaceIsBuiltin(interface
) &&
1435 _SCNetworkInterfaceIsThunderbolt(interface
) &&
1436 !isA_SCBridgeInterface(interface
)) {
1437 // add built-in Thunderbolt interfaces to bridge
1438 bridge
= copyAutoBridgeInterface(setPrivate
->prefs
, CFSTR("thunderbolt-bridge"));
1441 if (bridge
!= NULL
) {
1442 CFIndex bridgeIndex
;
1444 CFMutableArrayRef newMembers
;
1445 CFMutableSetRef newExcluded
;
1446 CFMutableArrayRef newInterfaces
;
1447 CFArrayRef newServices
;
1449 // track the bridge interface (if it's in our list)
1450 bridgeIndex
= CFArrayGetFirstIndexOfValue(interfaces
,
1451 CFRangeMake(0, CFArrayGetCount(interfaces
)),
1454 // add new member interface
1455 members
= SCBridgeInterfaceGetMemberInterfaces(bridge
);
1456 if ((members
!= NULL
) && (CFArrayGetCount(members
) > 0)) {
1457 newMembers
= CFArrayCreateMutableCopy(NULL
, 0, members
);
1458 updated
= TRUE
; // if we're updating an existing bridge
1460 newMembers
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1462 CFArrayAppendValue(newMembers
, interface
);
1463 ok
= SCBridgeInterfaceSetMemberInterfaces(bridge
, newMembers
);
1464 CFRelease(newMembers
);
1466 SCLog(TRUE
, LOG_DEBUG
,
1467 CFSTR("could not update bridge with \"%@\": %s\n"),
1468 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
1469 SCErrorString(SCError()));
1474 // exclude the new member interface
1475 newExcluded
= CFSetCreateMutableCopy(NULL
, 0, excluded
);
1476 CFRelease(excluded
);
1477 CFSetAddValue(newExcluded
, interface
);
1478 excluded
= newExcluded
;
1480 // update the list of interfaces to include the [new or updated] bridge
1481 newInterfaces
= CFArrayCreateMutableCopy(NULL
, 0, interfaces
);
1482 if (bridgeIndex
!= kCFNotFound
) {
1483 CFArraySetValueAtIndex(newInterfaces
, bridgeIndex
, bridge
);
1485 CFArrayAppendValue(newInterfaces
, bridge
);
1488 CFRelease(interfaces
);
1490 interfaces
= newInterfaces
;
1493 // refresh [existing] services
1494 newServices
= updateServices(services
, bridge
);
1495 if (newServices
!= NULL
) {
1496 CFRelease(services
);
1497 services
= newServices
;
1503 #endif // !TARGET_OS_IPHONE
1505 n
= (interfaces
!= NULL
) ? CFArrayGetCount(interfaces
) : 0;
1506 for (i
= 0; i
< n
; i
++) {
1507 SCNetworkInterfaceRef interface
;
1508 CFMutableArrayRef interface_list
;
1510 interface
= CFArrayGetValueAtIndex(interfaces
, i
);
1511 if ((excluded
!= NULL
)
1512 && CFSetContainsValue(excluded
, interface
)) {
1513 // if this interface is a member of a Bond or Bridge
1517 if (__SCNetworkServiceExistsForInterface(services
, interface
)) {
1518 // if this is not a new interface
1522 interface_list
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1523 CFArrayAppendValue(interface_list
, interface
);
1525 while (ok
&& (CFArrayGetCount(interface_list
) > 0)) {
1526 CFArrayRef protocol_types
;
1528 interface
= CFArrayGetValueAtIndex(interface_list
, 0);
1530 protocol_types
= SCNetworkInterfaceGetSupportedProtocolTypes(interface
);
1531 if ((protocol_types
!= NULL
) && (CFArrayGetCount(protocol_types
) > 0)) {
1532 SCNetworkServiceRef service
;
1534 service
= SCNetworkServiceCreate(setPrivate
->prefs
, interface
);
1535 if (service
== NULL
) {
1536 SCLog(TRUE
, LOG_DEBUG
,
1537 CFSTR("could not create service for \"%@\": %s\n"),
1538 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
1539 SCErrorString(SCError()));
1544 ok
= SCNetworkServiceEstablishDefaultConfiguration(service
);
1546 SCLog(TRUE
, LOG_DEBUG
,
1547 CFSTR("could not estabish default configuration for \"%@\": %s\n"),
1548 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
1549 SCErrorString(SCError()));
1550 SCNetworkServiceRemove(service
);
1556 CFStringRef newName
;
1558 ok
= SCNetworkSetAddService(set
, service
);
1563 if (SCError() != kSCStatusKeyExists
) {
1564 SCLog(TRUE
, LOG_DEBUG
,
1565 CFSTR("could not add service for \"%@\": %s\n"),
1566 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
1567 SCErrorString(SCError()));
1568 SCNetworkServiceRemove(service
);
1573 // we have two interfaces with the same service
1574 // name, acquire a new, hopefully unique, name
1576 newName
= __SCNetworkServiceNextName(service
);
1577 if (newName
== NULL
) {
1578 SCLog(TRUE
, LOG_DEBUG
,
1579 CFSTR("could not set unique name for \"%@\": %s\n"),
1580 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
1581 SCErrorString(SCError()));
1582 SCNetworkServiceRemove(service
);
1587 ok
= SCNetworkServiceSetName(service
, newName
);
1593 if (SCError() != kSCStatusKeyExists
) {
1594 SCLog(TRUE
, LOG_DEBUG
,
1595 CFSTR("could not set unique name for \"%@\": %s\n"),
1596 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
1597 SCErrorString(SCError()));
1598 SCNetworkServiceRemove(service
);
1607 add_supported_interfaces(interface_list
, interface
);
1612 CFArrayRemoveValueAtIndex(interface_list
, 0);
1614 CFRelease(interface_list
);
1616 if (updatedIFs
) CFRelease(interfaces
);
1617 if (services
!= NULL
) CFRelease(services
);
1618 if (excluded
!= NULL
) CFRelease(excluded
);
1620 #if TARGET_OS_IPHONE
1621 if (orphans
!= NULL
) {
1622 if (ok
&& updated
) {
1624 CFIndex n
= CFArrayGetCount(orphans
);
1626 for (i
= 0; i
< n
; i
++) {
1627 SCNetworkServiceRef service
;
1629 service
= CFArrayGetValueAtIndex(orphans
, i
);
1630 if (_SCNetworkServiceIsVPN(service
)) {
1631 ok
= SCNetworkSetAddService(set
, service
);
1641 #endif // TARGET_OS_IPHONE
1643 if (ok
&& !updated
) {
1644 // if no changes were made
1645 _SCErrorSet(kSCStatusOK
);
1653 SCNetworkSetEstablishDefaultConfiguration(SCNetworkSetRef set
)
1655 CFArrayRef interfaces
;
1656 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1657 Boolean updated
= FALSE
;
1659 if (!isA_SCNetworkSet(set
)) {
1660 _SCErrorSet(kSCStatusInvalidArgument
);
1664 interfaces
= _SCNetworkInterfaceCopyAllWithPreferences(setPrivate
->prefs
);
1665 if (interfaces
!= NULL
) {
1666 updated
= __SCNetworkSetEstablishDefaultConfigurationForInterfaces(set
, interfaces
);
1667 CFRelease(interfaces
);
1675 SCNetworkSetEstablishDefaultInterfaceConfiguration(SCNetworkSetRef set
, SCNetworkInterfaceRef interface
)
1677 CFArrayRef interfaces
;
1680 if (!isA_SCNetworkSet(set
)) {
1681 _SCErrorSet(kSCStatusInvalidArgument
);
1685 if (!isA_SCNetworkInterface(interface
)) {
1686 _SCErrorSet(kSCStatusInvalidArgument
);
1690 interfaces
= CFArrayCreate(NULL
, (const void **)&interface
, 1, &kCFTypeArrayCallBacks
);
1691 assert(interfaces
!= NULL
);
1692 updated
= __SCNetworkSetEstablishDefaultConfigurationForInterfaces(set
, interfaces
);
1693 CFRelease(interfaces
);
1700 SCNetworkSetCopySelectedVPNService(SCNetworkSetRef set
)
1704 SCNetworkServiceRef selected
= NULL
;
1705 CFArrayRef services
;
1706 CFMutableArrayRef services_vpn
= NULL
;
1708 if (!isA_SCNetworkSet(set
)) {
1709 _SCErrorSet(kSCStatusInvalidArgument
);
1713 services
= SCNetworkSetCopyServices(set
);
1714 if (services
!= NULL
) {
1715 n
= CFArrayGetCount(services
);
1716 for (i
= 0; i
< n
; i
++) {
1717 SCNetworkServiceRef service
;
1719 service
= CFArrayGetValueAtIndex(services
, i
);
1720 if (!SCNetworkServiceGetEnabled(service
)) {
1725 if (!_SCNetworkServiceIsVPN(service
)) {
1726 // if not VPN service
1730 if (services_vpn
== NULL
) {
1731 services_vpn
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1733 CFArrayAppendValue(services_vpn
, service
);
1736 CFRelease(services
);
1739 if (services_vpn
== NULL
) {
1740 // if no VPN services
1744 n
= CFArrayGetCount(services_vpn
);
1747 CFMutableArrayRef sorted
;
1749 order
= SCNetworkSetGetServiceOrder(set
);
1750 sorted
= CFArrayCreateMutableCopy(NULL
, 0, services_vpn
);
1751 CFArraySortValues(sorted
,
1752 CFRangeMake(0, CFArrayGetCount(sorted
)),
1753 _SCNetworkServiceCompare
,
1755 CFRelease(services_vpn
);
1756 services_vpn
= sorted
;
1759 #if TARGET_OS_IPHONE
1761 CFStringRef serviceID_prefs
;
1763 #define VPN_PREFERENCES CFSTR("com.apple.mobilevpn")
1764 #define VPN_SERVICE_ID CFSTR("activeVPNID")
1766 CFPreferencesAppSynchronize(VPN_PREFERENCES
);
1767 serviceID_prefs
= CFPreferencesCopyAppValue(VPN_SERVICE_ID
, VPN_PREFERENCES
);
1768 if (serviceID_prefs
!= NULL
) {
1769 for (i
= 0; i
< n
; i
++) {
1770 SCNetworkServiceRef service
;
1771 CFStringRef serviceID
;
1773 service
= CFArrayGetValueAtIndex(services_vpn
, i
);
1774 serviceID
= SCNetworkServiceGetServiceID(service
);
1775 if (CFEqual(serviceID
, serviceID_prefs
)) {
1783 CFRelease(serviceID_prefs
);
1786 #endif // TARGET_OS_IPHONE
1788 if (selected
== NULL
) {
1789 selected
= CFArrayGetValueAtIndex(services_vpn
, 0);
1793 CFRelease(services_vpn
);
1799 SCNetworkSetSetSelectedVPNService(SCNetworkSetRef set
, SCNetworkServiceRef service
)
1802 CFArrayRef services
;
1804 if (!isA_SCNetworkSet(set
)) {
1805 _SCErrorSet(kSCStatusInvalidArgument
);
1809 if (!isA_SCNetworkService(service
) || !_SCNetworkServiceIsVPN(service
)) {
1810 _SCErrorSet(kSCStatusInvalidArgument
);
1814 services
= SCNetworkSetCopyServices(set
);
1815 if (services
!= NULL
) {
1817 CFIndex n
= CFArrayGetCount(services
);
1819 if (!CFArrayContainsValue(services
, CFRangeMake(0, n
), service
)) {
1820 // if selected service not a member of the current set
1821 _SCErrorSet(kSCStatusInvalidArgument
);
1826 for (i
= 0; ok
&& (i
< n
); i
++) {
1827 SCNetworkServiceRef vpn
;
1829 vpn
= CFArrayGetValueAtIndex(services
, i
);
1830 if (!_SCNetworkServiceIsVPN(vpn
)) {
1831 // if not VPN service
1835 ok
= SCNetworkServiceSetEnabled(vpn
, CFEqual(service
, vpn
));
1841 if (services
!= NULL
) CFRelease(services
);