2 * Copyright (c) 2004-2017 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 * Modification History
27 * May 13, 2004 Allan Nathanson <ajn@apple.com>
32 #include <CoreFoundation/CoreFoundation.h>
33 #include <CoreFoundation/CFRuntime.h>
34 #include "SCNetworkConfigurationInternal.h"
39 static CFStringRef
__SCNetworkSetCopyDescription (CFTypeRef cf
);
40 static void __SCNetworkSetDeallocate (CFTypeRef cf
);
41 static Boolean
__SCNetworkSetEqual (CFTypeRef cf1
, CFTypeRef cf2
);
42 static CFHashCode
__SCNetworkSetHash (CFTypeRef cf
);
45 static CFTypeID __kSCNetworkSetTypeID
= _kCFRuntimeNotATypeID
;
48 static const CFRuntimeClass __SCNetworkSetClass
= {
50 "SCNetworkSet", // className
53 __SCNetworkSetDeallocate
, // dealloc
54 __SCNetworkSetEqual
, // equal
55 __SCNetworkSetHash
, // hash
56 NULL
, // copyFormattingDesc
57 __SCNetworkSetCopyDescription
// copyDebugDesc
61 static pthread_once_t initialized
= PTHREAD_ONCE_INIT
;
65 __SCNetworkSetCopyDescription(CFTypeRef cf
)
67 CFAllocatorRef allocator
= CFGetAllocator(cf
);
68 CFMutableStringRef result
;
69 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)cf
;
71 result
= CFStringCreateMutable(allocator
, 0);
72 CFStringAppendFormat(result
, NULL
, CFSTR("<SCNetworkSet %p [%p]> {"), cf
, allocator
);
73 CFStringAppendFormat(result
, NULL
, CFSTR("id = %@"), setPrivate
->setID
);
74 CFStringAppendFormat(result
, NULL
, CFSTR(", prefs = %p"), setPrivate
->prefs
);
75 if (setPrivate
->name
!= NULL
) {
76 CFStringAppendFormat(result
, NULL
, CFSTR(", name = %@"), setPrivate
->name
);
78 CFStringAppendFormat(result
, NULL
, CFSTR("}"));
85 __SCNetworkSetDeallocate(CFTypeRef cf
)
87 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)cf
;
89 /* release resources */
91 CFRelease(setPrivate
->setID
);
92 CFRelease(setPrivate
->prefs
);
93 if (setPrivate
->name
!= NULL
)
94 CFRelease(setPrivate
->name
);
101 __SCNetworkSetEqual(CFTypeRef cf1
, CFTypeRef cf2
)
103 SCNetworkSetPrivateRef s1
= (SCNetworkSetPrivateRef
)cf1
;
104 SCNetworkSetPrivateRef s2
= (SCNetworkSetPrivateRef
)cf2
;
109 if (s1
->prefs
!= s2
->prefs
)
110 return FALSE
; // if not the same prefs
112 if (!CFEqual(s1
->setID
, s2
->setID
))
113 return FALSE
; // if not the same set identifier
120 __SCNetworkSetHash(CFTypeRef cf
)
122 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)cf
;
124 return CFHash(setPrivate
->setID
);
129 __SCNetworkSetInitialize(void)
131 __kSCNetworkSetTypeID
= _CFRuntimeRegisterClass(&__SCNetworkSetClass
);
136 static SCNetworkSetPrivateRef
137 __SCNetworkSetCreatePrivate(CFAllocatorRef allocator
,
138 SCPreferencesRef prefs
,
141 SCNetworkSetPrivateRef setPrivate
;
144 /* initialize runtime */
145 pthread_once(&initialized
, __SCNetworkSetInitialize
);
147 /* allocate target */
148 size
= sizeof(SCNetworkSetPrivate
) - sizeof(CFRuntimeBase
);
149 setPrivate
= (SCNetworkSetPrivateRef
)_CFRuntimeCreateInstance(allocator
,
150 __kSCNetworkSetTypeID
,
153 if (setPrivate
== NULL
) {
157 /* initialize non-zero/NULL members */
158 setPrivate
->setID
= CFStringCreateCopy(NULL
, setID
);
159 setPrivate
->prefs
= CFRetain(prefs
);
169 _serviceOrder(SCNetworkServiceRef service
)
171 SCNetworkInterfaceRef interface
;
173 interface
= SCNetworkServiceGetInterface(service
);
174 if ((interface
== NULL
) || _SCNetworkServiceIsVPN(service
)) {
175 return 100000; // if unknown or VPN interface, sort last
178 return __SCNetworkInterfaceOrder(interface
);
183 _serviceOrder_add(SCNetworkSetRef set
, SCNetworkServiceRef service
)
187 CFMutableArrayRef newOrder
;
189 CFStringRef serviceID
;
190 CFIndex serviceOrder
;
191 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
194 order
= SCNetworkSetGetServiceOrder(set
);
196 newOrder
= CFArrayCreateMutableCopy(NULL
, 0, order
);
198 newOrder
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
200 assert(newOrder
!= NULL
);
201 n
= CFArrayGetCount(newOrder
);
203 serviceID
= SCNetworkServiceGetServiceID(service
);
204 if (CFArrayContainsValue(newOrder
, CFRangeMake(0, n
), serviceID
)) {
205 // if serviceID already present
209 serviceOrder
= _serviceOrder(service
);
212 for (i
= 0; i
< n
; i
++) {
214 SCNetworkServiceRef slotService
;
215 CFStringRef slotServiceID
;
217 slotServiceID
= CFArrayGetValueAtIndex(newOrder
, i
);
218 if (!isA_CFString(slotServiceID
)) {
223 slotService
= SCNetworkServiceCopy(setPrivate
->prefs
, slotServiceID
);
224 if (slotService
== NULL
) {
225 // if serviceID not valid
229 slotOrder
= _serviceOrder(slotService
);
230 if (serviceOrder
>= slotOrder
) {
231 // add the service *after* this one
235 CFRelease(slotService
);
238 CFArrayInsertValueAtIndex(newOrder
, slot
, serviceID
);
239 (void) SCNetworkSetSetServiceOrder(set
, newOrder
);
250 _serviceOrder_remove(SCNetworkSetRef set
, SCNetworkServiceRef service
)
252 CFMutableArrayRef newOrder
;
254 CFStringRef serviceID
;
256 order
= SCNetworkSetGetServiceOrder(set
);
261 serviceID
= SCNetworkServiceGetServiceID(service
);
263 newOrder
= CFArrayCreateMutableCopy(NULL
, 0, order
);
267 i
= CFArrayGetFirstIndexOfValue(newOrder
,
268 CFRangeMake(0, CFArrayGetCount(newOrder
)),
270 if (i
== kCFNotFound
) {
274 CFArrayRemoveValueAtIndex(newOrder
, i
);
276 (void) SCNetworkSetSetServiceOrder(set
, newOrder
);
284 #pragma mark SCNetworkSet APIs
290 #define PREVENT_DUPLICATE_SERVICE_NAMES
291 #ifdef PREVENT_DUPLICATE_SERVICE_NAMES
293 copy_next_name(CFStringRef name
)
295 CFArrayRef components
;
297 CFMutableArrayRef newComponents
;
304 components
= CFStringCreateArrayBySeparatingStrings(NULL
, name
, CFSTR(" "));
305 if (components
!= NULL
) {
306 newComponents
= CFArrayCreateMutableCopy(NULL
, 0, components
);
307 CFRelease(components
);
309 newComponents
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
310 CFArrayAppendValue(newComponents
, name
);
313 n
= CFArrayGetCount(newComponents
);
317 str
= CFArrayGetValueAtIndex(newComponents
, n
- 1);
318 suffix
= CFStringGetIntValue(str
);
320 CFArrayRemoveValueAtIndex(newComponents
, n
- 1);
326 name
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%d"), (int)suffix
);
327 CFArrayAppendValue(newComponents
, name
);
330 name
= CFStringCreateByCombiningStrings(NULL
, newComponents
, CFSTR(" "));
331 CFRelease(newComponents
);
338 ensure_unique_service_name(SCNetworkServiceRef service
)
340 SCNetworkInterfaceRef interface
;
344 interface
= SCNetworkServiceGetInterface(service
);
346 name
= SCNetworkServiceGetName(service
);
354 ok
= SCNetworkServiceSetName(service
, name
);
359 if (SCError() != kSCStatusKeyExists
) {
360 SC_log(LOG_INFO
, "could not update service name for \"%@\": %s",
361 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
362 SCErrorString(SCError()));
366 newName
= copy_next_name(name
);
367 if (newName
== NULL
) {
368 SC_log(LOG_INFO
, "could not create unique name for \"%@\": %s",
369 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
370 SCErrorString(SCError()));
374 // try again with the "new" name
387 #endif // PREVENT_DUPLICATE_SERVICE_NAMES
391 SCNetworkSetAddService(SCNetworkSetRef set
, SCNetworkServiceRef service
)
393 SCNetworkInterfaceRef interface
;
394 CFArrayRef interface_config
= NULL
;
398 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
399 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
401 if (!isA_SCNetworkSet(set
)) {
402 _SCErrorSet(kSCStatusInvalidArgument
);
406 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
407 _SCErrorSet(kSCStatusInvalidArgument
);
411 // make sure that we do not add an orphaned network service if its
412 // associated interface is a member of a bond or bridge.
413 interface
= SCNetworkServiceGetInterface(service
);
414 if ((interface
!= NULL
) &&
415 __SCNetworkInterfaceIsMember(servicePrivate
->prefs
, interface
)) {
416 _SCErrorSet(kSCStatusKeyExists
);
420 //#define PREVENT_DUPLICATE_SETS
421 #ifdef PREVENT_DUPLICATE_SETS
424 // ensure that each service is only a member of ONE set
425 sets
= SCNetworkSetCopyAll(setPrivate
->prefs
);
430 n
= CFArrayGetCount(sets
);
431 for (i
= 0; i
< n
; i
++) {
436 set
= CFArrayGetValueAtIndex(sets
, i
);
437 services
= SCNetworkSetCopyServices(set
);
438 found
= CFArrayContainsValue(services
,
439 CFRangeMake(0, CFArrayGetCount(services
)),
445 _SCErrorSet(kSCStatusKeyExists
);
451 #endif /* PREVENT_DUPLICATE_SETS */
453 // get the [deep] interface configuration settings
454 interface
= SCNetworkServiceGetInterface(service
);
455 if (interface
!= NULL
) {
456 interface_config
= __SCNetworkInterfaceCopyDeepConfiguration(set
, interface
);
459 // create the link between "set" and the "service"
460 path
= SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL
, // allocator
461 setPrivate
->setID
, // set
462 servicePrivate
->serviceID
, // service
464 link
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
465 servicePrivate
->serviceID
, // service
467 ok
= SCPreferencesPathSetLink(setPrivate
->prefs
, path
, link
);
468 #ifdef PREVENT_DUPLICATE_SERVICE_NAMES
470 ok
= ensure_unique_service_name(service
);
472 // if we could not ensure a unique name, remove the (just added)
473 // link between the "set" and the "service"
474 (void) SCPreferencesPathRemoveValue(setPrivate
->prefs
, path
);
477 #endif // PREVENT_DUPLICATE_SERVICE_NAMES
484 // push the [deep] interface configuration into all sets which contain this service.
485 if (interface
!= NULL
) {
486 __SCNetworkInterfaceSetDeepConfiguration(set
, interface
, interface_config
);
489 // add service to ServiceOrder
490 _serviceOrder_add(set
, service
);
492 // mark set as no longer "new"
493 setPrivate
->established
= TRUE
;
498 SC_log(LOG_DEBUG
, "SCNetworkSetAddService(): %@, %@", set
, service
);
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 CFDictionaryRef entity
;
781 CFStringRef interfacePath
;
782 Boolean skip
= FALSE
;
784 interfacePath
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
785 serviceID
, // service
786 kSCEntNetInterface
); // entity
787 entity
= SCPreferencesPathGetValue(setPrivate
->prefs
, interfacePath
);
788 CFRelease(interfacePath
);
790 if (__SCNetworkInterfaceEntityIsPPTP(entity
)) {
791 SC_log(LOG_INFO
, "PPTP services are no longer supported");
796 SCNetworkServicePrivateRef servicePrivate
;
798 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
,
802 CFArrayAppendValue(array
, (SCNetworkServiceRef
)servicePrivate
);
803 CFRelease(servicePrivate
);
808 CFRelease(components
);
810 if (keys
!= keys_q
) {
811 CFAllocatorDeallocate(NULL
, keys
);
820 SCNetworkSetCreate(SCPreferencesRef prefs
)
822 CFArrayRef components
;
823 CFDictionaryRef entity
;
828 SCNetworkSetPrivateRef setPrivate
;
830 prefix
= SCPreferencesPathKeyCreateSets(NULL
);
831 path
= __SCPreferencesPathCreateUniqueChild_WithMoreSCFCompatibility(prefs
, prefix
);
832 if (path
== NULL
) path
= SCPreferencesPathCreateUniqueChild(prefs
, prefix
);
838 components
= CFStringCreateArrayBySeparatingStrings(NULL
, path
, CFSTR("/"));
839 setID
= CFArrayGetValueAtIndex(components
, 2);
840 setPrivate
= __SCNetworkSetCreatePrivate(NULL
, prefs
, setID
);
841 assert(setPrivate
!= NULL
);
842 CFRelease(components
);
844 // mark set as "new" (not yet established)
845 setPrivate
->established
= FALSE
;
847 // establish the set in the preferences
848 entity
= CFDictionaryCreate(NULL
,
850 &kCFTypeDictionaryKeyCallBacks
,
851 &kCFTypeDictionaryValueCallBacks
);
852 ok
= SCPreferencesPathSetValue(prefs
, path
, entity
);
856 CFRelease(setPrivate
);
860 if (setPrivate
!= NULL
) {
861 SC_log(LOG_DEBUG
, "SCNetworkSetCreate(): %@", setPrivate
);
864 return (SCNetworkSetRef
)setPrivate
;
869 _SCNetworkSetCreateDefault(SCPreferencesRef prefs
)
874 CFStringRef setName
= NULL
;
876 set
= SCNetworkSetCopyCurrent(prefs
);
878 SC_log(LOG_NOTICE
, "creating default set w/already existing set");
880 _SCErrorSet(kSCStatusKeyExists
);
884 // create a new ("Automatic") set
885 set
= SCNetworkSetCreate(prefs
);
887 SC_log(LOG_NOTICE
, "could not create \"new\" set: %s",
888 SCErrorString(SCError()));
892 bundle
= _SC_CFBundleGet();
893 if (bundle
!= NULL
) {
894 setName
= CFBundleCopyLocalizedString(bundle
,
895 CFSTR("DEFAULT_SET_NAME"),
900 ok
= SCNetworkSetSetName(set
, (setName
!= NULL
) ? setName
: CFSTR("Automatic"));
902 // if we could not save the new set's "name"
903 SC_log(LOG_NOTICE
, "could not save the new set's name: %s",
904 SCErrorString(SCError()));
908 ok
= SCNetworkSetSetCurrent(set
);
910 // if we could not make this the "current" set
911 SC_log(LOG_NOTICE
, "could not establish new set as current: %s",
912 SCErrorString(SCError()));
918 if (!ok
&& (set
!= NULL
)) {
919 SCNetworkSetRemove(set
);
923 if (setName
!= NULL
) CFRelease(setName
);
929 SCNetworkSetGetSetID(SCNetworkSetRef set
)
931 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
933 if (!isA_SCNetworkSet(set
)) {
934 _SCErrorSet(kSCStatusInvalidArgument
);
938 return setPrivate
->setID
;
943 SCNetworkSetGetName(SCNetworkSetRef set
)
946 CFDictionaryRef entity
;
948 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
950 if (!isA_SCNetworkSet(set
)) {
951 _SCErrorSet(kSCStatusInvalidArgument
);
955 if (setPrivate
->name
!= NULL
) {
956 return setPrivate
->name
;
959 path
= SCPreferencesPathKeyCreateSet(NULL
, setPrivate
->setID
);
960 entity
= SCPreferencesPathGetValue(setPrivate
->prefs
, path
);
963 if (isA_CFDictionary(entity
)) {
966 name
= CFDictionaryGetValue(entity
, kSCPropUserDefinedName
);
967 if (isA_CFString(name
)) {
968 setPrivate
->name
= CFRetain(name
);
972 bundle
= _SC_CFBundleGet();
973 if (bundle
!= NULL
) {
974 if (setPrivate
->name
!= NULL
) {
975 CFStringRef non_localized
;
977 non_localized
= _SC_CFBundleCopyNonLocalizedString(bundle
,
978 CFSTR("DEFAULT_SET_NAME"),
981 if (non_localized
!= NULL
) {
982 if (CFEqual(setPrivate
->name
, non_localized
)) {
983 CFStringRef localized
;
985 // if "Automatic", return localized name
986 localized
= CFBundleCopyLocalizedString(bundle
,
987 CFSTR("DEFAULT_SET_NAME"),
990 if (localized
!= NULL
) {
991 CFRelease(setPrivate
->name
);
992 setPrivate
->name
= localized
;
996 CFRelease(non_localized
);
1001 return setPrivate
->name
;
1005 CFArrayRef
/* of serviceID CFStringRef's */
1006 SCNetworkSetGetServiceOrder(SCNetworkSetRef set
)
1008 CFDictionaryRef dict
;
1010 CFArrayRef serviceOrder
;
1011 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1013 if (!isA_SCNetworkSet(set
)) {
1014 _SCErrorSet(kSCStatusInvalidArgument
);
1018 path
= SCPreferencesPathKeyCreateSetNetworkGlobalEntity(NULL
, setPrivate
->setID
, kSCEntNetIPv4
);
1023 dict
= SCPreferencesPathGetValue(setPrivate
->prefs
, path
);
1025 if (!isA_CFDictionary(dict
)) {
1029 serviceOrder
= CFDictionaryGetValue(dict
, kSCPropNetServiceOrder
);
1030 serviceOrder
= isA_CFArray(serviceOrder
);
1032 return serviceOrder
;
1037 SCNetworkSetGetTypeID(void)
1039 pthread_once(&initialized
, __SCNetworkSetInitialize
); /* initialize runtime */
1040 return __kSCNetworkSetTypeID
;
1045 SCNetworkSetRemove(SCNetworkSetRef set
)
1047 CFStringRef currentPath
;
1050 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1052 if (!isA_SCNetworkSet(set
)) {
1053 _SCErrorSet(kSCStatusInvalidArgument
);
1057 currentPath
= SCPreferencesGetValue(setPrivate
->prefs
, kSCPrefCurrentSet
);
1058 path
= SCPreferencesPathKeyCreateSet(NULL
, setPrivate
->setID
);
1059 if (!isA_CFString(currentPath
) || !CFEqual(currentPath
, path
)) {
1060 ok
= SCPreferencesPathRemoveValue(setPrivate
->prefs
, path
);
1062 SC_log(LOG_DEBUG
, "SCNetworkSetRemove() failed, currently active: %@", setPrivate
->setID
);
1063 _SCErrorSet(kSCStatusInvalidArgument
);
1068 SC_log(LOG_DEBUG
, "SCNetworkSetRemove(): %@", set
);
1076 SCNetworkSetRemoveService(SCNetworkSetRef set
, SCNetworkServiceRef service
)
1078 SCNetworkInterfaceRef interface
;
1079 CFArrayRef interface_config
= NULL
;
1082 int sc_status
= kSCStatusOK
;
1083 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1084 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1086 if (!isA_SCNetworkSet(set
)) {
1087 _SCErrorSet(kSCStatusInvalidArgument
);
1091 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1092 _SCErrorSet(kSCStatusInvalidArgument
);
1096 // remove service from ServiceOrder
1097 _serviceOrder_remove(set
, service
);
1099 // get the [deep] interface configuration settings
1100 interface
= SCNetworkServiceGetInterface(service
);
1101 if (interface
!= NULL
) {
1102 interface_config
= __SCNetworkInterfaceCopyDeepConfiguration(set
, interface
);
1103 if (interface_config
!= NULL
) {
1104 // remove the interface configuration from all sets which contain this service.
1105 __SCNetworkInterfaceSetDeepConfiguration(set
, interface
, NULL
);
1109 // remove the link between "set" and the "service"
1110 path
= SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL
,
1112 servicePrivate
->serviceID
,
1114 ok
= SCPreferencesPathRemoveValue(setPrivate
->prefs
, path
);
1116 sc_status
= SCError(); // preserve the error
1120 // push the [deep] interface configuration [back] into all sets which contain the service.
1121 if (interface_config
!= NULL
) {
1122 __SCNetworkInterfaceSetDeepConfiguration(set
, interface
, interface_config
);
1123 CFRelease(interface_config
);
1127 SC_log(LOG_DEBUG
, "SCNetworkSetRemoveService(): %@, %@", set
, service
);
1129 _SCErrorSet(sc_status
);
1137 SCNetworkSetSetCurrent(SCNetworkSetRef set
)
1141 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1143 if (!isA_SCNetworkSet(set
)) {
1144 _SCErrorSet(kSCStatusInvalidArgument
);
1148 path
= SCPreferencesPathKeyCreateSet(NULL
, setPrivate
->setID
);
1149 ok
= SCPreferencesSetValue(setPrivate
->prefs
, kSCPrefCurrentSet
, path
);
1153 SC_log(LOG_DEBUG
, "SCNetworkSetSetCurrent(): %@", set
);
1161 SCNetworkSetSetName(SCNetworkSetRef set
, CFStringRef name
)
1163 CFBundleRef bundle
= NULL
;
1164 CFDictionaryRef entity
;
1165 CFStringRef localized
= NULL
;
1166 CFStringRef non_localized
= NULL
;
1169 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1171 if (!isA_SCNetworkSet(set
)) {
1172 _SCErrorSet(kSCStatusInvalidArgument
);
1176 if ((name
!= NULL
) && !isA_CFString(name
)) {
1177 _SCErrorSet(kSCStatusInvalidArgument
);
1181 // if known, compare against localized name
1184 bundle
= _SC_CFBundleGet();
1185 if (bundle
!= NULL
) {
1186 non_localized
= _SC_CFBundleCopyNonLocalizedString(bundle
,
1187 CFSTR("DEFAULT_SET_NAME"),
1190 if (non_localized
!= NULL
) {
1191 if (CFEqual(name
, non_localized
)) {
1192 localized
= CFBundleCopyLocalizedString(bundle
,
1193 CFSTR("DEFAULT_SET_NAME"),
1196 if (localized
!= NULL
) {
1204 #define PREVENT_DUPLICATE_SET_NAMES
1205 #ifdef PREVENT_DUPLICATE_SET_NAMES
1209 // ensure that each set is uniquely named
1211 sets
= SCNetworkSetCopyAll(setPrivate
->prefs
);
1216 n
= CFArrayGetCount(sets
);
1217 for (i
= 0; i
< n
; i
++) {
1218 CFStringRef otherID
;
1219 CFStringRef otherName
;
1220 SCNetworkSetRef set
= CFArrayGetValueAtIndex(sets
, i
);
1222 otherID
= SCNetworkSetGetSetID(set
);
1223 if (CFEqual(setPrivate
->setID
, otherID
)) {
1224 continue; // skip current set
1227 otherName
= SCNetworkSetGetName(set
);
1228 if ((otherName
!= NULL
) && CFEqual(name
, otherName
)) {
1229 // if "name" not unique
1231 _SCErrorSet(kSCStatusKeyExists
);
1238 #endif /* PREVENT_DUPLICATE_SET_NAMES */
1240 // if known, store non-localized name
1242 if ((name
!= NULL
) && (bundle
!= NULL
) && (non_localized
!= NULL
)) {
1243 if (localized
== NULL
) {
1244 localized
= CFBundleCopyLocalizedString(bundle
,
1245 CFSTR("DEFAULT_SET_NAME"),
1250 if (localized
!= NULL
) {
1251 if (CFEqual(name
, localized
)) {
1252 name
= non_localized
;
1257 // update the "name"
1259 path
= SCPreferencesPathKeyCreateSet(NULL
, setPrivate
->setID
);
1260 entity
= SCPreferencesPathGetValue(setPrivate
->prefs
, path
);
1261 if (isA_CFDictionary(entity
) ||
1262 ((entity
== NULL
) && (name
!= NULL
))) {
1263 CFMutableDictionaryRef newEntity
;
1265 if (entity
!= NULL
) {
1266 newEntity
= CFDictionaryCreateMutableCopy(NULL
, 0, entity
);
1268 newEntity
= CFDictionaryCreateMutable(NULL
,
1270 &kCFTypeDictionaryKeyCallBacks
,
1271 &kCFTypeDictionaryValueCallBacks
);
1274 CFDictionarySetValue(newEntity
, kSCPropUserDefinedName
, name
);
1276 CFDictionaryRemoveValue(newEntity
, kSCPropUserDefinedName
);
1278 ok
= SCPreferencesPathSetValue(setPrivate
->prefs
, path
, newEntity
);
1279 CFRelease(newEntity
);
1286 SC_log(LOG_DEBUG
, "SCNetworkSetSetName(): %@", set
);
1289 if (localized
!= NULL
) CFRelease(localized
);
1290 if (non_localized
!= NULL
) CFRelease(non_localized
);
1296 SCNetworkSetSetServiceOrder(SCNetworkSetRef set
, CFArrayRef newOrder
)
1298 CFDictionaryRef dict
;
1299 CFMutableDictionaryRef newDict
;
1302 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1304 if (!isA_SCNetworkSet(set
)) {
1305 _SCErrorSet(kSCStatusInvalidArgument
);
1309 if (isA_CFArray(newOrder
)) {
1311 CFIndex n
= CFArrayGetCount(newOrder
);
1313 for (i
= 0; i
< n
; i
++) {
1314 CFStringRef serviceID
;
1316 serviceID
= CFArrayGetValueAtIndex(newOrder
, i
);
1317 if (!isA_CFString(serviceID
)) {
1318 _SCErrorSet(kSCStatusInvalidArgument
);
1323 _SCErrorSet(kSCStatusInvalidArgument
);
1327 path
= SCPreferencesPathKeyCreateSetNetworkGlobalEntity(NULL
, setPrivate
->setID
, kSCEntNetIPv4
);
1332 dict
= SCPreferencesPathGetValue(setPrivate
->prefs
, path
);
1334 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
1336 newDict
= CFDictionaryCreateMutable(NULL
,
1338 &kCFTypeDictionaryKeyCallBacks
,
1339 &kCFTypeDictionaryValueCallBacks
);
1342 CFDictionarySetValue(newDict
, kSCPropNetServiceOrder
, newOrder
);
1343 ok
= SCPreferencesPathSetValue(setPrivate
->prefs
, path
, newDict
);
1352 #pragma mark SCNetworkSet SPIs
1356 add_supported_interfaces(CFMutableArrayRef interface_list
, SCNetworkInterfaceRef interface
)
1359 CFArrayRef interface_types
;
1362 interface_types
= SCNetworkInterfaceGetSupportedInterfaceTypes(interface
);
1363 n
= (interface_types
!= NULL
) ? CFArrayGetCount(interface_types
) : 0;
1364 for (i
= 0; i
< n
; i
++) {
1365 SCNetworkInterfaceRef parent
;
1366 CFStringRef interface_type
;
1368 interface_type
= CFArrayGetValueAtIndex(interface_types
, i
);
1369 parent
= SCNetworkInterfaceCreateWithInterface(interface
, interface_type
);
1370 if (parent
!= NULL
) {
1371 CFArrayAppendValue(interface_list
, parent
);
1380 static CFSetRef
/* of SCNetworkInterfaceRef's */
1381 copyExcludedInterfaces(SCPreferencesRef prefs
)
1383 CFMutableSetRef excluded
;
1384 CFArrayRef interfaces
;
1386 excluded
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
1388 #if !TARGET_OS_IPHONE
1389 // exclude Bond [member] interfaces
1390 interfaces
= SCBondInterfaceCopyAll(prefs
);
1391 if (interfaces
!= NULL
) {
1392 __SCBondInterfaceListCollectMembers(interfaces
, excluded
);
1393 CFRelease(interfaces
);
1395 #endif // !TARGET_OS_IPHONE
1397 // exclude Bridge [member] interfaces
1398 interfaces
= SCBridgeInterfaceCopyAll(prefs
);
1399 if (interfaces
!= NULL
) {
1400 __SCBridgeInterfaceListCollectMembers(interfaces
, excluded
);
1401 CFRelease(interfaces
);
1408 #if !TARGET_OS_IPHONE
1409 static SCBridgeInterfaceRef
1410 copyAutoBridgeInterface(SCPreferencesRef prefs
, CFStringRef bridgeName
)
1412 SCBridgeInterfaceRef bridge
= NULL
;
1413 CFArrayRef interfaces
;
1415 // exclude Bridge [member] interfaces
1416 interfaces
= SCBridgeInterfaceCopyAll(prefs
);
1417 if (interfaces
!= NULL
) {
1421 n
= CFArrayGetCount(interfaces
);
1422 for (i
= 0; i
< n
; i
++) {
1423 SCBridgeInterfaceRef interface
;
1424 CFStringRef name
= NULL
;
1425 CFDictionaryRef options
;
1427 interface
= CFArrayGetValueAtIndex(interfaces
, i
);
1428 options
= SCBridgeInterfaceGetOptions(interface
);
1429 if ((options
!= NULL
) &&
1430 CFDictionaryGetValueIfPresent(options
,
1432 (const void **)&name
) &&
1433 _SC_CFEqual(name
, bridgeName
)) {
1440 CFRelease(interfaces
);
1443 if (bridge
== NULL
) {
1444 bridge
= SCBridgeInterfaceCreate(prefs
);
1445 if (bridge
!= NULL
) {
1446 CFMutableDictionaryRef newOptions
;
1449 newOptions
= CFDictionaryCreateMutable(NULL
, 0,
1450 &kCFTypeDictionaryKeyCallBacks
,
1451 &kCFTypeDictionaryValueCallBacks
);
1452 CFDictionarySetValue(newOptions
, CFSTR("__AUTO__"), bridgeName
);
1453 ok
= SCBridgeInterfaceSetOptions(bridge
, newOptions
);
1454 CFRelease(newOptions
);
1464 #endif // !TARGET_OS_IPHONE
1468 copyServices(SCNetworkSetRef set
)
1470 CFArrayRef services
;
1471 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1473 // first, assume that we only want to add new services
1474 // for those interfaces that are not represented in the
1476 services
= SCNetworkSetCopyServices(set
);
1477 if ((services
!= NULL
) && setPrivate
->established
) {
1478 // but, if we are given an existing (or "established") set
1479 // than we only want to add new services for those interfaces
1480 // that are not represented in *any* set.
1481 CFRelease(services
);
1482 services
= SCNetworkServiceCopyAll(setPrivate
->prefs
);
1489 #if !TARGET_OS_IPHONE
1491 updateServices(CFArrayRef services
, SCNetworkInterfaceRef interface
)
1493 CFStringRef bsdName
;
1496 CFMutableArrayRef newServices
;
1498 if (services
== NULL
) {
1502 bsdName
= SCNetworkInterfaceGetBSDName(interface
);
1504 newServices
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1506 n
= CFArrayGetCount(services
);
1507 for (i
= 0; i
< n
; i
++) {
1508 SCNetworkInterfaceRef interface
;
1509 CFStringRef interfaceName
;
1510 SCNetworkServiceRef newService
;
1511 SCNetworkServiceRef service
;
1512 CFStringRef serviceID
;
1513 SCNetworkServicePrivateRef servicePrivate
;
1515 service
= CFArrayGetValueAtIndex(services
, i
);
1516 interface
= SCNetworkServiceGetInterface(service
);
1517 interfaceName
= SCNetworkInterfaceGetBSDName(interface
);
1518 if (!_SC_CFEqual(interfaceName
, bsdName
)) {
1519 // if not a match, retain
1520 CFArrayAppendValue(newServices
, service
);
1524 // if a match, update
1525 serviceID
= SCNetworkServiceGetServiceID(service
);
1526 servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1527 newService
= SCNetworkServiceCopy(servicePrivate
->prefs
, serviceID
);
1528 if (newService
!= NULL
) {
1529 CFArrayAppendValue(newServices
, newService
);
1530 CFRelease(newService
);
1536 #endif // !TARGET_OS_IPHONE
1539 static __inline__ Boolean
1540 skipInterface(SCNetworkInterfaceRef interface
)
1544 action
= _SCNetworkInterfaceGetConfigurationAction(interface
);
1545 if (isA_CFString(action
) &&
1546 CFEqual(action
, kSCNetworkInterfaceConfigurationActionValueNone
)) {
1555 __SCNetworkSetEstablishDefaultConfigurationForInterfaces(SCNetworkSetRef set
, CFArrayRef interfaces
, Boolean excludeHidden
)
1557 CFSetRef excluded
= NULL
;
1561 CFArrayRef services
;
1562 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1563 Boolean updated
= FALSE
;
1564 #if !TARGET_OS_IPHONE
1565 Boolean updatedIFs
= FALSE
;
1566 #endif // !TARGET_OS_IPHONE
1568 #if TARGET_OS_IPHONE
1569 CFArrayRef orphans
= NULL
;
1572 sets
= SCNetworkSetCopyAll(setPrivate
->prefs
);
1574 if (CFArrayGetCount(sets
) == 1) {
1575 services
= SCNetworkSetCopyServices(set
);
1576 if (services
!= NULL
) {
1577 n
= CFArrayGetCount(services
);
1578 CFRelease(services
);
1581 if ((n
== 0) && CFEqual(set
, CFArrayGetValueAtIndex(sets
, 0))) {
1582 // after a "Reset Network Settings" we need to find (and
1583 // add back) any VPN services that were orphaned.
1584 orphans
= SCNetworkServiceCopyAll(setPrivate
->prefs
);
1590 #endif // TARGET_OS_IPHONE
1592 // copy network services
1593 services
= copyServices(set
);
1595 // copy network interfaces to be excluded
1596 excluded
= copyExcludedInterfaces(setPrivate
->prefs
);
1598 #if !TARGET_OS_IPHONE
1599 // look for interfaces that should auto-magically be added
1600 // to an Ethernet bridge
1601 n
= (interfaces
!= NULL
) ? CFArrayGetCount(interfaces
) : 0;
1602 for (i
= 0; i
< n
; i
++) {
1603 SCBridgeInterfaceRef bridge
= NULL
;
1604 SCNetworkInterfaceRef interface
;
1606 interface
= CFArrayGetValueAtIndex(interfaces
, i
);
1608 if (excludeHidden
&& skipInterface(interface
)) {
1609 // if not auto-configure
1613 if ((excluded
!= NULL
)
1614 && CFSetContainsValue(excluded
, interface
)) {
1615 // if this interface is a member of a Bond or Bridge
1619 if (__SCNetworkServiceExistsForInterface(services
, interface
)) {
1620 // if this is not a new interface
1624 if (_SCNetworkInterfaceIsBuiltin(interface
) &&
1625 _SCNetworkInterfaceIsThunderbolt(interface
) &&
1626 !isA_SCBridgeInterface(interface
)) {
1627 // add built-in Thunderbolt interfaces to bridge
1628 bridge
= copyAutoBridgeInterface(setPrivate
->prefs
, CFSTR("thunderbolt-bridge"));
1631 if (bridge
!= NULL
) {
1632 CFIndex bridgeIndex
;
1634 CFMutableArrayRef newMembers
;
1635 CFMutableSetRef newExcluded
;
1636 CFMutableArrayRef newInterfaces
;
1637 CFArrayRef newServices
;
1639 // track the bridge interface (if it's in our list)
1640 bridgeIndex
= CFArrayGetFirstIndexOfValue(interfaces
,
1641 CFRangeMake(0, CFArrayGetCount(interfaces
)),
1644 // add new member interface
1645 members
= SCBridgeInterfaceGetMemberInterfaces(bridge
);
1646 if ((members
!= NULL
) && (CFArrayGetCount(members
) > 0)) {
1647 newMembers
= CFArrayCreateMutableCopy(NULL
, 0, members
);
1648 updated
= TRUE
; // if we're updating an existing bridge
1650 newMembers
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1652 CFArrayAppendValue(newMembers
, interface
);
1653 ok
= SCBridgeInterfaceSetMemberInterfaces(bridge
, newMembers
);
1654 CFRelease(newMembers
);
1656 SC_log(LOG_INFO
, "could not update bridge with \"%@\": %s",
1657 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
1658 SCErrorString(SCError()));
1663 // exclude the new member interface
1664 newExcluded
= CFSetCreateMutableCopy(NULL
, 0, excluded
);
1665 CFRelease(excluded
);
1666 CFSetAddValue(newExcluded
, interface
);
1667 excluded
= newExcluded
;
1669 // update the list of interfaces to include the [new or updated] bridge
1670 newInterfaces
= CFArrayCreateMutableCopy(NULL
, 0, interfaces
);
1671 if (bridgeIndex
!= kCFNotFound
) {
1672 CFArraySetValueAtIndex(newInterfaces
, bridgeIndex
, bridge
);
1674 CFArrayAppendValue(newInterfaces
, bridge
);
1677 CFRelease(interfaces
);
1679 interfaces
= newInterfaces
;
1682 // refresh [existing] services
1683 newServices
= updateServices(services
, bridge
);
1684 if (newServices
!= NULL
) {
1685 CFRelease(services
);
1686 services
= newServices
;
1692 #endif // !TARGET_OS_IPHONE
1694 n
= (interfaces
!= NULL
) ? CFArrayGetCount(interfaces
) : 0;
1695 for (i
= 0; i
< n
; i
++) {
1696 SCNetworkInterfaceRef interface
;
1697 CFMutableArrayRef interface_list
;
1699 interface
= CFArrayGetValueAtIndex(interfaces
, i
);
1701 if (excludeHidden
&& skipInterface(interface
)) {
1702 // if not auto-configure
1706 if ((excluded
!= NULL
)
1707 && CFSetContainsValue(excluded
, interface
)) {
1708 // if this interface is a member of a Bond or Bridge
1712 if (__SCNetworkServiceExistsForInterface(services
, interface
)) {
1713 // if this is not a new interface
1717 interface_list
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1718 CFArrayAppendValue(interface_list
, interface
);
1720 while (ok
&& (CFArrayGetCount(interface_list
) > 0)) {
1721 CFArrayRef protocol_types
;
1723 interface
= CFArrayGetValueAtIndex(interface_list
, 0);
1725 protocol_types
= SCNetworkInterfaceGetSupportedProtocolTypes(interface
);
1726 if ((protocol_types
!= NULL
) && (CFArrayGetCount(protocol_types
) > 0)) {
1727 SCNetworkServiceRef service
;
1729 service
= SCNetworkServiceCreate(setPrivate
->prefs
, interface
);
1730 if (service
== NULL
) {
1731 SC_log(LOG_ERR
, "could not create service for \"%@\": %s",
1732 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
1733 SCErrorString(SCError()));
1738 ok
= SCNetworkServiceEstablishDefaultConfiguration(service
);
1740 SC_log(LOG_ERR
, "could not estabish default configuration for \"%@\": %s",
1741 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
1742 SCErrorString(SCError()));
1743 SCNetworkServiceRemove(service
);
1748 ok
= SCNetworkSetAddService(set
, service
);
1750 SC_log(LOG_ERR
, "could not add service for \"%@\": %s",
1751 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
1752 SCErrorString(SCError()));
1753 SCNetworkServiceRemove(service
);
1761 add_supported_interfaces(interface_list
, interface
);
1766 CFArrayRemoveValueAtIndex(interface_list
, 0);
1768 CFRelease(interface_list
);
1770 #if !TARGET_OS_IPHONE
1771 if (updatedIFs
) CFRelease(interfaces
);
1772 #endif // !TARGET_OS_IPHONE
1773 if (services
!= NULL
) CFRelease(services
);
1774 if (excluded
!= NULL
) CFRelease(excluded
);
1776 #if TARGET_OS_IPHONE
1777 if (orphans
!= NULL
) {
1778 if (ok
&& updated
) {
1780 CFIndex n
= CFArrayGetCount(orphans
);
1782 for (i
= 0; i
< n
; i
++) {
1783 SCNetworkServiceRef service
;
1785 service
= CFArrayGetValueAtIndex(orphans
, i
);
1786 if (_SCNetworkServiceIsVPN(service
)) {
1787 ok
= SCNetworkSetAddService(set
, service
);
1797 #endif // TARGET_OS_IPHONE
1799 if (ok
&& !updated
) {
1800 // if no changes were made
1801 _SCErrorSet(kSCStatusOK
);
1809 SCNetworkSetEstablishDefaultConfiguration(SCNetworkSetRef set
)
1811 CFArrayRef interfaces
;
1812 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1813 Boolean updated
= FALSE
;
1815 if (!isA_SCNetworkSet(set
)) {
1816 _SCErrorSet(kSCStatusInvalidArgument
);
1820 interfaces
= _SCNetworkInterfaceCopyAllWithPreferences(setPrivate
->prefs
);
1821 if (interfaces
!= NULL
) {
1822 updated
= __SCNetworkSetEstablishDefaultConfigurationForInterfaces(set
, interfaces
, TRUE
);
1823 CFRelease(interfaces
);
1831 SCNetworkSetEstablishDefaultInterfaceConfiguration(SCNetworkSetRef set
, SCNetworkInterfaceRef interface
)
1833 CFArrayRef interfaces
;
1836 if (!isA_SCNetworkSet(set
)) {
1837 _SCErrorSet(kSCStatusInvalidArgument
);
1841 if (!isA_SCNetworkInterface(interface
)) {
1842 _SCErrorSet(kSCStatusInvalidArgument
);
1846 interfaces
= CFArrayCreate(NULL
, (const void **)&interface
, 1, &kCFTypeArrayCallBacks
);
1847 assert(interfaces
!= NULL
);
1848 updated
= __SCNetworkSetEstablishDefaultConfigurationForInterfaces(set
, interfaces
, FALSE
);
1849 CFRelease(interfaces
);
1856 SCNetworkSetCopySelectedVPNService(SCNetworkSetRef set
)
1860 SCNetworkServiceRef selected
= NULL
;
1861 CFArrayRef services
;
1862 CFMutableArrayRef services_vpn
= NULL
;
1864 if (!isA_SCNetworkSet(set
)) {
1865 _SCErrorSet(kSCStatusInvalidArgument
);
1869 services
= SCNetworkSetCopyServices(set
);
1870 if (services
!= NULL
) {
1871 n
= CFArrayGetCount(services
);
1872 for (i
= 0; i
< n
; i
++) {
1873 SCNetworkServiceRef service
;
1875 service
= CFArrayGetValueAtIndex(services
, i
);
1876 if (!SCNetworkServiceGetEnabled(service
)) {
1881 if (!_SCNetworkServiceIsVPN(service
)) {
1882 // if not VPN service
1886 if (services_vpn
== NULL
) {
1887 services_vpn
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1889 CFArrayAppendValue(services_vpn
, service
);
1892 CFRelease(services
);
1895 if (services_vpn
== NULL
) {
1896 // if no VPN services
1900 n
= CFArrayGetCount(services_vpn
);
1903 CFMutableArrayRef sorted
;
1905 order
= SCNetworkSetGetServiceOrder(set
);
1906 sorted
= CFArrayCreateMutableCopy(NULL
, 0, services_vpn
);
1907 CFArraySortValues(sorted
,
1908 CFRangeMake(0, CFArrayGetCount(sorted
)),
1909 _SCNetworkServiceCompare
,
1911 CFRelease(services_vpn
);
1912 services_vpn
= sorted
;
1915 #if TARGET_OS_IPHONE
1917 CFStringRef serviceID_prefs
;
1919 #define VPN_PREFERENCES CFSTR("com.apple.mobilevpn")
1920 #define VPN_SERVICE_ID CFSTR("activeVPNID")
1922 CFPreferencesAppSynchronize(VPN_PREFERENCES
);
1923 serviceID_prefs
= CFPreferencesCopyAppValue(VPN_SERVICE_ID
, VPN_PREFERENCES
);
1924 if (serviceID_prefs
!= NULL
) {
1925 for (i
= 0; i
< n
; i
++) {
1926 SCNetworkServiceRef service
;
1927 CFStringRef serviceID
;
1929 service
= CFArrayGetValueAtIndex(services_vpn
, i
);
1930 serviceID
= SCNetworkServiceGetServiceID(service
);
1931 if (CFEqual(serviceID
, serviceID_prefs
)) {
1939 CFRelease(serviceID_prefs
);
1942 #endif // TARGET_OS_IPHONE
1944 if (selected
== NULL
) {
1945 selected
= CFArrayGetValueAtIndex(services_vpn
, 0);
1949 CFRelease(services_vpn
);
1955 SCNetworkSetSetSelectedVPNService(SCNetworkSetRef set
, SCNetworkServiceRef service
)
1958 CFArrayRef services
;
1960 if (!isA_SCNetworkSet(set
)) {
1961 _SCErrorSet(kSCStatusInvalidArgument
);
1965 if (!isA_SCNetworkService(service
) || !_SCNetworkServiceIsVPN(service
)) {
1966 _SCErrorSet(kSCStatusInvalidArgument
);
1970 services
= SCNetworkSetCopyServices(set
);
1971 if (services
!= NULL
) {
1973 CFIndex n
= CFArrayGetCount(services
);
1975 if (!CFArrayContainsValue(services
, CFRangeMake(0, n
), service
)) {
1976 // if selected service not a member of the current set
1977 _SCErrorSet(kSCStatusInvalidArgument
);
1982 for (i
= 0; ok
&& (i
< n
); i
++) {
1983 SCNetworkServiceRef vpn
;
1985 vpn
= CFArrayGetValueAtIndex(services
, i
);
1986 if (!_SCNetworkServiceIsVPN(vpn
)) {
1987 // if not VPN service
1991 ok
= SCNetworkServiceSetEnabled(vpn
, CFEqual(service
, vpn
));
1997 if (services
!= NULL
) CFRelease(services
);
2003 _SCNetworkSetSetSetID(SCNetworkSetRef set
, CFStringRef newSetID
)
2005 SCNetworkSetRef currentSet
= NULL
;
2006 SCNetworkSetPrivateRef currentSetPrivate
= NULL
;
2007 CFDictionaryRef entity
;
2008 CFStringRef newPath
;
2010 CFStringRef oldPath
= NULL
;
2011 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
2012 Boolean updateCurrentSet
= FALSE
;
2014 if (!isA_SCNetworkSet(set
)) {
2015 _SCErrorSet(kSCStatusInvalidArgument
);
2019 if (!isA_CFString(newSetID
)) {
2020 _SCErrorSet(kSCStatusInvalidArgument
);
2024 // If newSetID is equal to current setID, our work is done
2025 if (CFEqual(newSetID
, setPrivate
->setID
)) {
2029 newPath
= SCPreferencesPathKeyCreateSet(NULL
, newSetID
);
2030 entity
= SCPreferencesPathGetValue(setPrivate
->prefs
, newPath
);
2031 if (isA_CFDictionary(entity
)) {
2032 // if the new set already exists
2033 _SCErrorSet(kSCStatusKeyExists
);
2037 oldPath
= SCPreferencesPathKeyCreateSet(NULL
, setPrivate
->setID
);
2038 entity
= SCPreferencesPathGetValue(setPrivate
->prefs
, oldPath
);
2039 if (!isA_CFDictionary(entity
)) {
2040 // if the set has already been removed
2041 _SCErrorSet(kSCStatusNoKey
);
2045 ok
= SCPreferencesPathSetValue(setPrivate
->prefs
, newPath
, entity
);
2050 ok
= SCPreferencesPathRemoveValue(setPrivate
->prefs
, oldPath
);
2055 // update current set (if needed)
2056 currentSet
= SCNetworkSetCopyCurrent(setPrivate
->prefs
);
2057 if (currentSet
!= NULL
) {
2058 currentSetPrivate
= (SCNetworkSetPrivateRef
)currentSet
;
2059 if (CFEqual(currentSetPrivate
->setID
, setPrivate
->setID
)) {
2060 updateCurrentSet
= TRUE
;
2062 CFRelease(currentSet
);
2065 SC_log(LOG_DEBUG
, "_SCNetworkSetSetID(): %@ --> %@", set
, newSetID
);
2067 // replace setID with new one
2069 CFRelease(setPrivate
->setID
);
2070 setPrivate
->setID
= newSetID
;
2072 if (updateCurrentSet
) {
2073 SCNetworkSetSetCurrent(set
);
2078 if (oldPath
!= NULL
) {
2081 if (newPath
!= NULL
) {