2 * Copyright (c) 2004-2015 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 * Modification History
27 * 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
294 #define PREVENT_DUPLICATE_SERVICE_NAMES
295 #ifdef PREVENT_DUPLICATE_SERVICE_NAMES
297 copy_next_name(CFStringRef name
)
299 CFArrayRef components
;
301 CFMutableArrayRef newComponents
;
308 components
= CFStringCreateArrayBySeparatingStrings(NULL
, name
, CFSTR(" "));
309 if (components
!= NULL
) {
310 newComponents
= CFArrayCreateMutableCopy(NULL
, 0, components
);
311 CFRelease(components
);
313 newComponents
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
314 CFArrayAppendValue(newComponents
, name
);
317 n
= CFArrayGetCount(newComponents
);
321 str
= CFArrayGetValueAtIndex(newComponents
, n
- 1);
322 suffix
= CFStringGetIntValue(str
);
324 CFArrayRemoveValueAtIndex(newComponents
, n
- 1);
330 name
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%d"), (int)suffix
);
331 CFArrayAppendValue(newComponents
, name
);
334 name
= CFStringCreateByCombiningStrings(NULL
, newComponents
, CFSTR(" "));
335 CFRelease(newComponents
);
342 ensure_unique_service_name(SCNetworkServiceRef service
)
344 SCNetworkInterfaceRef interface
;
348 interface
= SCNetworkServiceGetInterface(service
);
350 name
= SCNetworkServiceGetName(service
);
358 ok
= SCNetworkServiceSetName(service
, name
);
363 if (SCError() != kSCStatusKeyExists
) {
364 SC_log(LOG_INFO
, "could not update service name for \"%@\": %s",
365 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
366 SCErrorString(SCError()));
370 newName
= copy_next_name(name
);
371 if (newName
== NULL
) {
372 SC_log(LOG_INFO
, "could not create unique name for \"%@\": %s",
373 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
374 SCErrorString(SCError()));
378 // try again with the "new" name
391 #endif // PREVENT_DUPLICATE_SERVICE_NAMES
395 SCNetworkSetAddService(SCNetworkSetRef set
, SCNetworkServiceRef service
)
397 SCNetworkInterfaceRef interface
;
398 CFArrayRef interface_config
= NULL
;
402 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
403 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
405 if (!isA_SCNetworkSet(set
)) {
406 _SCErrorSet(kSCStatusInvalidArgument
);
410 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
411 _SCErrorSet(kSCStatusInvalidArgument
);
415 // make sure that we do not add an orphaned network service if its
416 // associated interface is a member of a bond or bridge.
417 interface
= SCNetworkServiceGetInterface(service
);
418 if ((interface
!= NULL
) &&
419 __SCNetworkInterfaceIsMember(servicePrivate
->prefs
, interface
)) {
420 _SCErrorSet(kSCStatusKeyExists
);
424 //#define PREVENT_DUPLICATE_SETS
425 #ifdef PREVENT_DUPLICATE_SETS
428 // ensure that each service is only a member of ONE set
429 sets
= SCNetworkSetCopyAll(setPrivate
->prefs
);
434 n
= CFArrayGetCount(sets
);
435 for (i
= 0; i
< n
; i
++) {
440 set
= CFArrayGetValueAtIndex(sets
, i
);
441 services
= SCNetworkSetCopyServices(set
);
442 found
= CFArrayContainsValue(services
,
443 CFRangeMake(0, CFArrayGetCount(services
)),
449 _SCErrorSet(kSCStatusKeyExists
);
455 #endif /* PREVENT_DUPLICATE_SETS */
457 // get the [deep] interface configuration settings
458 interface
= SCNetworkServiceGetInterface(service
);
459 if (interface
!= NULL
) {
460 interface_config
= __SCNetworkInterfaceCopyDeepConfiguration(set
, interface
);
463 // create the link between "set" and the "service"
464 path
= SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL
, // allocator
465 setPrivate
->setID
, // set
466 servicePrivate
->serviceID
, // service
468 link
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
469 servicePrivate
->serviceID
, // service
471 ok
= SCPreferencesPathSetLink(setPrivate
->prefs
, path
, link
);
472 #ifdef PREVENT_DUPLICATE_SERVICE_NAMES
474 ok
= ensure_unique_service_name(service
);
476 // if we could not ensure a unique name, remove the (just added)
477 // link between the "set" and the "service"
478 (void) SCPreferencesPathRemoveValue(setPrivate
->prefs
, path
);
481 #endif // PREVENT_DUPLICATE_SERVICE_NAMES
488 // push the [deep] interface configuration into all sets which contain this service.
489 if (interface
!= NULL
) {
490 __SCNetworkInterfaceSetDeepConfiguration(set
, interface
, interface_config
);
493 // add service to ServiceOrder
494 _serviceOrder_add(set
, service
);
496 // mark set as no longer "new"
497 setPrivate
->established
= TRUE
;
501 if (interface_config
!= NULL
) CFRelease(interface_config
);
507 SCNetworkSetCopy(SCPreferencesRef prefs
, CFStringRef setID
)
509 CFDictionaryRef entity
;
511 SCNetworkSetPrivateRef setPrivate
;
513 if (!isA_CFString(setID
)) {
514 _SCErrorSet(kSCStatusInvalidArgument
);
518 path
= SCPreferencesPathKeyCreateSet(NULL
, setID
);
519 entity
= SCPreferencesPathGetValue(prefs
, path
);
522 if (!isA_CFDictionary(entity
)) {
523 _SCErrorSet(kSCStatusNoKey
);
527 setPrivate
= __SCNetworkSetCreatePrivate(NULL
, prefs
, setID
);
528 assert(setPrivate
!= NULL
);
530 // mark set as "old" (already established)
531 setPrivate
->established
= TRUE
;
533 return (SCNetworkSetRef
)setPrivate
;
538 SCNetworkSetContainsInterface(SCNetworkSetRef set
, SCNetworkInterfaceRef interface
)
540 Boolean found
= FALSE
;
543 services
= SCNetworkSetCopyServices(set
);
544 if (services
!= NULL
) {
545 found
= __SCNetworkServiceExistsForInterface(services
, interface
);
553 CFArrayRef
/* of SCNetworkSetRef's */
554 SCNetworkSetCopyAll(SCPreferencesRef prefs
)
556 CFMutableArrayRef array
;
559 CFDictionaryRef sets
;
561 path
= SCPreferencesPathKeyCreateSets(NULL
);
562 sets
= SCPreferencesPathGetValue(prefs
, path
);
565 if ((sets
!= NULL
) && !isA_CFDictionary(sets
)) {
569 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
571 n
= (sets
!= NULL
) ? CFDictionaryGetCount(sets
) : 0;
574 const void * keys_q
[N_QUICK
];
575 const void ** keys
= keys_q
;
576 const void * vals_q
[N_QUICK
];
577 const void ** vals
= vals_q
;
579 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
580 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
581 vals
= CFAllocatorAllocate(NULL
, n
* sizeof(CFPropertyListRef
), 0);
583 CFDictionaryGetKeysAndValues(sets
, keys
, vals
);
584 for (i
= 0; i
< n
; i
++) {
585 SCNetworkSetPrivateRef setPrivate
;
587 if (!isA_CFDictionary(vals
[i
])) {
588 SC_log(LOG_INFO
, "error w/set \"%@\"", keys
[i
]);
592 setPrivate
= __SCNetworkSetCreatePrivate(NULL
, prefs
, keys
[i
]);
593 assert(setPrivate
!= NULL
);
595 // mark set as "old" (already established)
596 setPrivate
->established
= TRUE
;
598 CFArrayAppendValue(array
, (SCNetworkSetRef
)setPrivate
);
599 CFRelease(setPrivate
);
601 if (keys
!= keys_q
) {
602 CFAllocatorDeallocate(NULL
, keys
);
603 CFAllocatorDeallocate(NULL
, vals
);
611 CFArrayRef
/* of SCNetworkInterfaceRef's */
612 SCNetworkSetCopyAvailableInterfaces(SCNetworkSetRef set
)
614 CFMutableArrayRef available
;
615 CFMutableSetRef excluded
= NULL
;
617 CFArrayRef interfaces
;
618 CFIndex n_interfaces
;
619 CFIndex n_exclusions
= 0;
620 SCPreferencesRef prefs
;
621 SCNetworkSetPrivateRef setPrivate
;
623 setPrivate
= (SCNetworkSetPrivateRef
)set
;
624 prefs
= setPrivate
->prefs
;
626 interfaces
= _SCNetworkInterfaceCopyAllWithPreferences(prefs
);
627 n_interfaces
= CFArrayGetCount(interfaces
);
628 if (n_interfaces
== 0) {
633 CFArrayRef bridges
= NULL
;
635 excluded
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
637 #if !TARGET_OS_IPHONE
638 CFArrayRef bonds
= NULL
;
640 bonds
= SCBondInterfaceCopyAll(prefs
);
642 __SCBondInterfaceListCollectMembers(bonds
, excluded
);
645 #endif /* !TARGET_OS_IPHONE */
647 bridges
= SCBridgeInterfaceCopyAll(prefs
);
648 if (bridges
!= NULL
) {
649 __SCBridgeInterfaceListCollectMembers(bridges
, excluded
);
653 n_exclusions
= CFSetGetCount(excluded
);
656 if (n_exclusions
== 0) {
657 if (excluded
!= NULL
) {
664 available
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
666 for (i
= 0; i
< n_interfaces
; i
++) {
667 SCNetworkInterfaceRef interface
;
669 interface
= CFArrayGetValueAtIndex(interfaces
, i
);
670 if (CFSetContainsValue(excluded
, interface
)) {
675 CFArrayAppendValue(available
, interface
);
678 CFRelease(interfaces
);
686 SCNetworkSetCopyCurrent(SCPreferencesRef prefs
)
688 CFArrayRef components
;
689 CFStringRef currentID
;
690 SCNetworkSetPrivateRef setPrivate
= NULL
;
692 currentID
= SCPreferencesGetValue(prefs
, kSCPrefCurrentSet
);
693 if (!isA_CFString(currentID
)) {
697 components
= CFStringCreateArrayBySeparatingStrings(NULL
, currentID
, CFSTR("/"));
698 if (CFArrayGetCount(components
) == 3) {
702 setID
= CFArrayGetValueAtIndex(components
, 2);
703 path
= SCPreferencesPathKeyCreateSet(NULL
, setID
);
704 if (CFEqual(path
, currentID
)) {
705 setPrivate
= __SCNetworkSetCreatePrivate(NULL
, prefs
, setID
);
706 assert(setPrivate
!= NULL
);
708 // mark set as "old" (already established)
709 setPrivate
->established
= TRUE
;
711 SC_log(LOG_NOTICE
, "SCNetworkSetCopyCurrent(): preferences are non-conformant");
715 CFRelease(components
);
717 return (SCNetworkSetRef
)setPrivate
;
721 CFArrayRef
/* of SCNetworkServiceRef's */
722 SCNetworkSetCopyServices(SCNetworkSetRef set
)
724 CFMutableArrayRef array
;
725 CFDictionaryRef dict
;
728 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
730 if (!isA_SCNetworkSet(set
)) {
731 _SCErrorSet(kSCStatusInvalidArgument
);
735 path
= SCPreferencesPathKeyCreateSetNetworkService(NULL
, setPrivate
->setID
, NULL
);
736 dict
= SCPreferencesPathGetValue(setPrivate
->prefs
, path
);
738 if ((dict
!= NULL
) && !isA_CFDictionary(dict
)) {
742 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
744 n
= (dict
!= NULL
) ? CFDictionaryGetCount(dict
) : 0;
747 const void * keys_q
[N_QUICK
];
748 const void ** keys
= keys_q
;
750 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
751 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
753 CFDictionaryGetKeysAndValues(dict
, keys
, NULL
);
754 for (i
= 0; i
< n
; i
++) {
755 CFArrayRef components
;
758 path
= SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL
,
760 (CFStringRef
)keys
[i
],
762 link
= SCPreferencesPathGetLink(setPrivate
->prefs
, path
);
765 SC_log(LOG_INFO
, "service \"%@\" for set \"%@\" is not a link",
768 continue; // if the service is not a link
771 components
= CFStringCreateArrayBySeparatingStrings(NULL
, link
, CFSTR("/"));
772 if (CFArrayGetCount(components
) == 3) {
773 CFStringRef serviceID
;
775 serviceID
= CFArrayGetValueAtIndex(components
, 2);
776 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
777 serviceID
, // service
779 if (CFEqual(path
, link
)) {
780 SCNetworkServicePrivateRef servicePrivate
;
782 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
,
786 CFArrayAppendValue(array
, (SCNetworkServiceRef
)servicePrivate
);
787 CFRelease(servicePrivate
);
791 CFRelease(components
);
793 if (keys
!= keys_q
) {
794 CFAllocatorDeallocate(NULL
, keys
);
803 SCNetworkSetCreate(SCPreferencesRef prefs
)
805 CFArrayRef components
;
806 CFDictionaryRef entity
;
811 SCNetworkSetPrivateRef setPrivate
;
813 prefix
= SCPreferencesPathKeyCreateSets(NULL
);
814 path
= __SCPreferencesPathCreateUniqueChild_WithMoreSCFCompatibility(prefs
, prefix
);
815 if (path
== NULL
) path
= SCPreferencesPathCreateUniqueChild(prefs
, prefix
);
821 components
= CFStringCreateArrayBySeparatingStrings(NULL
, path
, CFSTR("/"));
822 setID
= CFArrayGetValueAtIndex(components
, 2);
823 setPrivate
= __SCNetworkSetCreatePrivate(NULL
, prefs
, setID
);
824 assert(setPrivate
!= NULL
);
825 CFRelease(components
);
827 // mark set as "new" (not yet established)
828 setPrivate
->established
= FALSE
;
830 // establish the set in the preferences
831 entity
= CFDictionaryCreate(NULL
,
833 &kCFTypeDictionaryKeyCallBacks
,
834 &kCFTypeDictionaryValueCallBacks
);
835 ok
= SCPreferencesPathSetValue(prefs
, path
, entity
);
839 CFRelease(setPrivate
);
843 return (SCNetworkSetRef
)setPrivate
;
848 SCNetworkSetGetSetID(SCNetworkSetRef set
)
850 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
852 if (!isA_SCNetworkSet(set
)) {
853 _SCErrorSet(kSCStatusInvalidArgument
);
857 return setPrivate
->setID
;
862 SCNetworkSetGetName(SCNetworkSetRef set
)
865 CFDictionaryRef entity
;
867 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
869 if (!isA_SCNetworkSet(set
)) {
870 _SCErrorSet(kSCStatusInvalidArgument
);
874 if (setPrivate
->name
!= NULL
) {
875 return setPrivate
->name
;
878 path
= SCPreferencesPathKeyCreateSet(NULL
, setPrivate
->setID
);
879 entity
= SCPreferencesPathGetValue(setPrivate
->prefs
, path
);
882 if (isA_CFDictionary(entity
)) {
885 name
= CFDictionaryGetValue(entity
, kSCPropUserDefinedName
);
886 if (isA_CFString(name
)) {
887 setPrivate
->name
= CFRetain(name
);
891 bundle
= _SC_CFBundleGet();
892 if (bundle
!= NULL
) {
893 if (setPrivate
->name
!= NULL
) {
894 CFStringRef non_localized
;
896 non_localized
= _SC_CFBundleCopyNonLocalizedString(bundle
,
897 CFSTR("DEFAULT_SET_NAME"),
900 if (non_localized
!= NULL
) {
901 if (CFEqual(setPrivate
->name
, non_localized
)) {
902 CFStringRef localized
;
904 // if "Automatic", return localized name
905 localized
= CFBundleCopyLocalizedString(bundle
,
906 CFSTR("DEFAULT_SET_NAME"),
909 if (localized
!= NULL
) {
910 CFRelease(setPrivate
->name
);
911 setPrivate
->name
= localized
;
915 CFRelease(non_localized
);
920 return setPrivate
->name
;
924 CFArrayRef
/* of serviceID CFStringRef's */
925 SCNetworkSetGetServiceOrder(SCNetworkSetRef set
)
927 CFDictionaryRef dict
;
929 CFArrayRef serviceOrder
;
930 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
932 if (!isA_SCNetworkSet(set
)) {
933 _SCErrorSet(kSCStatusInvalidArgument
);
937 path
= SCPreferencesPathKeyCreateSetNetworkGlobalEntity(NULL
, setPrivate
->setID
, kSCEntNetIPv4
);
942 dict
= SCPreferencesPathGetValue(setPrivate
->prefs
, path
);
944 if (!isA_CFDictionary(dict
)) {
948 serviceOrder
= CFDictionaryGetValue(dict
, kSCPropNetServiceOrder
);
949 serviceOrder
= isA_CFArray(serviceOrder
);
956 SCNetworkSetGetTypeID(void)
958 pthread_once(&initialized
, __SCNetworkSetInitialize
); /* initialize runtime */
959 return __kSCNetworkSetTypeID
;
964 SCNetworkSetRemove(SCNetworkSetRef set
)
966 CFStringRef currentPath
;
969 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
971 if (!isA_SCNetworkSet(set
)) {
972 _SCErrorSet(kSCStatusInvalidArgument
);
976 currentPath
= SCPreferencesGetValue(setPrivate
->prefs
, kSCPrefCurrentSet
);
977 path
= SCPreferencesPathKeyCreateSet(NULL
, setPrivate
->setID
);
978 if (!isA_CFString(currentPath
) || !CFEqual(currentPath
, path
)) {
979 ok
= SCPreferencesPathRemoveValue(setPrivate
->prefs
, path
);
981 _SCErrorSet(kSCStatusInvalidArgument
);
990 SCNetworkSetRemoveService(SCNetworkSetRef set
, SCNetworkServiceRef service
)
992 SCNetworkInterfaceRef interface
;
993 CFArrayRef interface_config
= NULL
;
996 int sc_status
= kSCStatusOK
;
997 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
998 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1000 if (!isA_SCNetworkSet(set
)) {
1001 _SCErrorSet(kSCStatusInvalidArgument
);
1005 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1006 _SCErrorSet(kSCStatusInvalidArgument
);
1010 // remove service from ServiceOrder
1011 _serviceOrder_remove(set
, service
);
1013 // get the [deep] interface configuration settings
1014 interface
= SCNetworkServiceGetInterface(service
);
1015 if (interface
!= NULL
) {
1016 interface_config
= __SCNetworkInterfaceCopyDeepConfiguration(set
, interface
);
1017 if (interface_config
!= NULL
) {
1018 // remove the interface configuration from all sets which contain this service.
1019 __SCNetworkInterfaceSetDeepConfiguration(set
, interface
, NULL
);
1023 // remove the link between "set" and the "service"
1024 path
= SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL
,
1026 servicePrivate
->serviceID
,
1028 ok
= SCPreferencesPathRemoveValue(setPrivate
->prefs
, path
);
1030 sc_status
= SCError(); // preserve the error
1034 // push the [deep] interface configuration [back] into all sets which contain the service.
1035 if (interface_config
!= NULL
) {
1036 __SCNetworkInterfaceSetDeepConfiguration(set
, interface
, interface_config
);
1039 if (interface_config
!= NULL
) CFRelease(interface_config
);
1041 _SCErrorSet(sc_status
);
1048 SCNetworkSetSetCurrent(SCNetworkSetRef set
)
1052 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1054 if (!isA_SCNetworkSet(set
)) {
1055 _SCErrorSet(kSCStatusInvalidArgument
);
1059 path
= SCPreferencesPathKeyCreateSet(NULL
, setPrivate
->setID
);
1060 ok
= SCPreferencesSetValue(setPrivate
->prefs
, kSCPrefCurrentSet
, path
);
1067 SCNetworkSetSetName(SCNetworkSetRef set
, CFStringRef name
)
1069 CFBundleRef bundle
= NULL
;
1070 CFDictionaryRef entity
;
1071 CFStringRef localized
= NULL
;
1072 CFStringRef non_localized
= NULL
;
1075 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1077 if (!isA_SCNetworkSet(set
)) {
1078 _SCErrorSet(kSCStatusInvalidArgument
);
1082 if ((name
!= NULL
) && !isA_CFString(name
)) {
1083 _SCErrorSet(kSCStatusInvalidArgument
);
1087 // if known, compare against localized name
1090 bundle
= _SC_CFBundleGet();
1091 if (bundle
!= NULL
) {
1092 non_localized
= _SC_CFBundleCopyNonLocalizedString(bundle
,
1093 CFSTR("DEFAULT_SET_NAME"),
1096 if (non_localized
!= NULL
) {
1097 if (CFEqual(name
, non_localized
)) {
1098 localized
= CFBundleCopyLocalizedString(bundle
,
1099 CFSTR("DEFAULT_SET_NAME"),
1102 if (localized
!= NULL
) {
1110 #define PREVENT_DUPLICATE_SET_NAMES
1111 #ifdef PREVENT_DUPLICATE_SET_NAMES
1115 // ensure that each set is uniquely named
1117 sets
= SCNetworkSetCopyAll(setPrivate
->prefs
);
1122 n
= CFArrayGetCount(sets
);
1123 for (i
= 0; i
< n
; i
++) {
1124 CFStringRef otherID
;
1125 CFStringRef otherName
;
1126 SCNetworkSetRef set
= CFArrayGetValueAtIndex(sets
, i
);
1128 otherID
= SCNetworkSetGetSetID(set
);
1129 if (CFEqual(setPrivate
->setID
, otherID
)) {
1130 continue; // skip current set
1133 otherName
= SCNetworkSetGetName(set
);
1134 if ((otherName
!= NULL
) && CFEqual(name
, otherName
)) {
1135 // if "name" not unique
1137 _SCErrorSet(kSCStatusKeyExists
);
1144 #endif /* PREVENT_DUPLICATE_SET_NAMES */
1146 // if known, store non-localized name
1148 if ((name
!= NULL
) && (bundle
!= NULL
) && (non_localized
!= NULL
)) {
1149 if (localized
== NULL
) {
1150 localized
= CFBundleCopyLocalizedString(bundle
,
1151 CFSTR("DEFAULT_SET_NAME"),
1156 if (localized
!= NULL
) {
1157 if (CFEqual(name
, localized
)) {
1158 name
= non_localized
;
1163 // update the "name"
1165 path
= SCPreferencesPathKeyCreateSet(NULL
, setPrivate
->setID
);
1166 entity
= SCPreferencesPathGetValue(setPrivate
->prefs
, path
);
1167 if (isA_CFDictionary(entity
) ||
1168 ((entity
== NULL
) && (name
!= NULL
))) {
1169 CFMutableDictionaryRef newEntity
;
1171 if (entity
!= NULL
) {
1172 newEntity
= CFDictionaryCreateMutableCopy(NULL
, 0, entity
);
1174 newEntity
= CFDictionaryCreateMutable(NULL
,
1176 &kCFTypeDictionaryKeyCallBacks
,
1177 &kCFTypeDictionaryValueCallBacks
);
1180 CFDictionarySetValue(newEntity
, kSCPropUserDefinedName
, name
);
1182 CFDictionaryRemoveValue(newEntity
, kSCPropUserDefinedName
);
1184 ok
= SCPreferencesPathSetValue(setPrivate
->prefs
, path
, newEntity
);
1185 CFRelease(newEntity
);
1191 if (localized
!= NULL
) CFRelease(localized
);
1192 if (non_localized
!= NULL
) CFRelease(non_localized
);
1198 SCNetworkSetSetServiceOrder(SCNetworkSetRef set
, CFArrayRef newOrder
)
1200 CFDictionaryRef dict
;
1201 CFMutableDictionaryRef newDict
;
1204 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1206 if (!isA_SCNetworkSet(set
)) {
1207 _SCErrorSet(kSCStatusInvalidArgument
);
1211 if (isA_CFArray(newOrder
)) {
1213 CFIndex n
= CFArrayGetCount(newOrder
);
1215 for (i
= 0; i
< n
; i
++) {
1216 CFStringRef serviceID
;
1218 serviceID
= CFArrayGetValueAtIndex(newOrder
, i
);
1219 if (!isA_CFString(serviceID
)) {
1220 _SCErrorSet(kSCStatusInvalidArgument
);
1225 _SCErrorSet(kSCStatusInvalidArgument
);
1229 path
= SCPreferencesPathKeyCreateSetNetworkGlobalEntity(NULL
, setPrivate
->setID
, kSCEntNetIPv4
);
1234 dict
= SCPreferencesPathGetValue(setPrivate
->prefs
, path
);
1236 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
1238 newDict
= CFDictionaryCreateMutable(NULL
,
1240 &kCFTypeDictionaryKeyCallBacks
,
1241 &kCFTypeDictionaryValueCallBacks
);
1244 CFDictionarySetValue(newDict
, kSCPropNetServiceOrder
, newOrder
);
1245 ok
= SCPreferencesPathSetValue(setPrivate
->prefs
, path
, newDict
);
1254 #pragma mark SCNetworkSet SPIs
1258 add_supported_interfaces(CFMutableArrayRef interface_list
, SCNetworkInterfaceRef interface
)
1261 CFArrayRef interface_types
;
1264 interface_types
= SCNetworkInterfaceGetSupportedInterfaceTypes(interface
);
1265 n
= (interface_types
!= NULL
) ? CFArrayGetCount(interface_types
) : 0;
1266 for (i
= 0; i
< n
; i
++) {
1267 SCNetworkInterfaceRef parent
;
1268 CFStringRef interface_type
;
1270 interface_type
= CFArrayGetValueAtIndex(interface_types
, i
);
1271 parent
= SCNetworkInterfaceCreateWithInterface(interface
, interface_type
);
1272 if (parent
!= NULL
) {
1273 CFArrayAppendValue(interface_list
, parent
);
1282 static CFSetRef
/* of SCNetworkInterfaceRef's */
1283 copyExcludedInterfaces(SCPreferencesRef prefs
)
1285 CFMutableSetRef excluded
;
1286 CFArrayRef interfaces
;
1288 excluded
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
1290 #if !TARGET_OS_IPHONE
1291 // exclude Bond [member] interfaces
1292 interfaces
= SCBondInterfaceCopyAll(prefs
);
1293 if (interfaces
!= NULL
) {
1294 __SCBondInterfaceListCollectMembers(interfaces
, excluded
);
1295 CFRelease(interfaces
);
1297 #endif // !TARGET_OS_IPHONE
1299 // exclude Bridge [member] interfaces
1300 interfaces
= SCBridgeInterfaceCopyAll(prefs
);
1301 if (interfaces
!= NULL
) {
1302 __SCBridgeInterfaceListCollectMembers(interfaces
, excluded
);
1303 CFRelease(interfaces
);
1310 #if !TARGET_OS_IPHONE
1311 static SCBridgeInterfaceRef
1312 copyAutoBridgeInterface(SCPreferencesRef prefs
, CFStringRef bridgeName
)
1314 SCBridgeInterfaceRef bridge
= NULL
;
1315 CFArrayRef interfaces
;
1317 // exclude Bridge [member] interfaces
1318 interfaces
= SCBridgeInterfaceCopyAll(prefs
);
1319 if (interfaces
!= NULL
) {
1323 n
= CFArrayGetCount(interfaces
);
1324 for (i
= 0; i
< n
; i
++) {
1325 SCBridgeInterfaceRef interface
;
1326 CFStringRef name
= NULL
;
1327 CFDictionaryRef options
;
1329 interface
= CFArrayGetValueAtIndex(interfaces
, i
);
1330 options
= SCBridgeInterfaceGetOptions(interface
);
1331 if ((options
!= NULL
) &&
1332 CFDictionaryGetValueIfPresent(options
,
1334 (const void **)&name
) &&
1335 _SC_CFEqual(name
, bridgeName
)) {
1342 CFRelease(interfaces
);
1345 if (bridge
== NULL
) {
1346 bridge
= SCBridgeInterfaceCreate(prefs
);
1347 if (bridge
!= NULL
) {
1348 CFMutableDictionaryRef newOptions
;
1351 newOptions
= CFDictionaryCreateMutable(NULL
, 0,
1352 &kCFTypeDictionaryKeyCallBacks
,
1353 &kCFTypeDictionaryValueCallBacks
);
1354 CFDictionarySetValue(newOptions
, CFSTR("__AUTO__"), bridgeName
);
1355 ok
= SCBridgeInterfaceSetOptions(bridge
, newOptions
);
1356 CFRelease(newOptions
);
1366 #endif // !TARGET_OS_IPHONE
1370 copyServices(SCNetworkSetRef set
)
1372 CFArrayRef services
;
1373 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1375 // first, assume that we only want to add new services
1376 // for those interfaces that are not represented in the
1378 services
= SCNetworkSetCopyServices(set
);
1379 if ((services
!= NULL
) && setPrivate
->established
) {
1380 // but, if we are given an existing (or "established") set
1381 // than we only want to add new services for those interfaces
1382 // that are not represented in *any* set.
1383 CFRelease(services
);
1384 services
= SCNetworkServiceCopyAll(setPrivate
->prefs
);
1391 #if !TARGET_OS_IPHONE
1393 updateServices(CFArrayRef services
, SCNetworkInterfaceRef interface
)
1395 CFStringRef bsdName
;
1398 CFMutableArrayRef newServices
;
1400 if (services
== NULL
) {
1404 bsdName
= SCNetworkInterfaceGetBSDName(interface
);
1406 newServices
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1408 n
= CFArrayGetCount(services
);
1409 for (i
= 0; i
< n
; i
++) {
1410 SCNetworkInterfaceRef interface
;
1411 CFStringRef interfaceName
;
1412 SCNetworkServiceRef newService
;
1413 SCNetworkServiceRef service
;
1414 CFStringRef serviceID
;
1415 SCNetworkServicePrivateRef servicePrivate
;
1417 service
= CFArrayGetValueAtIndex(services
, i
);
1418 interface
= SCNetworkServiceGetInterface(service
);
1419 interfaceName
= SCNetworkInterfaceGetBSDName(interface
);
1420 if (!_SC_CFEqual(interfaceName
, bsdName
)) {
1421 // if not a match, retain
1422 CFArrayAppendValue(newServices
, service
);
1426 // if a match, update
1427 serviceID
= SCNetworkServiceGetServiceID(service
);
1428 servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1429 newService
= SCNetworkServiceCopy(servicePrivate
->prefs
, serviceID
);
1430 if (newService
!= NULL
) {
1431 CFArrayAppendValue(newServices
, newService
);
1432 CFRelease(newService
);
1438 #endif // !TARGET_OS_IPHONE
1441 static __inline__ Boolean
1442 skipInterface(SCNetworkInterfaceRef interface
)
1446 action
= _SCNetworkInterfaceGetConfigurationAction(interface
);
1447 if (isA_CFString(action
) &&
1448 CFEqual(action
, kSCNetworkInterfaceConfigurationActionValueNone
)) {
1457 __SCNetworkSetEstablishDefaultConfigurationForInterfaces(SCNetworkSetRef set
, CFArrayRef interfaces
, Boolean excludeHidden
)
1459 CFSetRef excluded
= NULL
;
1463 CFArrayRef services
;
1464 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1465 Boolean updated
= FALSE
;
1466 Boolean updatedIFs
= FALSE
;
1468 #if TARGET_OS_IPHONE
1469 CFArrayRef orphans
= NULL
;
1472 sets
= SCNetworkSetCopyAll(setPrivate
->prefs
);
1474 if (CFArrayGetCount(sets
) == 1) {
1475 services
= SCNetworkSetCopyServices(set
);
1476 if (services
!= NULL
) {
1477 n
= CFArrayGetCount(services
);
1478 CFRelease(services
);
1481 if ((n
== 0) && CFEqual(set
, CFArrayGetValueAtIndex(sets
, 0))) {
1482 // after a "Reset Network Settings" we need to find (and
1483 // add back) any VPN services that were orphaned.
1484 orphans
= SCNetworkServiceCopyAll(setPrivate
->prefs
);
1490 #endif // TARGET_OS_IPHONE
1492 // copy network services
1493 services
= copyServices(set
);
1495 // copy network interfaces to be excluded
1496 excluded
= copyExcludedInterfaces(setPrivate
->prefs
);
1498 #if !TARGET_OS_IPHONE
1499 // look for interfaces that should auto-magically be added
1500 // to an Ethernet bridge
1501 n
= (interfaces
!= NULL
) ? CFArrayGetCount(interfaces
) : 0;
1502 for (i
= 0; i
< n
; i
++) {
1503 SCBridgeInterfaceRef bridge
= NULL
;
1504 SCNetworkInterfaceRef interface
;
1506 interface
= CFArrayGetValueAtIndex(interfaces
, i
);
1508 if (excludeHidden
&& skipInterface(interface
)) {
1509 // if not auto-configure
1513 if ((excluded
!= NULL
)
1514 && CFSetContainsValue(excluded
, interface
)) {
1515 // if this interface is a member of a Bond or Bridge
1519 if (__SCNetworkServiceExistsForInterface(services
, interface
)) {
1520 // if this is not a new interface
1524 if (_SCNetworkInterfaceIsBuiltin(interface
) &&
1525 _SCNetworkInterfaceIsThunderbolt(interface
) &&
1526 !isA_SCBridgeInterface(interface
)) {
1527 // add built-in Thunderbolt interfaces to bridge
1528 bridge
= copyAutoBridgeInterface(setPrivate
->prefs
, CFSTR("thunderbolt-bridge"));
1531 if (bridge
!= NULL
) {
1532 CFIndex bridgeIndex
;
1534 CFMutableArrayRef newMembers
;
1535 CFMutableSetRef newExcluded
;
1536 CFMutableArrayRef newInterfaces
;
1537 CFArrayRef newServices
;
1539 // track the bridge interface (if it's in our list)
1540 bridgeIndex
= CFArrayGetFirstIndexOfValue(interfaces
,
1541 CFRangeMake(0, CFArrayGetCount(interfaces
)),
1544 // add new member interface
1545 members
= SCBridgeInterfaceGetMemberInterfaces(bridge
);
1546 if ((members
!= NULL
) && (CFArrayGetCount(members
) > 0)) {
1547 newMembers
= CFArrayCreateMutableCopy(NULL
, 0, members
);
1548 updated
= TRUE
; // if we're updating an existing bridge
1550 newMembers
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1552 CFArrayAppendValue(newMembers
, interface
);
1553 ok
= SCBridgeInterfaceSetMemberInterfaces(bridge
, newMembers
);
1554 CFRelease(newMembers
);
1556 SC_log(LOG_INFO
, "could not update bridge with \"%@\": %s",
1557 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
1558 SCErrorString(SCError()));
1563 // exclude the new member interface
1564 newExcluded
= CFSetCreateMutableCopy(NULL
, 0, excluded
);
1565 CFRelease(excluded
);
1566 CFSetAddValue(newExcluded
, interface
);
1567 excluded
= newExcluded
;
1569 // update the list of interfaces to include the [new or updated] bridge
1570 newInterfaces
= CFArrayCreateMutableCopy(NULL
, 0, interfaces
);
1571 if (bridgeIndex
!= kCFNotFound
) {
1572 CFArraySetValueAtIndex(newInterfaces
, bridgeIndex
, bridge
);
1574 CFArrayAppendValue(newInterfaces
, bridge
);
1577 CFRelease(interfaces
);
1579 interfaces
= newInterfaces
;
1582 // refresh [existing] services
1583 newServices
= updateServices(services
, bridge
);
1584 if (newServices
!= NULL
) {
1585 CFRelease(services
);
1586 services
= newServices
;
1592 #endif // !TARGET_OS_IPHONE
1594 n
= (interfaces
!= NULL
) ? CFArrayGetCount(interfaces
) : 0;
1595 for (i
= 0; i
< n
; i
++) {
1596 SCNetworkInterfaceRef interface
;
1597 CFMutableArrayRef interface_list
;
1599 interface
= CFArrayGetValueAtIndex(interfaces
, i
);
1601 if (excludeHidden
&& skipInterface(interface
)) {
1602 // if not auto-configure
1606 if ((excluded
!= NULL
)
1607 && CFSetContainsValue(excluded
, interface
)) {
1608 // if this interface is a member of a Bond or Bridge
1612 if (__SCNetworkServiceExistsForInterface(services
, interface
)) {
1613 // if this is not a new interface
1617 interface_list
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1618 CFArrayAppendValue(interface_list
, interface
);
1620 while (ok
&& (CFArrayGetCount(interface_list
) > 0)) {
1621 CFArrayRef protocol_types
;
1623 interface
= CFArrayGetValueAtIndex(interface_list
, 0);
1625 protocol_types
= SCNetworkInterfaceGetSupportedProtocolTypes(interface
);
1626 if ((protocol_types
!= NULL
) && (CFArrayGetCount(protocol_types
) > 0)) {
1627 SCNetworkServiceRef service
;
1629 service
= SCNetworkServiceCreate(setPrivate
->prefs
, interface
);
1630 if (service
== NULL
) {
1631 SC_log(LOG_INFO
, "could not create service for \"%@\": %s",
1632 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
1633 SCErrorString(SCError()));
1638 ok
= SCNetworkServiceEstablishDefaultConfiguration(service
);
1640 SC_log(LOG_INFO
, "could not estabish default configuration for \"%@\": %s",
1641 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
1642 SCErrorString(SCError()));
1643 SCNetworkServiceRemove(service
);
1648 ok
= SCNetworkSetAddService(set
, service
);
1650 SC_log(LOG_INFO
, "could not add service for \"%@\": %s",
1651 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
1652 SCErrorString(SCError()));
1653 SCNetworkServiceRemove(service
);
1661 add_supported_interfaces(interface_list
, interface
);
1666 CFArrayRemoveValueAtIndex(interface_list
, 0);
1668 CFRelease(interface_list
);
1670 if (updatedIFs
) CFRelease(interfaces
);
1671 if (services
!= NULL
) CFRelease(services
);
1672 if (excluded
!= NULL
) CFRelease(excluded
);
1674 #if TARGET_OS_IPHONE
1675 if (orphans
!= NULL
) {
1676 if (ok
&& updated
) {
1678 CFIndex n
= CFArrayGetCount(orphans
);
1680 for (i
= 0; i
< n
; i
++) {
1681 SCNetworkServiceRef service
;
1683 service
= CFArrayGetValueAtIndex(orphans
, i
);
1684 if (_SCNetworkServiceIsVPN(service
)) {
1685 ok
= SCNetworkSetAddService(set
, service
);
1695 #endif // TARGET_OS_IPHONE
1697 if (ok
&& !updated
) {
1698 // if no changes were made
1699 _SCErrorSet(kSCStatusOK
);
1707 SCNetworkSetEstablishDefaultConfiguration(SCNetworkSetRef set
)
1709 CFArrayRef interfaces
;
1710 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1711 Boolean updated
= FALSE
;
1713 if (!isA_SCNetworkSet(set
)) {
1714 _SCErrorSet(kSCStatusInvalidArgument
);
1718 interfaces
= _SCNetworkInterfaceCopyAllWithPreferences(setPrivate
->prefs
);
1719 if (interfaces
!= NULL
) {
1720 updated
= __SCNetworkSetEstablishDefaultConfigurationForInterfaces(set
, interfaces
, TRUE
);
1721 CFRelease(interfaces
);
1729 SCNetworkSetEstablishDefaultInterfaceConfiguration(SCNetworkSetRef set
, SCNetworkInterfaceRef interface
)
1731 CFArrayRef interfaces
;
1734 if (!isA_SCNetworkSet(set
)) {
1735 _SCErrorSet(kSCStatusInvalidArgument
);
1739 if (!isA_SCNetworkInterface(interface
)) {
1740 _SCErrorSet(kSCStatusInvalidArgument
);
1744 interfaces
= CFArrayCreate(NULL
, (const void **)&interface
, 1, &kCFTypeArrayCallBacks
);
1745 assert(interfaces
!= NULL
);
1746 updated
= __SCNetworkSetEstablishDefaultConfigurationForInterfaces(set
, interfaces
, FALSE
);
1747 CFRelease(interfaces
);
1754 SCNetworkSetCopySelectedVPNService(SCNetworkSetRef set
)
1758 SCNetworkServiceRef selected
= NULL
;
1759 CFArrayRef services
;
1760 CFMutableArrayRef services_vpn
= NULL
;
1762 if (!isA_SCNetworkSet(set
)) {
1763 _SCErrorSet(kSCStatusInvalidArgument
);
1767 services
= SCNetworkSetCopyServices(set
);
1768 if (services
!= NULL
) {
1769 n
= CFArrayGetCount(services
);
1770 for (i
= 0; i
< n
; i
++) {
1771 SCNetworkServiceRef service
;
1773 service
= CFArrayGetValueAtIndex(services
, i
);
1774 if (!SCNetworkServiceGetEnabled(service
)) {
1779 if (!_SCNetworkServiceIsVPN(service
)) {
1780 // if not VPN service
1784 if (services_vpn
== NULL
) {
1785 services_vpn
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1787 CFArrayAppendValue(services_vpn
, service
);
1790 CFRelease(services
);
1793 if (services_vpn
== NULL
) {
1794 // if no VPN services
1798 n
= CFArrayGetCount(services_vpn
);
1801 CFMutableArrayRef sorted
;
1803 order
= SCNetworkSetGetServiceOrder(set
);
1804 sorted
= CFArrayCreateMutableCopy(NULL
, 0, services_vpn
);
1805 CFArraySortValues(sorted
,
1806 CFRangeMake(0, CFArrayGetCount(sorted
)),
1807 _SCNetworkServiceCompare
,
1809 CFRelease(services_vpn
);
1810 services_vpn
= sorted
;
1813 #if TARGET_OS_IPHONE
1815 CFStringRef serviceID_prefs
;
1817 #define VPN_PREFERENCES CFSTR("com.apple.mobilevpn")
1818 #define VPN_SERVICE_ID CFSTR("activeVPNID")
1820 CFPreferencesAppSynchronize(VPN_PREFERENCES
);
1821 serviceID_prefs
= CFPreferencesCopyAppValue(VPN_SERVICE_ID
, VPN_PREFERENCES
);
1822 if (serviceID_prefs
!= NULL
) {
1823 for (i
= 0; i
< n
; i
++) {
1824 SCNetworkServiceRef service
;
1825 CFStringRef serviceID
;
1827 service
= CFArrayGetValueAtIndex(services_vpn
, i
);
1828 serviceID
= SCNetworkServiceGetServiceID(service
);
1829 if (CFEqual(serviceID
, serviceID_prefs
)) {
1837 CFRelease(serviceID_prefs
);
1840 #endif // TARGET_OS_IPHONE
1842 if (selected
== NULL
) {
1843 selected
= CFArrayGetValueAtIndex(services_vpn
, 0);
1847 CFRelease(services_vpn
);
1853 SCNetworkSetSetSelectedVPNService(SCNetworkSetRef set
, SCNetworkServiceRef service
)
1856 CFArrayRef services
;
1858 if (!isA_SCNetworkSet(set
)) {
1859 _SCErrorSet(kSCStatusInvalidArgument
);
1863 if (!isA_SCNetworkService(service
) || !_SCNetworkServiceIsVPN(service
)) {
1864 _SCErrorSet(kSCStatusInvalidArgument
);
1868 services
= SCNetworkSetCopyServices(set
);
1869 if (services
!= NULL
) {
1871 CFIndex n
= CFArrayGetCount(services
);
1873 if (!CFArrayContainsValue(services
, CFRangeMake(0, n
), service
)) {
1874 // if selected service not a member of the current set
1875 _SCErrorSet(kSCStatusInvalidArgument
);
1880 for (i
= 0; ok
&& (i
< n
); i
++) {
1881 SCNetworkServiceRef vpn
;
1883 vpn
= CFArrayGetValueAtIndex(services
, i
);
1884 if (!_SCNetworkServiceIsVPN(vpn
)) {
1885 // if not VPN service
1889 ok
= SCNetworkServiceSetEnabled(vpn
, CFEqual(service
, vpn
));
1895 if (services
!= NULL
) CFRelease(services
);
1901 _SCNetworkSetSetSetID(SCNetworkSetRef set
, CFStringRef newSetID
)
1903 SCNetworkSetRef currentSet
= NULL
;
1904 SCNetworkSetPrivateRef currentSetPrivate
= NULL
;
1905 CFDictionaryRef entity
;
1906 CFStringRef newPath
;
1908 CFStringRef oldPath
= NULL
;
1909 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1910 Boolean updateCurrentSet
= FALSE
;
1912 if (!isA_SCNetworkSet(set
)) {
1913 _SCErrorSet(kSCStatusInvalidArgument
);
1917 if (!isA_CFString(newSetID
)) {
1918 _SCErrorSet(kSCStatusInvalidArgument
);
1922 // If newSetID is equal to current setID, our work is done
1923 if (CFEqual(newSetID
, setPrivate
->setID
)) {
1927 newPath
= SCPreferencesPathKeyCreateSet(NULL
, newSetID
);
1928 entity
= SCPreferencesPathGetValue(setPrivate
->prefs
, newPath
);
1929 if (isA_CFDictionary(entity
)) {
1930 // if the new set already exists
1931 _SCErrorSet(kSCStatusKeyExists
);
1935 oldPath
= SCPreferencesPathKeyCreateSet(NULL
, setPrivate
->setID
);
1936 entity
= SCPreferencesPathGetValue(setPrivate
->prefs
, oldPath
);
1937 if (!isA_CFDictionary(entity
)) {
1938 // if the set has already been removed
1939 _SCErrorSet(kSCStatusNoKey
);
1943 ok
= SCPreferencesPathSetValue(setPrivate
->prefs
, newPath
, entity
);
1948 ok
= SCPreferencesPathRemoveValue(setPrivate
->prefs
, oldPath
);
1953 // update current set (if needed)
1954 currentSet
= SCNetworkSetCopyCurrent(setPrivate
->prefs
);
1955 if (currentSet
!= NULL
) {
1956 currentSetPrivate
= (SCNetworkSetPrivateRef
)currentSet
;
1957 if (CFEqual(currentSetPrivate
->setID
, setPrivate
->setID
)) {
1958 updateCurrentSet
= TRUE
;
1960 CFRelease(currentSet
);
1964 CFRelease(setPrivate
->setID
);
1966 setPrivate
->setID
= newSetID
;
1968 if (updateCurrentSet
) {
1969 SCNetworkSetSetCurrent(set
);
1974 if (oldPath
!= NULL
) {
1977 if (newPath
!= NULL
) {