2 * Copyright (c) 2004-2007 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
;
172 _serviceIsPPP(SCNetworkServiceRef service
)
174 SCNetworkInterfaceRef interface
;
175 CFStringRef interfaceType
;
177 interface
= SCNetworkServiceGetInterface(service
);
178 if (interface
== NULL
) {
182 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
183 return CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
);
188 _serviceIsVPN(SCNetworkServiceRef service
)
190 SCNetworkInterfaceRef interface
;
191 CFStringRef interfaceType
;
193 // if (!_serviceIsPPP(service)) {
197 interface
= SCNetworkServiceGetInterface(service
);
198 // if (interface == NULL) {
202 interface
= SCNetworkInterfaceGetInterface(interface
);
203 if (interface
== NULL
) {
207 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
208 return (CFEqual(interfaceType
, kSCNetworkInterfaceTypeL2TP
) ||
209 CFEqual(interfaceType
, kSCNetworkInterfaceTypePPTP
));
214 _serviceOrder(SCNetworkServiceRef service
)
216 SCNetworkInterfaceRef interface
;
218 interface
= SCNetworkServiceGetInterface(service
);
219 if (interface
== NULL
) {
220 return 100000; // sort last
223 return __SCNetworkInterfaceOrder(interface
);
228 _serviceOrder_add(SCNetworkSetRef set
, SCNetworkServiceRef service
)
232 CFMutableArrayRef newOrder
;
234 CFStringRef serviceID
;
235 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
238 order
= SCNetworkSetGetServiceOrder(set
);
240 newOrder
= CFArrayCreateMutableCopy(NULL
, 0, order
);
242 newOrder
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
244 n
= CFArrayGetCount(newOrder
);
246 serviceID
= SCNetworkServiceGetServiceID(service
);
247 if (CFArrayContainsValue(newOrder
, CFRangeMake(0, n
), serviceID
)) {
248 // if serviceID already present
252 if (_serviceIsPPP(service
) && !_serviceIsVPN(service
)) {
256 * we add [non-VPN] PPP interfaces to the head of the
257 * service order but ensure that "modem" devices are
258 * in front of "Bluetooth" & "IrDA" devices.
262 serviceOrder
= _serviceOrder(service
);
264 for (i
= 0; i
< n
; i
++) {
266 CFStringRef slotServiceID
;
267 SCNetworkServiceRef slotService
;
269 slotServiceID
= CFArrayGetValueAtIndex(newOrder
, i
);
270 if (!isA_CFString(slotServiceID
)) {
275 slotService
= SCNetworkServiceCopy(setPrivate
->prefs
, slotServiceID
);
276 if (slotService
== NULL
) {
277 // if serviceID not valid
281 if (_serviceIsPPP(slotService
)) {
283 slotOrder
= _serviceOrder(slotService
);
284 if (serviceOrder
>= slotOrder
) {
285 // add the service *after* this one
290 CFRelease(slotService
);
294 * non-PPP interfaces are added to the end of the list.
299 CFArrayInsertValueAtIndex(newOrder
, slot
, serviceID
);
300 (void) SCNetworkSetSetServiceOrder(set
, newOrder
);
311 _serviceOrder_remove(SCNetworkSetRef set
, SCNetworkServiceRef service
)
313 CFMutableArrayRef newOrder
;
315 CFStringRef serviceID
;
317 order
= SCNetworkSetGetServiceOrder(set
);
322 serviceID
= SCNetworkServiceGetServiceID(service
);
324 newOrder
= CFArrayCreateMutableCopy(NULL
, 0, order
);
328 i
= CFArrayGetFirstIndexOfValue(newOrder
,
329 CFRangeMake(0, CFArrayGetCount(newOrder
)),
331 if (i
== kCFNotFound
) {
335 CFArrayRemoveValueAtIndex(newOrder
, i
);
337 (void) SCNetworkSetSetServiceOrder(set
, newOrder
);
345 #pragma mark SCNetworkSet APIs
352 SCNetworkSetAddService(SCNetworkSetRef set
, SCNetworkServiceRef service
)
354 SCNetworkInterfaceRef interface
;
355 CFArrayRef interface_config
= NULL
;
359 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
360 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
362 if (!isA_SCNetworkSet(set
)) {
363 _SCErrorSet(kSCStatusInvalidArgument
);
367 if (!isA_SCNetworkService(service
)) {
368 _SCErrorSet(kSCStatusInvalidArgument
);
372 #define PREVENT_DUPLICATE_SERVICE_NAMES
373 #ifdef PREVENT_DUPLICATE_SERVICE_NAMES
376 name
= SCNetworkServiceGetName(service
);
380 services
= SCNetworkSetCopyServices(set
);
381 if (services
!= NULL
) {
385 n
= CFArrayGetCount(services
);
386 for (i
= 0; i
< n
; i
++) {
387 CFStringRef otherName
;
388 SCNetworkServiceRef otherService
;
390 otherService
= CFArrayGetValueAtIndex(services
, i
);
391 otherName
= SCNetworkServiceGetName(otherService
);
392 if ((otherName
!= NULL
) && CFEqual(name
, otherName
)) {
394 * if a service with the same "name" is
395 * already a member of the set.
398 _SCErrorSet(kSCStatusKeyExists
);
406 #endif // PREVENT_DUPLICATE_SERVICE_NAMES
408 //#define PREVENT_DUPLICATE_SETS
409 #ifdef PREVENT_DUPLICATE_SETS
412 // ensure that each service is only a member of ONE set
413 sets
= SCNetworkSetCopyAll(setPrivate
->prefs
);
418 n
= CFArrayGetCount(sets
);
419 for (i
= 0; i
< n
; i
++) {
424 set
= CFArrayGetValueAtIndex(sets
, i
);
425 services
= SCNetworkSetCopyServices(set
);
426 found
= CFArrayContainsValue(services
,
427 CFRangeMake(0, CFArrayGetCount(services
)),
433 _SCErrorSet(kSCStatusKeyExists
);
439 #endif /* PREVENT_DUPLICATE_SETS */
441 // get the [deep] interface configuration settings
442 interface
= SCNetworkServiceGetInterface(service
);
443 if (interface
!= NULL
) {
444 interface_config
= __SCNetworkInterfaceCopyDeepConfiguration(interface
);
447 // create the link between "set" and the "service"
448 path
= SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL
, // allocator
449 setPrivate
->setID
, // set
450 servicePrivate
->serviceID
, // service
452 link
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
453 servicePrivate
->serviceID
, // service
455 ok
= SCPreferencesPathSetLink(setPrivate
->prefs
, path
, link
);
462 // push the [deep] interface configuration into all sets which contain this service.
463 if (interface
!= NULL
) {
464 __SCNetworkInterfaceSetDeepConfiguration(interface
, interface_config
);
467 // add service to ServiceOrder
468 _serviceOrder_add(set
, service
);
472 if (interface_config
!= NULL
) CFRelease(interface_config
);
478 SCNetworkSetCopy(SCPreferencesRef prefs
, CFStringRef setID
)
480 CFDictionaryRef entity
;
482 SCNetworkSetPrivateRef setPrivate
;
484 if (!isA_CFString(setID
)) {
485 _SCErrorSet(kSCStatusInvalidArgument
);
489 path
= SCPreferencesPathKeyCreateSet(NULL
, setID
);
490 entity
= SCPreferencesPathGetValue(prefs
, path
);
493 if (!isA_CFDictionary(entity
)) {
494 _SCErrorSet(kSCStatusNoKey
);
498 setPrivate
= __SCNetworkSetCreatePrivate(NULL
, prefs
, setID
);
499 return (SCNetworkSetRef
)setPrivate
;
504 _SCNetworkServiceExistsForInterface(CFArrayRef services
, SCNetworkInterfaceRef interface
)
509 n
= isA_CFArray(services
) ? CFArrayGetCount(services
) : 0;
510 for (i
= 0; i
< n
; i
++) {
511 SCNetworkServiceRef service
;
512 SCNetworkInterfaceRef service_interface
;
514 service
= CFArrayGetValueAtIndex(services
, i
);
516 service_interface
= SCNetworkServiceGetInterface(service
);
517 while (service_interface
!= NULL
) {
518 if (CFEqual(interface
, service_interface
)) {
522 service_interface
= SCNetworkInterfaceGetInterface(service_interface
);
531 SCNetworkSetContainsInterface(SCNetworkSetRef set
, SCNetworkInterfaceRef interface
)
533 Boolean found
= FALSE
;
536 services
= SCNetworkSetCopyServices(set
);
537 if (services
!= NULL
) {
538 found
= _SCNetworkServiceExistsForInterface(services
, interface
);
546 CFArrayRef
/* of SCNetworkSetRef's */
547 SCNetworkSetCopyAll(SCPreferencesRef prefs
)
549 CFMutableArrayRef array
;
552 CFDictionaryRef sets
;
554 path
= SCPreferencesPathKeyCreateSets(NULL
);
555 sets
= SCPreferencesPathGetValue(prefs
, path
);
558 if ((sets
!= NULL
) && !isA_CFDictionary(sets
)) {
562 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
564 n
= (sets
!= NULL
) ? CFDictionaryGetCount(sets
) : 0;
567 const void * keys_q
[N_QUICK
];
568 const void ** keys
= keys_q
;
569 const void * vals_q
[N_QUICK
];
570 const void ** vals
= vals_q
;
572 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
573 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
574 vals
= CFAllocatorAllocate(NULL
, n
* sizeof(CFPropertyListRef
), 0);
576 CFDictionaryGetKeysAndValues(sets
, keys
, vals
);
577 for (i
= 0; i
< n
; i
++) {
578 SCNetworkSetPrivateRef setPrivate
;
580 if (!isA_CFDictionary(vals
[i
])) {
583 CFSTR("SCNetworkSetCopyAll(): error w/set \"%@\"\n"),
588 setPrivate
= __SCNetworkSetCreatePrivate(NULL
, prefs
, keys
[i
]);
589 CFArrayAppendValue(array
, (SCNetworkSetRef
)setPrivate
);
590 CFRelease(setPrivate
);
592 if (keys
!= keys_q
) {
593 CFAllocatorDeallocate(NULL
, keys
);
594 CFAllocatorDeallocate(NULL
, vals
);
603 SCNetworkSetCopyCurrent(SCPreferencesRef prefs
)
605 CFArrayRef components
;
606 CFStringRef currentID
;
607 SCNetworkSetPrivateRef setPrivate
= NULL
;
609 currentID
= SCPreferencesGetValue(prefs
, kSCPrefCurrentSet
);
610 if (!isA_CFString(currentID
)) {
614 components
= CFStringCreateArrayBySeparatingStrings(NULL
, currentID
, CFSTR("/"));
615 if (CFArrayGetCount(components
) == 3) {
619 setID
= CFArrayGetValueAtIndex(components
, 2);
620 path
= SCPreferencesPathKeyCreateSet(NULL
, setID
);
621 if (CFEqual(path
, currentID
)) {
622 setPrivate
= __SCNetworkSetCreatePrivate(NULL
, prefs
, setID
);
624 SCLog(TRUE
, LOG_ERR
, CFSTR("SCNetworkSetCopyCurrent(): preferences are non-conformant"));
628 CFRelease(components
);
630 return (SCNetworkSetRef
)setPrivate
;
634 CFArrayRef
/* of SCNetworkServiceRef's */
635 SCNetworkSetCopyServices(SCNetworkSetRef set
)
637 CFMutableArrayRef array
;
638 CFDictionaryRef dict
;
641 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
643 if (!isA_SCNetworkSet(set
)) {
644 _SCErrorSet(kSCStatusInvalidArgument
);
648 path
= SCPreferencesPathKeyCreateSetNetworkService(NULL
, setPrivate
->setID
, NULL
);
649 dict
= SCPreferencesPathGetValue(setPrivate
->prefs
, path
);
651 if ((dict
!= NULL
) && !isA_CFDictionary(dict
)) {
655 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
657 n
= (dict
!= NULL
) ? CFDictionaryGetCount(dict
) : 0;
660 const void * keys_q
[N_QUICK
];
661 const void ** keys
= keys_q
;
663 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
664 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
666 CFDictionaryGetKeysAndValues(dict
, keys
, NULL
);
667 for (i
= 0; i
< n
; i
++) {
668 CFArrayRef components
;
671 path
= SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL
,
673 (CFStringRef
)keys
[i
],
675 link
= SCPreferencesPathGetLink(setPrivate
->prefs
, path
);
680 CFSTR("SCNetworkSetCopyServices(): service \"%@\" for set \"%@\" is not a link\n"),
683 continue; // if the service is not a link
686 components
= CFStringCreateArrayBySeparatingStrings(NULL
, link
, CFSTR("/"));
687 if (CFArrayGetCount(components
) == 3) {
688 CFStringRef serviceID
;
690 serviceID
= CFArrayGetValueAtIndex(components
, 2);
691 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
692 serviceID
, // service
694 if (CFEqual(path
, link
)) {
695 SCNetworkServicePrivateRef servicePrivate
;
697 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
,
701 CFArrayAppendValue(array
, (SCNetworkServiceRef
)servicePrivate
);
702 CFRelease(servicePrivate
);
706 CFRelease(components
);
708 if (keys
!= keys_q
) {
709 CFAllocatorDeallocate(NULL
, keys
);
718 SCNetworkSetCreate(SCPreferencesRef prefs
)
720 CFArrayRef components
;
724 SCNetworkSetPrivateRef setPrivate
;
726 prefix
= SCPreferencesPathKeyCreateSets(NULL
);
727 path
= __SCPreferencesPathCreateUniqueChild_WithMoreSCFCompatibility(prefs
, prefix
);
728 if (path
== NULL
) path
= SCPreferencesPathCreateUniqueChild(prefs
, prefix
);
734 components
= CFStringCreateArrayBySeparatingStrings(NULL
, path
, CFSTR("/"));
737 setID
= CFArrayGetValueAtIndex(components
, 2);
738 setPrivate
= __SCNetworkSetCreatePrivate(NULL
, prefs
, setID
);
739 CFRelease(components
);
741 return (SCNetworkSetRef
)setPrivate
;
746 SCNetworkSetGetSetID(SCNetworkSetRef set
)
748 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
750 if (!isA_SCNetworkSet(set
)) {
751 _SCErrorSet(kSCStatusInvalidArgument
);
755 return setPrivate
->setID
;
760 SCNetworkSetGetName(SCNetworkSetRef set
)
763 CFDictionaryRef entity
;
765 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
767 if (!isA_SCNetworkSet(set
)) {
768 _SCErrorSet(kSCStatusInvalidArgument
);
772 if (setPrivate
->name
!= NULL
) {
773 return setPrivate
->name
;
776 path
= SCPreferencesPathKeyCreateSet(NULL
, setPrivate
->setID
);
777 entity
= SCPreferencesPathGetValue(setPrivate
->prefs
, path
);
780 if (isA_CFDictionary(entity
)) {
783 name
= CFDictionaryGetValue(entity
, kSCPropUserDefinedName
);
784 if (isA_CFString(name
)) {
785 setPrivate
->name
= CFRetain(name
);
789 bundle
= _SC_CFBundleGet();
790 if (bundle
!= NULL
) {
791 if (setPrivate
->name
!= NULL
) {
792 CFStringRef non_localized
;
794 non_localized
= _SC_CFBundleCopyNonLocalizedString(bundle
,
795 CFSTR("DEFAULT_SET_NAME"),
798 if (non_localized
!= NULL
) {
799 if (CFEqual(setPrivate
->name
, non_localized
)) {
800 CFStringRef localized
;
802 // if "Automatic", return localized name
803 localized
= CFBundleCopyLocalizedString(bundle
,
804 CFSTR("DEFAULT_SET_NAME"),
807 if (localized
!= NULL
) {
808 CFRelease(setPrivate
->name
);
809 setPrivate
->name
= localized
;
813 CFRelease(non_localized
);
818 return setPrivate
->name
;
822 CFArrayRef
/* of serviceID CFStringRef's */
823 SCNetworkSetGetServiceOrder(SCNetworkSetRef set
)
825 CFDictionaryRef dict
;
827 CFArrayRef serviceOrder
;
828 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
830 if (!isA_SCNetworkSet(set
)) {
831 _SCErrorSet(kSCStatusInvalidArgument
);
835 path
= SCPreferencesPathKeyCreateSetNetworkGlobalEntity(NULL
, setPrivate
->setID
, kSCEntNetIPv4
);
840 dict
= SCPreferencesPathGetValue(setPrivate
->prefs
, path
);
842 if (!isA_CFDictionary(dict
)) {
846 serviceOrder
= CFDictionaryGetValue(dict
, kSCPropNetServiceOrder
);
847 serviceOrder
= isA_CFArray(serviceOrder
);
854 SCNetworkSetGetTypeID(void)
856 pthread_once(&initialized
, __SCNetworkSetInitialize
); /* initialize runtime */
857 return __kSCNetworkSetTypeID
;
862 SCNetworkSetRemove(SCNetworkSetRef set
)
864 CFStringRef currentPath
;
867 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
869 if (!isA_SCNetworkSet(set
)) {
870 _SCErrorSet(kSCStatusInvalidArgument
);
874 currentPath
= SCPreferencesGetValue(setPrivate
->prefs
, kSCPrefCurrentSet
);
875 path
= SCPreferencesPathKeyCreateSet(NULL
, setPrivate
->setID
);
876 if (!isA_CFString(currentPath
) || !CFEqual(currentPath
, path
)) {
877 ok
= SCPreferencesPathRemoveValue(setPrivate
->prefs
, path
);
886 SCNetworkSetRemoveService(SCNetworkSetRef set
, SCNetworkServiceRef service
)
888 SCNetworkInterfaceRef interface
;
889 CFArrayRef interface_config
= NULL
;
892 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
893 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
895 if (!isA_SCNetworkSet(set
)) {
896 _SCErrorSet(kSCStatusInvalidArgument
);
900 if (!isA_SCNetworkService(service
)) {
901 _SCErrorSet(kSCStatusInvalidArgument
);
905 // remove service from ServiceOrder
906 _serviceOrder_remove(set
, service
);
908 // get the [deep] interface configuration settings
909 interface
= SCNetworkServiceGetInterface(service
);
910 if (interface
!= NULL
) {
911 interface_config
= __SCNetworkInterfaceCopyDeepConfiguration(interface
);
912 if (interface_config
!= NULL
) {
913 // remove the interface configuration from all sets which contain this service.
914 __SCNetworkInterfaceSetDeepConfiguration(interface
, NULL
);
918 // remove the link between "set" and the "service"
919 path
= SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL
,
921 servicePrivate
->serviceID
,
923 ok
= SCPreferencesPathRemoveValue(setPrivate
->prefs
, path
);
929 // push the [deep] interface configuration [back] into all sets which contain the service.
930 if (interface_config
!= NULL
) {
931 __SCNetworkInterfaceSetDeepConfiguration(interface
, interface_config
);
936 if (interface_config
!= NULL
) CFRelease(interface_config
);
942 SCNetworkSetSetCurrent(SCNetworkSetRef set
)
946 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
948 if (!isA_SCNetworkSet(set
)) {
949 _SCErrorSet(kSCStatusInvalidArgument
);
953 path
= SCPreferencesPathKeyCreateSet(NULL
, setPrivate
->setID
);
954 ok
= SCPreferencesSetValue(setPrivate
->prefs
, kSCPrefCurrentSet
, path
);
961 SCNetworkSetSetName(SCNetworkSetRef set
, CFStringRef name
)
963 CFBundleRef bundle
= NULL
;
964 CFDictionaryRef entity
;
965 CFStringRef localized
= NULL
;
966 CFStringRef non_localized
= NULL
;
969 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
971 if (!isA_SCNetworkSet(set
)) {
972 _SCErrorSet(kSCStatusInvalidArgument
);
976 if ((name
!= NULL
) && !isA_CFString(name
)) {
977 _SCErrorSet(kSCStatusInvalidArgument
);
981 // if known, compare against localized name
984 bundle
= _SC_CFBundleGet();
985 if (bundle
!= NULL
) {
986 non_localized
= _SC_CFBundleCopyNonLocalizedString(bundle
,
987 CFSTR("DEFAULT_SET_NAME"),
990 if (non_localized
!= NULL
) {
991 if (CFEqual(name
, non_localized
)) {
992 localized
= CFBundleCopyLocalizedString(bundle
,
993 CFSTR("DEFAULT_SET_NAME"),
996 if (localized
!= NULL
) {
1004 #define PREVENT_DUPLICATE_SET_NAMES
1005 #ifdef PREVENT_DUPLICATE_SET_NAMES
1009 // ensure that each set is uniquely named
1011 sets
= SCNetworkSetCopyAll(setPrivate
->prefs
);
1016 n
= CFArrayGetCount(sets
);
1017 for (i
= 0; i
< n
; i
++) {
1018 CFStringRef otherID
;
1019 CFStringRef otherName
;
1020 SCNetworkSetRef set
= CFArrayGetValueAtIndex(sets
, i
);
1022 otherID
= SCNetworkSetGetSetID(set
);
1023 if (CFEqual(setPrivate
->setID
, otherID
)) {
1024 continue; // skip current set
1027 otherName
= SCNetworkSetGetName(set
);
1028 if ((otherName
!= NULL
) && CFEqual(name
, otherName
)) {
1029 // if "name" not unique
1031 _SCErrorSet(kSCStatusKeyExists
);
1038 #endif /* PREVENT_DUPLICATE_SET_NAMES */
1040 // if known, store non-localized name
1042 if ((name
!= NULL
) && (bundle
!= NULL
) && (non_localized
!= NULL
)) {
1043 if (localized
== NULL
) {
1044 localized
= CFBundleCopyLocalizedString(bundle
,
1045 CFSTR("DEFAULT_SET_NAME"),
1050 if (localized
!= NULL
) {
1051 if (CFEqual(name
, localized
)) {
1052 name
= non_localized
;
1057 // update the "name"
1059 path
= SCPreferencesPathKeyCreateSet(NULL
, setPrivate
->setID
);
1060 entity
= SCPreferencesPathGetValue(setPrivate
->prefs
, path
);
1061 if ((entity
== NULL
) && (name
!= NULL
)) {
1062 entity
= CFDictionaryCreate(NULL
,
1066 &kCFTypeDictionaryKeyCallBacks
,
1067 &kCFTypeDictionaryValueCallBacks
);
1069 if (isA_CFDictionary(entity
)) {
1070 CFMutableDictionaryRef newEntity
;
1072 newEntity
= CFDictionaryCreateMutableCopy(NULL
, 0, entity
);
1074 CFDictionarySetValue(newEntity
, kSCPropUserDefinedName
, name
);
1076 CFDictionaryRemoveValue(newEntity
, kSCPropUserDefinedName
);
1078 ok
= SCPreferencesPathSetValue(setPrivate
->prefs
, path
, newEntity
);
1079 CFRelease(newEntity
);
1085 if (localized
!= NULL
) CFRelease(localized
);
1086 if (non_localized
!= NULL
) CFRelease(non_localized
);
1092 SCNetworkSetSetServiceOrder(SCNetworkSetRef set
, CFArrayRef newOrder
)
1094 CFDictionaryRef dict
;
1095 CFMutableDictionaryRef newDict
;
1098 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1100 if (!isA_SCNetworkSet(set
)) {
1101 _SCErrorSet(kSCStatusInvalidArgument
);
1105 if (isA_CFArray(newOrder
)) {
1107 CFIndex n
= CFArrayGetCount(newOrder
);
1109 for (i
= 0; i
< n
; i
++) {
1110 CFStringRef serviceID
;
1112 serviceID
= CFArrayGetValueAtIndex(newOrder
, i
);
1113 if (!isA_CFString(serviceID
)) {
1114 _SCErrorSet(kSCStatusInvalidArgument
);
1119 _SCErrorSet(kSCStatusInvalidArgument
);
1123 path
= SCPreferencesPathKeyCreateSetNetworkGlobalEntity(NULL
, setPrivate
->setID
, kSCEntNetIPv4
);
1128 dict
= SCPreferencesPathGetValue(setPrivate
->prefs
, path
);
1130 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
);
1132 newDict
= CFDictionaryCreateMutable(NULL
,
1134 &kCFTypeDictionaryKeyCallBacks
,
1135 &kCFTypeDictionaryValueCallBacks
);
1138 CFDictionarySetValue(newDict
, kSCPropNetServiceOrder
, newOrder
);
1139 ok
= SCPreferencesPathSetValue(setPrivate
->prefs
, path
, newDict
);
1148 #pragma mark SCNetworkSet SPIs
1152 add_supported_interfaces(CFMutableArrayRef interface_list
, SCNetworkInterfaceRef interface
)
1155 CFArrayRef interface_types
;
1158 interface_types
= SCNetworkInterfaceGetSupportedInterfaceTypes(interface
);
1159 n
= (interface_types
!= NULL
) ? CFArrayGetCount(interface_types
) : 0;
1160 for (i
= 0; i
< n
; i
++) {
1161 SCNetworkInterfaceRef parent
;
1162 CFStringRef interface_type
;
1164 interface_type
= CFArrayGetValueAtIndex(interface_types
, i
);
1165 parent
= SCNetworkInterfaceCreateWithInterface(interface
, interface_type
);
1166 if (parent
!= NULL
) {
1167 CFArrayAppendValue(interface_list
, parent
);
1177 next_service_name(SCNetworkServiceRef service
)
1179 CFArrayRef components
;
1182 CFMutableArrayRef newComponents
;
1185 name
= SCNetworkServiceGetName(service
);
1190 components
= CFStringCreateArrayBySeparatingStrings(NULL
, name
, CFSTR(" "));
1191 if (components
!= NULL
) {
1192 newComponents
= CFArrayCreateMutableCopy(NULL
, 0, components
);
1193 CFRelease(components
);
1195 newComponents
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1196 CFArrayAppendValue(newComponents
, name
);
1199 n
= CFArrayGetCount(newComponents
);
1203 str
= CFArrayGetValueAtIndex(newComponents
, n
- 1);
1204 suffix
= CFStringGetIntValue(str
);
1206 CFArrayRemoveValueAtIndex(newComponents
, n
- 1);
1212 name
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%d"), suffix
);
1213 CFArrayAppendValue(newComponents
, name
);
1216 name
= CFStringCreateByCombiningStrings(NULL
, newComponents
, CFSTR(" "));
1217 CFRelease(newComponents
);
1224 __SCNetworkSetEstablishDefaultConfigurationForInterfaces(SCNetworkSetRef set
, CFArrayRef interfaces
)
1229 CFArrayRef services
;
1230 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1231 Boolean updated
= FALSE
;
1233 // first, assume that we only want to add new services
1234 // for those interfaces that are not represented in the
1236 services
= SCNetworkSetCopyServices(set
);
1237 if ((services
!= NULL
) && (CFArrayGetCount(services
) > 0)) {
1238 // but, if we are starting off with a non-empty
1239 // set than we only want to add new services for
1240 // those interfaces that are not represented in
1242 CFRelease(services
);
1243 services
= SCNetworkServiceCopyAll(setPrivate
->prefs
);
1246 n
= (interfaces
!= NULL
) ? CFArrayGetCount(interfaces
) : 0;
1247 for (i
= 0; i
< n
; i
++) {
1248 SCNetworkInterfaceRef interface
;
1249 CFMutableArrayRef interface_list
;
1251 interface
= CFArrayGetValueAtIndex(interfaces
, i
);
1252 if (_SCNetworkServiceExistsForInterface(services
, interface
)) {
1253 // if this is not a new interface
1257 interface_list
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1258 CFArrayAppendValue(interface_list
, interface
);
1260 while (ok
&& (CFArrayGetCount(interface_list
) > 0)) {
1261 CFArrayRef protocol_types
;
1263 interface
= CFArrayGetValueAtIndex(interface_list
, 0);
1265 protocol_types
= SCNetworkInterfaceGetSupportedProtocolTypes(interface
);
1266 if ((protocol_types
!= NULL
) && (CFArrayGetCount(protocol_types
) > 0)) {
1267 SCNetworkServiceRef service
;
1269 service
= SCNetworkServiceCreate(setPrivate
->prefs
, interface
);
1270 if (service
== NULL
) {
1271 SCLog(TRUE
, LOG_DEBUG
,
1272 CFSTR("could not create service for \"%@\": %s\n"),
1273 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
1274 SCErrorString(SCError()));
1279 ok
= SCNetworkServiceEstablishDefaultConfiguration(service
);
1281 SCLog(TRUE
, LOG_DEBUG
,
1282 CFSTR("could not estabish default configuration for \"%@\": %s\n"),
1283 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
1284 SCErrorString(SCError()));
1285 SCNetworkServiceRemove(service
);
1291 CFStringRef newName
;
1293 ok
= SCNetworkSetAddService(set
, service
);
1298 if (SCError() != kSCStatusKeyExists
) {
1299 SCLog(TRUE
, LOG_DEBUG
,
1300 CFSTR("could not add service for \"%@\": %s\n"),
1301 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
1302 SCErrorString(SCError()));
1303 SCNetworkServiceRemove(service
);
1308 // we have two interfaces with the same service
1309 // name, acquire a new, hopefully unique, name
1311 newName
= next_service_name(service
);
1312 if (newName
== NULL
) {
1313 SCLog(TRUE
, LOG_DEBUG
,
1314 CFSTR("could not set unique name for \"%@\": %s\n"),
1315 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
1316 SCErrorString(SCError()));
1317 SCNetworkServiceRemove(service
);
1322 ok
= SCNetworkServiceSetName(service
, newName
);
1328 if (SCError() != kSCStatusKeyExists
) {
1329 SCLog(TRUE
, LOG_DEBUG
,
1330 CFSTR("could not set unique name for \"%@\": %s\n"),
1331 SCNetworkInterfaceGetLocalizedDisplayName(interface
),
1332 SCErrorString(SCError()));
1333 SCNetworkServiceRemove(service
);
1342 add_supported_interfaces(interface_list
, interface
);
1347 CFArrayRemoveValueAtIndex(interface_list
, 0);
1349 CFRelease(interface_list
);
1351 if (services
!= NULL
) CFRelease(services
);
1353 if (ok
&& !updated
) {
1354 // if no changes were made
1355 _SCErrorSet(kSCStatusOK
);
1363 SCNetworkSetEstablishDefaultConfiguration(SCNetworkSetRef set
)
1365 CFArrayRef interfaces
;
1368 if (!isA_SCNetworkSet(set
)) {
1369 _SCErrorSet(kSCStatusInvalidArgument
);
1373 interfaces
= SCNetworkInterfaceCopyAll();
1374 updated
= __SCNetworkSetEstablishDefaultConfigurationForInterfaces(set
, interfaces
);
1375 if (interfaces
!= NULL
) CFRelease(interfaces
);
1382 SCNetworkSetEstablishDefaultInterfaceConfiguration(SCNetworkSetRef set
, SCNetworkInterfaceRef interface
)
1384 CFMutableArrayRef interfaces
;
1387 if (!isA_SCNetworkSet(set
)) {
1388 _SCErrorSet(kSCStatusInvalidArgument
);
1392 if (!isA_SCNetworkInterface(interface
)) {
1393 _SCErrorSet(kSCStatusInvalidArgument
);
1397 interfaces
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1398 CFArrayAppendValue(interfaces
, interface
);
1399 updated
= __SCNetworkSetEstablishDefaultConfigurationForInterfaces(set
, interfaces
);
1400 CFRelease(interfaces
);