2 * Copyright (c) 2004-2014 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 * Modification History
27 * 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 SCLog(TRUE
, LOG_DEBUG
,
365 CFSTR("could not update service name for \"%@\": %s"),
366 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
367 SCErrorString(SCError()));
371 newName
= copy_next_name(name
);
372 if (newName
== NULL
) {
373 SCLog(TRUE
, LOG_DEBUG
,
374 CFSTR("could not create unique name for \"%@\": %s"),
375 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
376 SCErrorString(SCError()));
380 // try again with the "new" name
393 #endif // PREVENT_DUPLICATE_SERVICE_NAMES
397 SCNetworkSetAddService(SCNetworkSetRef set
, SCNetworkServiceRef service
)
399 SCNetworkInterfaceRef interface
;
400 CFArrayRef interface_config
= NULL
;
404 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
405 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
407 if (!isA_SCNetworkSet(set
)) {
408 _SCErrorSet(kSCStatusInvalidArgument
);
412 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
413 _SCErrorSet(kSCStatusInvalidArgument
);
417 // make sure that we do not add an orphaned network service if its
418 // associated interface is a member of a bond or bridge.
419 interface
= SCNetworkServiceGetInterface(service
);
420 if ((interface
!= NULL
) &&
421 __SCNetworkInterfaceIsMember(servicePrivate
->prefs
, interface
)) {
422 _SCErrorSet(kSCStatusKeyExists
);
426 //#define PREVENT_DUPLICATE_SETS
427 #ifdef PREVENT_DUPLICATE_SETS
430 // ensure that each service is only a member of ONE set
431 sets
= SCNetworkSetCopyAll(setPrivate
->prefs
);
436 n
= CFArrayGetCount(sets
);
437 for (i
= 0; i
< n
; i
++) {
442 set
= CFArrayGetValueAtIndex(sets
, i
);
443 services
= SCNetworkSetCopyServices(set
);
444 found
= CFArrayContainsValue(services
,
445 CFRangeMake(0, CFArrayGetCount(services
)),
451 _SCErrorSet(kSCStatusKeyExists
);
457 #endif /* PREVENT_DUPLICATE_SETS */
459 // get the [deep] interface configuration settings
460 interface
= SCNetworkServiceGetInterface(service
);
461 if (interface
!= NULL
) {
462 interface_config
= __SCNetworkInterfaceCopyDeepConfiguration(set
, interface
);
465 // create the link between "set" and the "service"
466 path
= SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL
, // allocator
467 setPrivate
->setID
, // set
468 servicePrivate
->serviceID
, // service
470 link
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
471 servicePrivate
->serviceID
, // service
473 ok
= SCPreferencesPathSetLink(setPrivate
->prefs
, path
, link
);
474 #ifdef PREVENT_DUPLICATE_SERVICE_NAMES
476 ok
= ensure_unique_service_name(service
);
478 // if we could not ensure a unique name, remove the (just added)
479 // link between the "set" and the "service"
480 (void) SCPreferencesPathRemoveValue(setPrivate
->prefs
, path
);
483 #endif // PREVENT_DUPLICATE_SERVICE_NAMES
490 // push the [deep] interface configuration into all sets which contain this service.
491 if (interface
!= NULL
) {
492 __SCNetworkInterfaceSetDeepConfiguration(set
, interface
, interface_config
);
495 // add service to ServiceOrder
496 _serviceOrder_add(set
, service
);
498 // mark set as no longer "new"
499 setPrivate
->established
= TRUE
;
503 if (interface_config
!= NULL
) CFRelease(interface_config
);
509 SCNetworkSetCopy(SCPreferencesRef prefs
, CFStringRef setID
)
511 CFDictionaryRef entity
;
513 SCNetworkSetPrivateRef setPrivate
;
515 if (!isA_CFString(setID
)) {
516 _SCErrorSet(kSCStatusInvalidArgument
);
520 path
= SCPreferencesPathKeyCreateSet(NULL
, setID
);
521 entity
= SCPreferencesPathGetValue(prefs
, path
);
524 if (!isA_CFDictionary(entity
)) {
525 _SCErrorSet(kSCStatusNoKey
);
529 setPrivate
= __SCNetworkSetCreatePrivate(NULL
, prefs
, setID
);
530 assert(setPrivate
!= NULL
);
532 // mark set as "old" (already established)
533 setPrivate
->established
= TRUE
;
535 return (SCNetworkSetRef
)setPrivate
;
540 SCNetworkSetContainsInterface(SCNetworkSetRef set
, SCNetworkInterfaceRef interface
)
542 Boolean found
= FALSE
;
545 services
= SCNetworkSetCopyServices(set
);
546 if (services
!= NULL
) {
547 found
= __SCNetworkServiceExistsForInterface(services
, interface
);
555 CFArrayRef
/* of SCNetworkSetRef's */
556 SCNetworkSetCopyAll(SCPreferencesRef prefs
)
558 CFMutableArrayRef array
;
561 CFDictionaryRef sets
;
563 path
= SCPreferencesPathKeyCreateSets(NULL
);
564 sets
= SCPreferencesPathGetValue(prefs
, path
);
567 if ((sets
!= NULL
) && !isA_CFDictionary(sets
)) {
571 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
573 n
= (sets
!= NULL
) ? CFDictionaryGetCount(sets
) : 0;
576 const void * keys_q
[N_QUICK
];
577 const void ** keys
= keys_q
;
578 const void * vals_q
[N_QUICK
];
579 const void ** vals
= vals_q
;
581 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
582 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
583 vals
= CFAllocatorAllocate(NULL
, n
* sizeof(CFPropertyListRef
), 0);
585 CFDictionaryGetKeysAndValues(sets
, keys
, vals
);
586 for (i
= 0; i
< n
; i
++) {
587 SCNetworkSetPrivateRef setPrivate
;
589 if (!isA_CFDictionary(vals
[i
])) {
592 CFSTR("SCNetworkSetCopyAll(): error w/set \"%@\"\n"),
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 SCLog(TRUE
, LOG_ERR
, CFSTR("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
);
772 CFSTR("SCNetworkSetCopyServices(): service \"%@\" for set \"%@\" is not a link\n"),
775 continue; // if the service is not a link
778 components
= CFStringCreateArrayBySeparatingStrings(NULL
, link
, CFSTR("/"));
779 if (CFArrayGetCount(components
) == 3) {
780 CFStringRef serviceID
;
782 serviceID
= CFArrayGetValueAtIndex(components
, 2);
783 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
784 serviceID
, // service
786 if (CFEqual(path
, link
)) {
787 SCNetworkServicePrivateRef servicePrivate
;
789 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
,
793 CFArrayAppendValue(array
, (SCNetworkServiceRef
)servicePrivate
);
794 CFRelease(servicePrivate
);
798 CFRelease(components
);
800 if (keys
!= keys_q
) {
801 CFAllocatorDeallocate(NULL
, keys
);
810 SCNetworkSetCreate(SCPreferencesRef prefs
)
812 CFArrayRef components
;
813 CFDictionaryRef entity
;
818 SCNetworkSetPrivateRef setPrivate
;
820 prefix
= SCPreferencesPathKeyCreateSets(NULL
);
821 path
= __SCPreferencesPathCreateUniqueChild_WithMoreSCFCompatibility(prefs
, prefix
);
822 if (path
== NULL
) path
= SCPreferencesPathCreateUniqueChild(prefs
, prefix
);
828 components
= CFStringCreateArrayBySeparatingStrings(NULL
, path
, CFSTR("/"));
829 setID
= CFArrayGetValueAtIndex(components
, 2);
830 setPrivate
= __SCNetworkSetCreatePrivate(NULL
, prefs
, setID
);
831 assert(setPrivate
!= NULL
);
832 CFRelease(components
);
834 // mark set as "new" (not yet established)
835 setPrivate
->established
= FALSE
;
837 // establish the set in the preferences
838 entity
= CFDictionaryCreate(NULL
,
840 &kCFTypeDictionaryKeyCallBacks
,
841 &kCFTypeDictionaryValueCallBacks
);
842 ok
= SCPreferencesPathSetValue(prefs
, path
, entity
);
846 CFRelease(setPrivate
);
850 return (SCNetworkSetRef
)setPrivate
;
855 SCNetworkSetGetSetID(SCNetworkSetRef set
)
857 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
859 if (!isA_SCNetworkSet(set
)) {
860 _SCErrorSet(kSCStatusInvalidArgument
);
864 return setPrivate
->setID
;
869 SCNetworkSetGetName(SCNetworkSetRef set
)
872 CFDictionaryRef entity
;
874 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
876 if (!isA_SCNetworkSet(set
)) {
877 _SCErrorSet(kSCStatusInvalidArgument
);
881 if (setPrivate
->name
!= NULL
) {
882 return setPrivate
->name
;
885 path
= SCPreferencesPathKeyCreateSet(NULL
, setPrivate
->setID
);
886 entity
= SCPreferencesPathGetValue(setPrivate
->prefs
, path
);
889 if (isA_CFDictionary(entity
)) {
892 name
= CFDictionaryGetValue(entity
, kSCPropUserDefinedName
);
893 if (isA_CFString(name
)) {
894 setPrivate
->name
= CFRetain(name
);
898 bundle
= _SC_CFBundleGet();
899 if (bundle
!= NULL
) {
900 if (setPrivate
->name
!= NULL
) {
901 CFStringRef non_localized
;
903 non_localized
= _SC_CFBundleCopyNonLocalizedString(bundle
,
904 CFSTR("DEFAULT_SET_NAME"),
907 if (non_localized
!= NULL
) {
908 if (CFEqual(setPrivate
->name
, non_localized
)) {
909 CFStringRef localized
;
911 // if "Automatic", return localized name
912 localized
= CFBundleCopyLocalizedString(bundle
,
913 CFSTR("DEFAULT_SET_NAME"),
916 if (localized
!= NULL
) {
917 CFRelease(setPrivate
->name
);
918 setPrivate
->name
= localized
;
922 CFRelease(non_localized
);
927 return setPrivate
->name
;
931 CFArrayRef
/* of serviceID CFStringRef's */
932 SCNetworkSetGetServiceOrder(SCNetworkSetRef set
)
934 CFDictionaryRef dict
;
936 CFArrayRef serviceOrder
;
937 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
939 if (!isA_SCNetworkSet(set
)) {
940 _SCErrorSet(kSCStatusInvalidArgument
);
944 path
= SCPreferencesPathKeyCreateSetNetworkGlobalEntity(NULL
, setPrivate
->setID
, kSCEntNetIPv4
);
949 dict
= SCPreferencesPathGetValue(setPrivate
->prefs
, path
);
951 if (!isA_CFDictionary(dict
)) {
955 serviceOrder
= CFDictionaryGetValue(dict
, kSCPropNetServiceOrder
);
956 serviceOrder
= isA_CFArray(serviceOrder
);
963 SCNetworkSetGetTypeID(void)
965 pthread_once(&initialized
, __SCNetworkSetInitialize
); /* initialize runtime */
966 return __kSCNetworkSetTypeID
;
971 SCNetworkSetRemove(SCNetworkSetRef set
)
973 CFStringRef currentPath
;
976 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
978 if (!isA_SCNetworkSet(set
)) {
979 _SCErrorSet(kSCStatusInvalidArgument
);
983 currentPath
= SCPreferencesGetValue(setPrivate
->prefs
, kSCPrefCurrentSet
);
984 path
= SCPreferencesPathKeyCreateSet(NULL
, setPrivate
->setID
);
985 if (!isA_CFString(currentPath
) || !CFEqual(currentPath
, path
)) {
986 ok
= SCPreferencesPathRemoveValue(setPrivate
->prefs
, path
);
988 _SCErrorSet(kSCStatusInvalidArgument
);
997 SCNetworkSetRemoveService(SCNetworkSetRef set
, SCNetworkServiceRef service
)
999 SCNetworkInterfaceRef interface
;
1000 CFArrayRef interface_config
= NULL
;
1003 int sc_status
= kSCStatusOK
;
1004 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1005 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1007 if (!isA_SCNetworkSet(set
)) {
1008 _SCErrorSet(kSCStatusInvalidArgument
);
1012 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1013 _SCErrorSet(kSCStatusInvalidArgument
);
1017 // remove service from ServiceOrder
1018 _serviceOrder_remove(set
, service
);
1020 // get the [deep] interface configuration settings
1021 interface
= SCNetworkServiceGetInterface(service
);
1022 if (interface
!= NULL
) {
1023 interface_config
= __SCNetworkInterfaceCopyDeepConfiguration(set
, interface
);
1024 if (interface_config
!= NULL
) {
1025 // remove the interface configuration from all sets which contain this service.
1026 __SCNetworkInterfaceSetDeepConfiguration(set
, interface
, NULL
);
1030 // remove the link between "set" and the "service"
1031 path
= SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL
,
1033 servicePrivate
->serviceID
,
1035 ok
= SCPreferencesPathRemoveValue(setPrivate
->prefs
, path
);
1037 sc_status
= SCError(); // preserve the error
1041 // push the [deep] interface configuration [back] into all sets which contain the service.
1042 if (interface_config
!= NULL
) {
1043 __SCNetworkInterfaceSetDeepConfiguration(set
, interface
, interface_config
);
1046 if (interface_config
!= NULL
) CFRelease(interface_config
);
1048 _SCErrorSet(sc_status
);
1055 SCNetworkSetSetCurrent(SCNetworkSetRef set
)
1059 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1061 if (!isA_SCNetworkSet(set
)) {
1062 _SCErrorSet(kSCStatusInvalidArgument
);
1066 path
= SCPreferencesPathKeyCreateSet(NULL
, setPrivate
->setID
);
1067 ok
= SCPreferencesSetValue(setPrivate
->prefs
, kSCPrefCurrentSet
, path
);
1074 SCNetworkSetSetName(SCNetworkSetRef set
, CFStringRef name
)
1076 CFBundleRef bundle
= NULL
;
1077 CFDictionaryRef entity
;
1078 CFStringRef localized
= NULL
;
1079 CFStringRef non_localized
= NULL
;
1082 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1084 if (!isA_SCNetworkSet(set
)) {
1085 _SCErrorSet(kSCStatusInvalidArgument
);
1089 if ((name
!= NULL
) && !isA_CFString(name
)) {
1090 _SCErrorSet(kSCStatusInvalidArgument
);
1094 // if known, compare against localized name
1097 bundle
= _SC_CFBundleGet();
1098 if (bundle
!= NULL
) {
1099 non_localized
= _SC_CFBundleCopyNonLocalizedString(bundle
,
1100 CFSTR("DEFAULT_SET_NAME"),
1103 if (non_localized
!= NULL
) {
1104 if (CFEqual(name
, non_localized
)) {
1105 localized
= CFBundleCopyLocalizedString(bundle
,
1106 CFSTR("DEFAULT_SET_NAME"),
1109 if (localized
!= NULL
) {
1117 #define PREVENT_DUPLICATE_SET_NAMES
1118 #ifdef PREVENT_DUPLICATE_SET_NAMES
1122 // ensure that each set is uniquely named
1124 sets
= SCNetworkSetCopyAll(setPrivate
->prefs
);
1129 n
= CFArrayGetCount(sets
);
1130 for (i
= 0; i
< n
; i
++) {
1131 CFStringRef otherID
;
1132 CFStringRef otherName
;
1133 SCNetworkSetRef set
= CFArrayGetValueAtIndex(sets
, i
);
1135 otherID
= SCNetworkSetGetSetID(set
);
1136 if (CFEqual(setPrivate
->setID
, otherID
)) {
1137 continue; // skip current set
1140 otherName
= SCNetworkSetGetName(set
);
1141 if ((otherName
!= NULL
) && CFEqual(name
, otherName
)) {
1142 // if "name" not unique
1144 _SCErrorSet(kSCStatusKeyExists
);
1151 #endif /* PREVENT_DUPLICATE_SET_NAMES */
1153 // if known, store non-localized name
1155 if ((name
!= NULL
) && (bundle
!= NULL
) && (non_localized
!= NULL
)) {
1156 if (localized
== NULL
) {
1157 localized
= CFBundleCopyLocalizedString(bundle
,
1158 CFSTR("DEFAULT_SET_NAME"),
1163 if (localized
!= NULL
) {
1164 if (CFEqual(name
, localized
)) {
1165 name
= non_localized
;
1170 // update the "name"
1172 path
= SCPreferencesPathKeyCreateSet(NULL
, setPrivate
->setID
);
1173 entity
= SCPreferencesPathGetValue(setPrivate
->prefs
, path
);
1174 if (isA_CFDictionary(entity
) ||
1175 ((entity
== NULL
) && (name
!= NULL
))) {
1176 CFMutableDictionaryRef newEntity
;
1178 if (entity
!= NULL
) {
1179 newEntity
= CFDictionaryCreateMutableCopy(NULL
, 0, entity
);
1181 newEntity
= CFDictionaryCreateMutable(NULL
,
1183 &kCFTypeDictionaryKeyCallBacks
,
1184 &kCFTypeDictionaryValueCallBacks
);
1187 CFDictionarySetValue(newEntity
, kSCPropUserDefinedName
, name
);
1189 CFDictionaryRemoveValue(newEntity
, kSCPropUserDefinedName
);
1191 ok
= SCPreferencesPathSetValue(setPrivate
->prefs
, path
, newEntity
);
1192 CFRelease(newEntity
);
1198 if (localized
!= NULL
) CFRelease(localized
);
1199 if (non_localized
!= NULL
) CFRelease(non_localized
);
1205 SCNetworkSetSetServiceOrder(SCNetworkSetRef set
, CFArrayRef newOrder
)
1207 CFDictionaryRef dict
;
1208 CFMutableDictionaryRef newDict
;
1211 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1213 if (!isA_SCNetworkSet(set
)) {
1214 _SCErrorSet(kSCStatusInvalidArgument
);
1218 if (isA_CFArray(newOrder
)) {
1220 CFIndex n
= CFArrayGetCount(newOrder
);
1222 for (i
= 0; i
< n
; i
++) {
1223 CFStringRef serviceID
;
1225 serviceID
= CFArrayGetValueAtIndex(newOrder
, i
);
1226 if (!isA_CFString(serviceID
)) {
1227 _SCErrorSet(kSCStatusInvalidArgument
);
1232 _SCErrorSet(kSCStatusInvalidArgument
);
1236 path
= SCPreferencesPathKeyCreateSetNetworkGlobalEntity(NULL
, setPrivate
->setID
, kSCEntNetIPv4
);
1241 dict
= SCPreferencesPathGetValue(setPrivate
->prefs
, path
);
1243 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
1245 newDict
= CFDictionaryCreateMutable(NULL
,
1247 &kCFTypeDictionaryKeyCallBacks
,
1248 &kCFTypeDictionaryValueCallBacks
);
1251 CFDictionarySetValue(newDict
, kSCPropNetServiceOrder
, newOrder
);
1252 ok
= SCPreferencesPathSetValue(setPrivate
->prefs
, path
, newDict
);
1261 #pragma mark SCNetworkSet SPIs
1265 add_supported_interfaces(CFMutableArrayRef interface_list
, SCNetworkInterfaceRef interface
)
1268 CFArrayRef interface_types
;
1271 interface_types
= SCNetworkInterfaceGetSupportedInterfaceTypes(interface
);
1272 n
= (interface_types
!= NULL
) ? CFArrayGetCount(interface_types
) : 0;
1273 for (i
= 0; i
< n
; i
++) {
1274 SCNetworkInterfaceRef parent
;
1275 CFStringRef interface_type
;
1277 interface_type
= CFArrayGetValueAtIndex(interface_types
, i
);
1278 parent
= SCNetworkInterfaceCreateWithInterface(interface
, interface_type
);
1279 if (parent
!= NULL
) {
1280 CFArrayAppendValue(interface_list
, parent
);
1289 static CFSetRef
/* of SCNetworkInterfaceRef's */
1290 copyExcludedInterfaces(SCPreferencesRef prefs
)
1292 CFMutableSetRef excluded
;
1293 CFArrayRef interfaces
;
1295 excluded
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
1297 #if !TARGET_OS_IPHONE
1298 // exclude Bond [member] interfaces
1299 interfaces
= SCBondInterfaceCopyAll(prefs
);
1300 if (interfaces
!= NULL
) {
1301 __SCBondInterfaceListCollectMembers(interfaces
, excluded
);
1302 CFRelease(interfaces
);
1304 #endif // !TARGET_OS_IPHONE
1306 // exclude Bridge [member] interfaces
1307 interfaces
= SCBridgeInterfaceCopyAll(prefs
);
1308 if (interfaces
!= NULL
) {
1309 __SCBridgeInterfaceListCollectMembers(interfaces
, excluded
);
1310 CFRelease(interfaces
);
1317 #if !TARGET_OS_IPHONE
1318 static SCBridgeInterfaceRef
1319 copyAutoBridgeInterface(SCPreferencesRef prefs
, CFStringRef bridgeName
)
1321 SCBridgeInterfaceRef bridge
= NULL
;
1322 CFArrayRef interfaces
;
1324 // exclude Bridge [member] interfaces
1325 interfaces
= SCBridgeInterfaceCopyAll(prefs
);
1326 if (interfaces
!= NULL
) {
1330 n
= CFArrayGetCount(interfaces
);
1331 for (i
= 0; i
< n
; i
++) {
1332 SCBridgeInterfaceRef interface
;
1333 CFStringRef name
= NULL
;
1334 CFDictionaryRef options
;
1336 interface
= CFArrayGetValueAtIndex(interfaces
, i
);
1337 options
= SCBridgeInterfaceGetOptions(interface
);
1338 if ((options
!= NULL
) &&
1339 CFDictionaryGetValueIfPresent(options
,
1341 (const void **)&name
) &&
1342 _SC_CFEqual(name
, bridgeName
)) {
1349 CFRelease(interfaces
);
1352 if (bridge
== NULL
) {
1353 bridge
= SCBridgeInterfaceCreate(prefs
);
1354 if (bridge
!= NULL
) {
1355 CFMutableDictionaryRef newOptions
;
1358 newOptions
= CFDictionaryCreateMutable(NULL
, 0,
1359 &kCFTypeDictionaryKeyCallBacks
,
1360 &kCFTypeDictionaryValueCallBacks
);
1361 CFDictionarySetValue(newOptions
, CFSTR("__AUTO__"), bridgeName
);
1362 ok
= SCBridgeInterfaceSetOptions(bridge
, newOptions
);
1363 CFRelease(newOptions
);
1373 #endif // !TARGET_OS_IPHONE
1377 copyServices(SCNetworkSetRef set
)
1379 CFArrayRef services
;
1380 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1382 // first, assume that we only want to add new services
1383 // for those interfaces that are not represented in the
1385 services
= SCNetworkSetCopyServices(set
);
1386 if ((services
!= NULL
) && setPrivate
->established
) {
1387 // but, if we are given an existing (or "established") set
1388 // than we only want to add new services for those interfaces
1389 // that are not represented in *any* set.
1390 CFRelease(services
);
1391 services
= SCNetworkServiceCopyAll(setPrivate
->prefs
);
1398 #if !TARGET_OS_IPHONE
1400 updateServices(CFArrayRef services
, SCNetworkInterfaceRef interface
)
1402 CFStringRef bsdName
;
1405 CFMutableArrayRef newServices
;
1407 if (services
== NULL
) {
1411 bsdName
= SCNetworkInterfaceGetBSDName(interface
);
1413 newServices
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1415 n
= CFArrayGetCount(services
);
1416 for (i
= 0; i
< n
; i
++) {
1417 SCNetworkInterfaceRef interface
;
1418 CFStringRef interfaceName
;
1419 SCNetworkServiceRef newService
;
1420 SCNetworkServiceRef service
;
1421 CFStringRef serviceID
;
1422 SCNetworkServicePrivateRef servicePrivate
;
1424 service
= CFArrayGetValueAtIndex(services
, i
);
1425 interface
= SCNetworkServiceGetInterface(service
);
1426 interfaceName
= SCNetworkInterfaceGetBSDName(interface
);
1427 if (!_SC_CFEqual(interfaceName
, bsdName
)) {
1428 // if not a match, retain
1429 CFArrayAppendValue(newServices
, service
);
1433 // if a match, update
1434 serviceID
= SCNetworkServiceGetServiceID(service
);
1435 servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1436 newService
= SCNetworkServiceCopy(servicePrivate
->prefs
, serviceID
);
1437 if (newService
!= NULL
) {
1438 CFArrayAppendValue(newServices
, newService
);
1439 CFRelease(newService
);
1445 #endif // !TARGET_OS_IPHONE
1448 static __inline__ Boolean
1449 skipInterface(SCNetworkInterfaceRef interface
)
1453 action
= _SCNetworkInterfaceGetConfigurationAction(interface
);
1454 if (isA_CFString(action
) &&
1455 CFEqual(action
, kSCNetworkInterfaceConfigurationActionValueNone
)) {
1464 __SCNetworkSetEstablishDefaultConfigurationForInterfaces(SCNetworkSetRef set
, CFArrayRef interfaces
, Boolean excludeHidden
)
1466 CFSetRef excluded
= NULL
;
1470 CFArrayRef services
;
1471 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1472 Boolean updated
= FALSE
;
1473 Boolean updatedIFs
= FALSE
;
1475 #if TARGET_OS_IPHONE
1476 CFArrayRef orphans
= NULL
;
1479 sets
= SCNetworkSetCopyAll(setPrivate
->prefs
);
1481 if (CFArrayGetCount(sets
) == 1) {
1482 services
= SCNetworkSetCopyServices(set
);
1483 if (services
!= NULL
) {
1484 n
= CFArrayGetCount(services
);
1485 CFRelease(services
);
1488 if ((n
== 0) && CFEqual(set
, CFArrayGetValueAtIndex(sets
, 0))) {
1489 // after a "Reset Network Settings" we need to find (and
1490 // add back) any VPN services that were orphaned.
1491 orphans
= SCNetworkServiceCopyAll(setPrivate
->prefs
);
1497 #endif // TARGET_OS_IPHONE
1499 // copy network services
1500 services
= copyServices(set
);
1502 // copy network interfaces to be excluded
1503 excluded
= copyExcludedInterfaces(setPrivate
->prefs
);
1505 #if !TARGET_OS_IPHONE
1506 // look for interfaces that should auto-magically be added
1507 // to an Ethernet bridge
1508 n
= (interfaces
!= NULL
) ? CFArrayGetCount(interfaces
) : 0;
1509 for (i
= 0; i
< n
; i
++) {
1510 SCBridgeInterfaceRef bridge
= NULL
;
1511 SCNetworkInterfaceRef interface
;
1513 interface
= CFArrayGetValueAtIndex(interfaces
, i
);
1515 if (excludeHidden
&& skipInterface(interface
)) {
1516 // if not auto-configure
1520 if ((excluded
!= NULL
)
1521 && CFSetContainsValue(excluded
, interface
)) {
1522 // if this interface is a member of a Bond or Bridge
1526 if (__SCNetworkServiceExistsForInterface(services
, interface
)) {
1527 // if this is not a new interface
1531 if (_SCNetworkInterfaceIsBuiltin(interface
) &&
1532 _SCNetworkInterfaceIsThunderbolt(interface
) &&
1533 !isA_SCBridgeInterface(interface
)) {
1534 // add built-in Thunderbolt interfaces to bridge
1535 bridge
= copyAutoBridgeInterface(setPrivate
->prefs
, CFSTR("thunderbolt-bridge"));
1538 if (bridge
!= NULL
) {
1539 CFIndex bridgeIndex
;
1541 CFMutableArrayRef newMembers
;
1542 CFMutableSetRef newExcluded
;
1543 CFMutableArrayRef newInterfaces
;
1544 CFArrayRef newServices
;
1546 // track the bridge interface (if it's in our list)
1547 bridgeIndex
= CFArrayGetFirstIndexOfValue(interfaces
,
1548 CFRangeMake(0, CFArrayGetCount(interfaces
)),
1551 // add new member interface
1552 members
= SCBridgeInterfaceGetMemberInterfaces(bridge
);
1553 if ((members
!= NULL
) && (CFArrayGetCount(members
) > 0)) {
1554 newMembers
= CFArrayCreateMutableCopy(NULL
, 0, members
);
1555 updated
= TRUE
; // if we're updating an existing bridge
1557 newMembers
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1559 CFArrayAppendValue(newMembers
, interface
);
1560 ok
= SCBridgeInterfaceSetMemberInterfaces(bridge
, newMembers
);
1561 CFRelease(newMembers
);
1563 SCLog(TRUE
, LOG_DEBUG
,
1564 CFSTR("could not update bridge with \"%@\": %s\n"),
1565 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
1566 SCErrorString(SCError()));
1571 // exclude the new member interface
1572 newExcluded
= CFSetCreateMutableCopy(NULL
, 0, excluded
);
1573 CFRelease(excluded
);
1574 CFSetAddValue(newExcluded
, interface
);
1575 excluded
= newExcluded
;
1577 // update the list of interfaces to include the [new or updated] bridge
1578 newInterfaces
= CFArrayCreateMutableCopy(NULL
, 0, interfaces
);
1579 if (bridgeIndex
!= kCFNotFound
) {
1580 CFArraySetValueAtIndex(newInterfaces
, bridgeIndex
, bridge
);
1582 CFArrayAppendValue(newInterfaces
, bridge
);
1585 CFRelease(interfaces
);
1587 interfaces
= newInterfaces
;
1590 // refresh [existing] services
1591 newServices
= updateServices(services
, bridge
);
1592 if (newServices
!= NULL
) {
1593 CFRelease(services
);
1594 services
= newServices
;
1600 #endif // !TARGET_OS_IPHONE
1602 n
= (interfaces
!= NULL
) ? CFArrayGetCount(interfaces
) : 0;
1603 for (i
= 0; i
< n
; i
++) {
1604 SCNetworkInterfaceRef interface
;
1605 CFMutableArrayRef interface_list
;
1607 interface
= CFArrayGetValueAtIndex(interfaces
, i
);
1609 if (excludeHidden
&& skipInterface(interface
)) {
1610 // if not auto-configure
1614 if ((excluded
!= NULL
)
1615 && CFSetContainsValue(excluded
, interface
)) {
1616 // if this interface is a member of a Bond or Bridge
1620 if (__SCNetworkServiceExistsForInterface(services
, interface
)) {
1621 // if this is not a new interface
1625 interface_list
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1626 CFArrayAppendValue(interface_list
, interface
);
1628 while (ok
&& (CFArrayGetCount(interface_list
) > 0)) {
1629 CFArrayRef protocol_types
;
1631 interface
= CFArrayGetValueAtIndex(interface_list
, 0);
1633 protocol_types
= SCNetworkInterfaceGetSupportedProtocolTypes(interface
);
1634 if ((protocol_types
!= NULL
) && (CFArrayGetCount(protocol_types
) > 0)) {
1635 SCNetworkServiceRef service
;
1637 service
= SCNetworkServiceCreate(setPrivate
->prefs
, interface
);
1638 if (service
== NULL
) {
1639 SCLog(TRUE
, LOG_DEBUG
,
1640 CFSTR("could not create service for \"%@\": %s\n"),
1641 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
1642 SCErrorString(SCError()));
1647 ok
= SCNetworkServiceEstablishDefaultConfiguration(service
);
1649 SCLog(TRUE
, LOG_DEBUG
,
1650 CFSTR("could not estabish default configuration for \"%@\": %s\n"),
1651 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
1652 SCErrorString(SCError()));
1653 SCNetworkServiceRemove(service
);
1658 ok
= SCNetworkSetAddService(set
, service
);
1660 SCLog(TRUE
, LOG_DEBUG
,
1661 CFSTR("could not add service for \"%@\": %s\n"),
1662 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
1663 SCErrorString(SCError()));
1664 SCNetworkServiceRemove(service
);
1672 add_supported_interfaces(interface_list
, interface
);
1677 CFArrayRemoveValueAtIndex(interface_list
, 0);
1679 CFRelease(interface_list
);
1681 if (updatedIFs
) CFRelease(interfaces
);
1682 if (services
!= NULL
) CFRelease(services
);
1683 if (excluded
!= NULL
) CFRelease(excluded
);
1685 #if TARGET_OS_IPHONE
1686 if (orphans
!= NULL
) {
1687 if (ok
&& updated
) {
1689 CFIndex n
= CFArrayGetCount(orphans
);
1691 for (i
= 0; i
< n
; i
++) {
1692 SCNetworkServiceRef service
;
1694 service
= CFArrayGetValueAtIndex(orphans
, i
);
1695 if (_SCNetworkServiceIsVPN(service
)) {
1696 ok
= SCNetworkSetAddService(set
, service
);
1706 #endif // TARGET_OS_IPHONE
1708 if (ok
&& !updated
) {
1709 // if no changes were made
1710 _SCErrorSet(kSCStatusOK
);
1718 SCNetworkSetEstablishDefaultConfiguration(SCNetworkSetRef set
)
1720 CFArrayRef interfaces
;
1721 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1722 Boolean updated
= FALSE
;
1724 if (!isA_SCNetworkSet(set
)) {
1725 _SCErrorSet(kSCStatusInvalidArgument
);
1729 interfaces
= _SCNetworkInterfaceCopyAllWithPreferences(setPrivate
->prefs
);
1730 if (interfaces
!= NULL
) {
1731 updated
= __SCNetworkSetEstablishDefaultConfigurationForInterfaces(set
, interfaces
, TRUE
);
1732 CFRelease(interfaces
);
1740 SCNetworkSetEstablishDefaultInterfaceConfiguration(SCNetworkSetRef set
, SCNetworkInterfaceRef interface
)
1742 CFArrayRef interfaces
;
1745 if (!isA_SCNetworkSet(set
)) {
1746 _SCErrorSet(kSCStatusInvalidArgument
);
1750 if (!isA_SCNetworkInterface(interface
)) {
1751 _SCErrorSet(kSCStatusInvalidArgument
);
1755 interfaces
= CFArrayCreate(NULL
, (const void **)&interface
, 1, &kCFTypeArrayCallBacks
);
1756 assert(interfaces
!= NULL
);
1757 updated
= __SCNetworkSetEstablishDefaultConfigurationForInterfaces(set
, interfaces
, FALSE
);
1758 CFRelease(interfaces
);
1765 SCNetworkSetCopySelectedVPNService(SCNetworkSetRef set
)
1769 SCNetworkServiceRef selected
= NULL
;
1770 CFArrayRef services
;
1771 CFMutableArrayRef services_vpn
= NULL
;
1773 if (!isA_SCNetworkSet(set
)) {
1774 _SCErrorSet(kSCStatusInvalidArgument
);
1778 services
= SCNetworkSetCopyServices(set
);
1779 if (services
!= NULL
) {
1780 n
= CFArrayGetCount(services
);
1781 for (i
= 0; i
< n
; i
++) {
1782 SCNetworkServiceRef service
;
1784 service
= CFArrayGetValueAtIndex(services
, i
);
1785 if (!SCNetworkServiceGetEnabled(service
)) {
1790 if (!_SCNetworkServiceIsVPN(service
)) {
1791 // if not VPN service
1795 if (services_vpn
== NULL
) {
1796 services_vpn
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1798 CFArrayAppendValue(services_vpn
, service
);
1801 CFRelease(services
);
1804 if (services_vpn
== NULL
) {
1805 // if no VPN services
1809 n
= CFArrayGetCount(services_vpn
);
1812 CFMutableArrayRef sorted
;
1814 order
= SCNetworkSetGetServiceOrder(set
);
1815 sorted
= CFArrayCreateMutableCopy(NULL
, 0, services_vpn
);
1816 CFArraySortValues(sorted
,
1817 CFRangeMake(0, CFArrayGetCount(sorted
)),
1818 _SCNetworkServiceCompare
,
1820 CFRelease(services_vpn
);
1821 services_vpn
= sorted
;
1824 #if TARGET_OS_IPHONE
1826 CFStringRef serviceID_prefs
;
1828 #define VPN_PREFERENCES CFSTR("com.apple.mobilevpn")
1829 #define VPN_SERVICE_ID CFSTR("activeVPNID")
1831 CFPreferencesAppSynchronize(VPN_PREFERENCES
);
1832 serviceID_prefs
= CFPreferencesCopyAppValue(VPN_SERVICE_ID
, VPN_PREFERENCES
);
1833 if (serviceID_prefs
!= NULL
) {
1834 for (i
= 0; i
< n
; i
++) {
1835 SCNetworkServiceRef service
;
1836 CFStringRef serviceID
;
1838 service
= CFArrayGetValueAtIndex(services_vpn
, i
);
1839 serviceID
= SCNetworkServiceGetServiceID(service
);
1840 if (CFEqual(serviceID
, serviceID_prefs
)) {
1848 CFRelease(serviceID_prefs
);
1851 #endif // TARGET_OS_IPHONE
1853 if (selected
== NULL
) {
1854 selected
= CFArrayGetValueAtIndex(services_vpn
, 0);
1858 CFRelease(services_vpn
);
1864 SCNetworkSetSetSelectedVPNService(SCNetworkSetRef set
, SCNetworkServiceRef service
)
1867 CFArrayRef services
;
1869 if (!isA_SCNetworkSet(set
)) {
1870 _SCErrorSet(kSCStatusInvalidArgument
);
1874 if (!isA_SCNetworkService(service
) || !_SCNetworkServiceIsVPN(service
)) {
1875 _SCErrorSet(kSCStatusInvalidArgument
);
1879 services
= SCNetworkSetCopyServices(set
);
1880 if (services
!= NULL
) {
1882 CFIndex n
= CFArrayGetCount(services
);
1884 if (!CFArrayContainsValue(services
, CFRangeMake(0, n
), service
)) {
1885 // if selected service not a member of the current set
1886 _SCErrorSet(kSCStatusInvalidArgument
);
1891 for (i
= 0; ok
&& (i
< n
); i
++) {
1892 SCNetworkServiceRef vpn
;
1894 vpn
= CFArrayGetValueAtIndex(services
, i
);
1895 if (!_SCNetworkServiceIsVPN(vpn
)) {
1896 // if not VPN service
1900 ok
= SCNetworkServiceSetEnabled(vpn
, CFEqual(service
, vpn
));
1906 if (services
!= NULL
) CFRelease(services
);
1912 _SCNetworkSetSetSetID(SCNetworkSetRef set
, CFStringRef newSetID
)
1914 SCNetworkSetRef currentSet
= NULL
;
1915 SCNetworkSetPrivateRef currentSetPrivate
= NULL
;
1916 CFDictionaryRef entity
;
1917 CFStringRef newPath
;
1919 CFStringRef oldPath
= NULL
;
1920 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1921 Boolean updateCurrentSet
= FALSE
;
1923 if (!isA_SCNetworkSet(set
)) {
1924 _SCErrorSet(kSCStatusInvalidArgument
);
1928 if (!isA_CFString(newSetID
)) {
1929 _SCErrorSet(kSCStatusInvalidArgument
);
1933 // If newSetID is equal to current setID, our work is done
1934 if (CFEqual(newSetID
, setPrivate
->setID
)) {
1938 newPath
= SCPreferencesPathKeyCreateSet(NULL
, newSetID
);
1939 entity
= SCPreferencesPathGetValue(setPrivate
->prefs
, newPath
);
1940 if (isA_CFDictionary(entity
)) {
1941 // if the new set already exists
1942 _SCErrorSet(kSCStatusKeyExists
);
1946 oldPath
= SCPreferencesPathKeyCreateSet(NULL
, setPrivate
->setID
);
1947 entity
= SCPreferencesPathGetValue(setPrivate
->prefs
, oldPath
);
1948 if (!isA_CFDictionary(entity
)) {
1949 // if the set has already been removed
1950 _SCErrorSet(kSCStatusNoKey
);
1954 ok
= SCPreferencesPathSetValue(setPrivate
->prefs
, newPath
, entity
);
1959 ok
= SCPreferencesPathRemoveValue(setPrivate
->prefs
, oldPath
);
1964 // update current set (if needed)
1965 currentSet
= SCNetworkSetCopyCurrent(setPrivate
->prefs
);
1966 if (currentSet
!= NULL
) {
1967 currentSetPrivate
= (SCNetworkSetPrivateRef
)currentSet
;
1968 if (CFEqual(currentSetPrivate
->setID
, setPrivate
->setID
)) {
1969 updateCurrentSet
= TRUE
;
1971 CFRelease(currentSet
);
1975 CFRelease(setPrivate
->setID
);
1977 setPrivate
->setID
= newSetID
;
1979 if (updateCurrentSet
) {
1980 SCNetworkSetSetCurrent(set
);
1985 if (oldPath
!= NULL
) {
1988 if (newPath
!= NULL
) {