2 * Copyright (c) 2004-2013 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 * Modification History
27 * May 13, 2004 Allan Nathanson <ajn@apple.com>
32 #include <CoreFoundation/CoreFoundation.h>
33 #include <CoreFoundation/CFRuntime.h>
34 #include <SystemConfiguration/SystemConfiguration.h>
35 #include "SCNetworkConfigurationInternal.h"
36 #include <SystemConfiguration/SCValidation.h>
37 #include <SystemConfiguration/SCPrivate.h>
41 #define EXTERNAL_ID_DOMAIN_PREFIX "_"
43 static CFStringRef
__SCNetworkServiceCopyDescription (CFTypeRef cf
);
44 static void __SCNetworkServiceDeallocate (CFTypeRef cf
);
45 static Boolean
__SCNetworkServiceEqual (CFTypeRef cf1
, CFTypeRef cf2
);
46 static CFHashCode
__SCNetworkServiceHash (CFTypeRef cf
);
49 static CFTypeID __kSCNetworkServiceTypeID
= _kCFRuntimeNotATypeID
;
52 static const CFRuntimeClass __SCNetworkServiceClass
= {
54 "SCNetworkService", // className
57 __SCNetworkServiceDeallocate
, // dealloc
58 __SCNetworkServiceEqual
, // equal
59 __SCNetworkServiceHash
, // hash
60 NULL
, // copyFormattingDesc
61 __SCNetworkServiceCopyDescription
// copyDebugDesc
65 static pthread_once_t initialized
= PTHREAD_ONCE_INIT
;
69 __SCNetworkServiceCopyDescription(CFTypeRef cf
)
71 CFAllocatorRef allocator
= CFGetAllocator(cf
);
72 CFMutableStringRef result
;
73 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)cf
;
75 result
= CFStringCreateMutable(allocator
, 0);
76 CFStringAppendFormat(result
, NULL
, CFSTR("<SCNetworkService %p [%p]> {"), cf
, allocator
);
77 CFStringAppendFormat(result
, NULL
, CFSTR("id = %@"), servicePrivate
->serviceID
);
78 if (servicePrivate
->prefs
!= NULL
) {
79 CFStringAppendFormat(result
, NULL
, CFSTR(", prefs = %p"), servicePrivate
->prefs
);
80 } else if (servicePrivate
->store
!= NULL
) {
81 CFStringAppendFormat(result
, NULL
, CFSTR(", store = %p"), servicePrivate
->store
);
83 if (servicePrivate
->name
!= NULL
) {
84 CFStringAppendFormat(result
, NULL
, CFSTR(", name = %@"), servicePrivate
->name
);
86 CFStringAppendFormat(result
, NULL
, CFSTR("}"));
93 __SCNetworkServiceDeallocate(CFTypeRef cf
)
95 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)cf
;
97 /* release resources */
99 CFRelease(servicePrivate
->serviceID
);
100 if (servicePrivate
->interface
!= NULL
) CFRelease(servicePrivate
->interface
);
101 if (servicePrivate
->prefs
!= NULL
) CFRelease(servicePrivate
->prefs
);
102 if (servicePrivate
->store
!= NULL
) CFRelease(servicePrivate
->store
);
103 if (servicePrivate
->name
!= NULL
) CFRelease(servicePrivate
->name
);
104 if (servicePrivate
->externalIDs
!= NULL
) CFRelease(servicePrivate
->externalIDs
);
111 __SCNetworkServiceEqual(CFTypeRef cf1
, CFTypeRef cf2
)
113 SCNetworkServicePrivateRef s1
= (SCNetworkServicePrivateRef
)cf1
;
114 SCNetworkServicePrivateRef s2
= (SCNetworkServicePrivateRef
)cf2
;
119 if (s1
->prefs
!= s2
->prefs
)
120 return FALSE
; // if not the same prefs
122 if (!CFEqual(s1
->serviceID
, s2
->serviceID
))
123 return FALSE
; // if not the same service identifier
130 __SCNetworkServiceHash(CFTypeRef cf
)
132 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)cf
;
134 return CFHash(servicePrivate
->serviceID
);
139 __SCNetworkServiceInitialize(void)
141 __kSCNetworkServiceTypeID
= _CFRuntimeRegisterClass(&__SCNetworkServiceClass
);
146 __private_extern__ SCNetworkServicePrivateRef
147 __SCNetworkServiceCreatePrivate(CFAllocatorRef allocator
,
148 SCPreferencesRef prefs
,
149 CFStringRef serviceID
,
150 SCNetworkInterfaceRef interface
)
152 SCNetworkServicePrivateRef servicePrivate
;
155 /* initialize runtime */
156 pthread_once(&initialized
, __SCNetworkServiceInitialize
);
158 /* allocate target */
159 size
= sizeof(SCNetworkServicePrivate
) - sizeof(CFRuntimeBase
);
160 servicePrivate
= (SCNetworkServicePrivateRef
)_CFRuntimeCreateInstance(allocator
,
161 __kSCNetworkServiceTypeID
,
164 if (servicePrivate
== NULL
) {
168 servicePrivate
->prefs
= (prefs
!= NULL
) ? CFRetain(prefs
): NULL
;
169 servicePrivate
->serviceID
= CFStringCreateCopy(NULL
, serviceID
);
170 servicePrivate
->interface
= (interface
!= NULL
) ? CFRetain(interface
) : NULL
;
171 servicePrivate
->name
= NULL
;
173 return servicePrivate
;
178 #pragma mark Service ordering
182 _SCNetworkServiceCompare(const void *val1
, const void *val2
, void *context
)
186 CFArrayRef order
= (CFArrayRef
)context
;
187 SCNetworkServiceRef s1
= (SCNetworkServiceRef
)val1
;
188 SCNetworkServiceRef s2
= (SCNetworkServiceRef
)val2
;
190 id1
= SCNetworkServiceGetServiceID(s1
);
191 id2
= SCNetworkServiceGetServiceID(s2
);
198 range
= CFRangeMake(0, CFArrayGetCount(order
));
199 o1
= CFArrayGetFirstIndexOfValue(order
, range
, id1
);
200 o2
= CFArrayGetFirstIndexOfValue(order
, range
, id2
);
203 return (o2
!= kCFNotFound
) ? kCFCompareGreaterThan
: kCFCompareLessThan
;
204 } else if (o1
< o2
) {
205 return (o1
!= kCFNotFound
) ? kCFCompareLessThan
: kCFCompareGreaterThan
;
209 return CFStringCompare(id1
, id2
, 0);
214 #pragma mark SCNetworkService APIs
220 __private_extern__ CFArrayRef
/* of SCNetworkServiceRef's */
221 __SCNetworkServiceCopyAllEnabled(SCPreferencesRef prefs
)
223 CFMutableArrayRef array
= NULL
;
228 sets
= SCNetworkSetCopyAll(prefs
);
233 n_sets
= CFArrayGetCount(sets
);
234 for (i_sets
= 0; i_sets
< n_sets
; i_sets
++) {
240 set
= CFArrayGetValueAtIndex(sets
, i_sets
);
241 services
= SCNetworkSetCopyServices(set
);
242 if (services
== NULL
) {
246 n_services
= CFArrayGetCount(services
);
247 for (i_services
= 0; i_services
< n_services
; i_services
++) {
248 SCNetworkServiceRef service
;
250 service
= CFArrayGetValueAtIndex(services
, i_services
);
251 if (!SCNetworkServiceGetEnabled(service
)) {
256 if ((array
== NULL
) ||
257 !CFArrayContainsValue(array
,
258 CFRangeMake(0, CFArrayGetCount(array
)),
261 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
263 CFArrayAppendValue(array
, service
);
274 __private_extern__ Boolean
275 __SCNetworkServiceExistsForInterface(CFArrayRef services
, SCNetworkInterfaceRef interface
)
280 n
= isA_CFArray(services
) ? CFArrayGetCount(services
) : 0;
281 for (i
= 0; i
< n
; i
++) {
282 SCNetworkServiceRef service
;
283 SCNetworkInterfaceRef service_interface
;
285 service
= CFArrayGetValueAtIndex(services
, i
);
287 service_interface
= SCNetworkServiceGetInterface(service
);
288 while (service_interface
!= NULL
) {
289 if (CFEqual(interface
, service_interface
)) {
293 service_interface
= SCNetworkInterfaceGetInterface(service_interface
);
301 __private_extern__ CF_RETURNS_RETAINED CFStringRef
302 __SCNetworkServiceNextName(SCNetworkServiceRef service
)
304 CFArrayRef components
;
307 CFMutableArrayRef newComponents
;
310 name
= SCNetworkServiceGetName(service
);
315 components
= CFStringCreateArrayBySeparatingStrings(NULL
, name
, CFSTR(" "));
316 if (components
!= NULL
) {
317 newComponents
= CFArrayCreateMutableCopy(NULL
, 0, components
);
318 CFRelease(components
);
320 newComponents
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
321 CFArrayAppendValue(newComponents
, name
);
324 n
= CFArrayGetCount(newComponents
);
328 str
= CFArrayGetValueAtIndex(newComponents
, n
- 1);
329 suffix
= CFStringGetIntValue(str
);
331 CFArrayRemoveValueAtIndex(newComponents
, n
- 1);
337 name
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%d"), (int)suffix
);
338 CFArrayAppendValue(newComponents
, name
);
341 name
= CFStringCreateByCombiningStrings(NULL
, newComponents
, CFSTR(" "));
342 CFRelease(newComponents
);
349 mergeDict(const void *key
, const void *value
, void *context
)
351 CFMutableDictionaryRef newDict
= (CFMutableDictionaryRef
)context
;
353 CFDictionarySetValue(newDict
, key
, value
);
358 static CF_RETURNS_RETAINED CFDictionaryRef
359 _protocolTemplate(SCNetworkServiceRef service
, CFStringRef protocolType
)
361 SCNetworkInterfaceRef interface
;
362 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
363 CFDictionaryRef
template = NULL
;
365 interface
= servicePrivate
->interface
;
366 if (interface
!= NULL
) {
367 SCNetworkInterfaceRef childInterface
;
368 CFStringRef childInterfaceType
= NULL
;
369 CFStringRef interfaceType
;
372 interfaceType
= SCNetworkInterfaceGetInterfaceType(servicePrivate
->interface
);
373 childInterface
= SCNetworkInterfaceGetInterface(servicePrivate
->interface
);
374 if (childInterface
!= NULL
) {
375 childInterfaceType
= SCNetworkInterfaceGetInterfaceType(childInterface
);
378 template = __copyProtocolTemplate(interfaceType
, childInterfaceType
, protocolType
);
379 if (template != NULL
) {
380 CFDictionaryRef overrides
;
382 // move to the interface at the lowest layer
383 while (childInterface
!= NULL
) {
384 interface
= childInterface
;
385 childInterface
= SCNetworkInterfaceGetInterface(interface
);
388 overrides
= __SCNetworkInterfaceGetTemplateOverrides(interface
, protocolType
);
389 if (overrides
!= NULL
) {
390 CFMutableDictionaryRef newTemplate
;
392 newTemplate
= CFDictionaryCreateMutableCopy(NULL
, 0, template);
393 CFDictionaryApplyFunction(overrides
, mergeDict
, newTemplate
);
395 template = newTemplate
;
400 if (template == NULL
) {
401 template = CFDictionaryCreate(NULL
,
405 &kCFTypeDictionaryKeyCallBacks
,
406 &kCFTypeDictionaryValueCallBacks
);
414 SCNetworkServiceAddProtocolType(SCNetworkServiceRef service
, CFStringRef protocolType
)
416 CFDictionaryRef entity
;
417 CFDictionaryRef newEntity
= NULL
;
420 SCNetworkProtocolRef protocol
;
421 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
423 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
424 _SCErrorSet(kSCStatusInvalidArgument
);
428 if (!__SCNetworkProtocolIsValidType(protocolType
)) {
429 _SCErrorSet(kSCStatusInvalidArgument
);
433 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
434 servicePrivate
->serviceID
, // service
435 protocolType
); // entity
437 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
438 if (entity
!= NULL
) {
439 // if "protocol" already exists
440 _SCErrorSet(kSCStatusKeyExists
);
444 newEntity
= CFDictionaryCreate(NULL
,
448 &kCFTypeDictionaryKeyCallBacks
,
449 &kCFTypeDictionaryValueCallBacks
);
450 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, newEntity
);
451 CFRelease(newEntity
);
456 protocol
= SCNetworkServiceCopyProtocol(service
, protocolType
);
457 assert(protocol
!= NULL
);
459 newEntity
= _protocolTemplate(service
, protocolType
);
460 ok
= SCNetworkProtocolSetConfiguration(protocol
, newEntity
);
461 CFRelease(newEntity
);
471 CFArrayRef
/* of SCNetworkServiceRef's */
472 SCNetworkServiceCopyAll(SCPreferencesRef prefs
)
474 CFMutableArrayRef array
;
477 CFDictionaryRef services
;
479 path
= SCPreferencesPathKeyCreateNetworkServices(NULL
);
480 services
= SCPreferencesPathGetValue(prefs
, path
);
483 if ((services
!= NULL
) && !isA_CFDictionary(services
)) {
487 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
489 n
= (services
!= NULL
) ? CFDictionaryGetCount(services
) : 0;
492 const void * keys_q
[N_QUICK
];
493 const void ** keys
= keys_q
;
494 const void * vals_q
[N_QUICK
];
495 const void ** vals
= vals_q
;
497 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
498 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
499 vals
= CFAllocatorAllocate(NULL
, n
* sizeof(CFPropertyListRef
), 0);
501 CFDictionaryGetKeysAndValues(services
, keys
, vals
);
502 for (i
= 0; i
< n
; i
++) {
503 CFDictionaryRef entity
;
504 SCNetworkServicePrivateRef servicePrivate
;
506 if (!isA_CFDictionary(vals
[i
])) {
509 CFSTR("SCNetworkServiceCopyAll(): error w/service \"%@\"\n"),
514 entity
= CFDictionaryGetValue(vals
[i
], kSCEntNetInterface
);
515 if (!isA_CFDictionary(entity
)) {
519 CFSTR("SCNetworkServiceCopyAll(): no \"%@\" entity for service \"%@\"\n"),
525 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, prefs
, keys
[i
], NULL
);
526 assert(servicePrivate
!= NULL
);
527 CFArrayAppendValue(array
, (SCNetworkServiceRef
)servicePrivate
);
528 CFRelease(servicePrivate
);
530 if (keys
!= keys_q
) {
531 CFAllocatorDeallocate(NULL
, keys
);
532 CFAllocatorDeallocate(NULL
, vals
);
541 * build a list of all of a servives entity types that are associated
542 * with the services interface. The list will include :
544 * - entity types associated with the interface type (Ethernet, FireWire, PPP, ...)
545 * - entity types associated with the interface sub-type (PPPSerial, PPPoE, L2TP, PPTP, ...)
546 * - entity types associated with the hardware device (Ethernet, AirPort, FireWire, Modem, ...)
549 _copyInterfaceEntityTypes(CFDictionaryRef protocols
)
551 CFDictionaryRef interface
;
552 CFMutableSetRef interface_entity_types
;
554 interface_entity_types
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
556 interface
= CFDictionaryGetValue(protocols
, kSCEntNetInterface
);
557 if (isA_CFDictionary(interface
)) {
558 CFStringRef entities
[] = { kSCPropNetInterfaceType
,
559 kSCPropNetInterfaceSubType
,
560 kSCPropNetInterfaceHardware
};
563 // include the "Interface" entity itself
564 CFSetAddValue(interface_entity_types
, kSCEntNetInterface
);
566 // include the entities associated with the interface
567 for (i
= 0; i
< sizeof(entities
)/sizeof(entities
[0]); i
++) {
570 entity
= CFDictionaryGetValue(interface
, entities
[i
]);
571 if (isA_CFString(entity
)) {
572 CFSetAddValue(interface_entity_types
, entity
);
577 * and, because we've found some misguided network preference code
578 * developers leaving [PPP] entity dictionaries around even though
579 * they are unused and/or unneeded...
581 CFSetAddValue(interface_entity_types
, kSCEntNetPPP
);
584 return interface_entity_types
;
589 SCNetworkServiceCopy(SCPreferencesRef prefs
, CFStringRef serviceID
)
591 CFDictionaryRef entity
;
593 SCNetworkServicePrivateRef servicePrivate
;
595 if (!isA_CFString(serviceID
)) {
596 _SCErrorSet(kSCStatusInvalidArgument
);
600 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
601 serviceID
, // service
602 kSCEntNetInterface
); // entity
603 entity
= SCPreferencesPathGetValue(prefs
, path
);
606 if (!isA_CFDictionary(entity
)) {
607 // a "service" must have an "interface"
608 _SCErrorSet(kSCStatusNoKey
);
612 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, prefs
, serviceID
, NULL
);
613 return (SCNetworkServiceRef
)servicePrivate
;
618 _SCNetworkServiceCopyActive(SCDynamicStoreRef store
, CFStringRef serviceID
)
620 SCNetworkServicePrivateRef servicePrivate
;
622 if (!isA_CFString(serviceID
)) {
623 _SCErrorSet(kSCStatusInvalidArgument
);
627 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, NULL
, serviceID
, NULL
);
628 assert(servicePrivate
!= NULL
);
630 servicePrivate
->store
= CFRetain(store
);
632 return (SCNetworkServiceRef
)servicePrivate
;
637 SCNetworkServiceCopyProtocol(SCNetworkServiceRef service
, CFStringRef protocolType
)
639 CFSetRef non_protocol_entities
;
641 CFDictionaryRef protocols
;
642 SCNetworkProtocolPrivateRef protocolPrivate
= NULL
;
643 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
645 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
646 _SCErrorSet(kSCStatusInvalidArgument
);
650 if (!isA_CFString(protocolType
)) {
651 _SCErrorSet(kSCStatusInvalidArgument
);
655 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
656 servicePrivate
->serviceID
, // service
658 protocols
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
661 if (!isA_CFDictionary(protocols
)) {
663 _SCErrorSet(kSCStatusFailed
);
667 non_protocol_entities
= _copyInterfaceEntityTypes(protocols
);
668 if (CFSetContainsValue(non_protocol_entities
, protocolType
)) {
669 // if the "protocolType" matches an interface entity type
670 _SCErrorSet(kSCStatusInvalidArgument
);
674 if (!CFDictionaryContainsKey(protocols
, protocolType
)) {
675 // if the "protocolType" entity does not exist
676 _SCErrorSet(kSCStatusNoKey
);
680 protocolPrivate
= __SCNetworkProtocolCreatePrivate(NULL
, protocolType
, service
);
684 CFRelease(non_protocol_entities
);
686 return (SCNetworkProtocolRef
)protocolPrivate
;
690 CFArrayRef
/* of SCNetworkProtocolRef's */
691 SCNetworkServiceCopyProtocols(SCNetworkServiceRef service
)
693 CFMutableArrayRef array
;
695 CFSetRef non_protocol_entities
;
697 CFDictionaryRef protocols
;
698 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
700 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
701 _SCErrorSet(kSCStatusInvalidArgument
);
705 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
706 servicePrivate
->serviceID
, // service
708 protocols
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
711 if (!isA_CFDictionary(protocols
)) {
713 _SCErrorSet(kSCStatusFailed
);
717 non_protocol_entities
= _copyInterfaceEntityTypes(protocols
);
719 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
721 n
= CFDictionaryGetCount(protocols
);
724 const void * keys_q
[N_QUICK
];
725 const void ** keys
= keys_q
;
726 const void * vals_q
[N_QUICK
];
727 const void ** vals
= vals_q
;
729 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
730 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
731 vals
= CFAllocatorAllocate(NULL
, n
* sizeof(CFPropertyListRef
), 0);
733 CFDictionaryGetKeysAndValues(protocols
, keys
, vals
);
734 for (i
= 0; i
< n
; i
++) {
735 SCNetworkProtocolPrivateRef protocolPrivate
;
737 if (!isA_CFDictionary(vals
[i
])) {
738 // if it's not a dictionary then it can't be a protocol entity
742 if (CFSetContainsValue(non_protocol_entities
, keys
[i
])) {
743 // skip any non-protocol (interface) entities
747 protocolPrivate
= __SCNetworkProtocolCreatePrivate(NULL
, keys
[i
], service
);
748 CFArrayAppendValue(array
, (SCNetworkProtocolRef
)protocolPrivate
);
750 CFRelease(protocolPrivate
);
752 if (keys
!= keys_q
) {
753 CFAllocatorDeallocate(NULL
, keys
);
754 CFAllocatorDeallocate(NULL
, vals
);
758 CFRelease(non_protocol_entities
);
765 __SCNetworkServiceSetInterfaceEntity(SCNetworkServiceRef service
,
766 SCNetworkInterfaceRef interface
)
768 CFDictionaryRef entity
;
771 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
773 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
774 servicePrivate
->serviceID
, // service
775 kSCEntNetInterface
); // entity
776 entity
= __SCNetworkInterfaceCopyInterfaceEntity(interface
);
777 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, entity
);
786 SCNetworkServiceCreate(SCPreferencesRef prefs
, SCNetworkInterfaceRef interface
)
788 CFArrayRef components
;
789 CFArrayRef interface_config
;
790 CFStringRef interface_name
;
791 SCNetworkInterfaceRef newInterface
;
794 CFStringRef serviceID
;
795 SCNetworkServicePrivateRef servicePrivate
;
796 CFArrayRef supported_protocols
;
798 if (!isA_SCNetworkInterface(interface
)) {
799 _SCErrorSet(kSCStatusInvalidArgument
);
803 // only allow network interfaces which support one or more protocols
804 // to be added to a service. The one exception is that we allow
805 // third-party interface types to be configured.
806 supported_protocols
= SCNetworkInterfaceGetSupportedProtocolTypes(interface
);
807 if (supported_protocols
== NULL
) {
808 CFStringRef interface_type
;
810 interface_type
= SCNetworkInterfaceGetInterfaceType(interface
);
811 if (CFStringFind(interface_type
, CFSTR("."), 0).location
== kCFNotFound
) {
812 _SCErrorSet(kSCStatusInvalidArgument
);
817 // do not allow creation of a network service if the interface is a
818 // member of a bond or bridge
819 if (__SCNetworkInterfaceIsMember(prefs
, interface
)) {
820 _SCErrorSet(kSCStatusKeyExists
);
824 // establish the service
825 prefix
= SCPreferencesPathKeyCreateNetworkServices(NULL
);
826 path
= __SCPreferencesPathCreateUniqueChild_WithMoreSCFCompatibility(prefs
, prefix
);
827 if (path
== NULL
) path
= SCPreferencesPathCreateUniqueChild(prefs
, prefix
);
833 components
= CFStringCreateArrayBySeparatingStrings(NULL
, path
, CFSTR("/"));
836 serviceID
= CFArrayGetValueAtIndex(components
, 2);
837 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, prefs
, serviceID
, NULL
);
838 CFRelease(components
);
840 // duplicate the interface and associate the copy with the new service
841 newInterface
= (SCNetworkInterfaceRef
)__SCNetworkInterfaceCreateCopy(NULL
,
845 servicePrivate
->interface
= newInterface
;
847 // establish "default" configuration(s) for the interface
848 for (interface
= newInterface
;
850 interface
= SCNetworkInterfaceGetInterface(interface
)) {
851 SCNetworkInterfaceRef childInterface
;
852 CFStringRef childInterfaceType
= NULL
;
853 CFDictionaryRef config
;
854 CFStringRef interfaceType
;
856 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
857 childInterface
= SCNetworkInterfaceGetInterface(interface
);
858 if (childInterface
!= NULL
) {
859 childInterfaceType
= SCNetworkInterfaceGetInterfaceType(childInterface
);
862 config
= __copyInterfaceTemplate(interfaceType
, childInterfaceType
);
863 if (config
!= NULL
) {
864 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeBluetooth
) ||
865 CFEqual(interfaceType
, kSCNetworkInterfaceTypeIrDA
) ||
866 CFEqual(interfaceType
, kSCNetworkInterfaceTypeModem
) ||
867 CFEqual(interfaceType
, kSCNetworkInterfaceTypeSerial
) ||
868 CFEqual(interfaceType
, kSCNetworkInterfaceTypeWWAN
)) {
869 CFDictionaryRef overrides
;
871 overrides
= __SCNetworkInterfaceGetTemplateOverrides(interface
, kSCNetworkInterfaceTypeModem
);
873 // a ConnectionScript (and related keys) from the interface
874 // should trump the settings from the configuration template.
875 if (overrides
!= NULL
) {
876 CFMutableDictionaryRef newConfig
;
878 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
879 if (CFDictionaryContainsKey(overrides
, kSCPropNetModemConnectionScript
)) {
880 CFDictionaryRemoveValue(newConfig
, kSCPropNetModemConnectionPersonality
);
881 CFDictionaryRemoveValue(newConfig
, kSCPropNetModemConnectionScript
);
882 CFDictionaryRemoveValue(newConfig
, kSCPropNetModemDeviceVendor
);
883 CFDictionaryRemoveValue(newConfig
, kSCPropNetModemDeviceModel
);
885 CFDictionaryApplyFunction(overrides
, mergeDict
, newConfig
);
889 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
) ||
890 CFEqual(interfaceType
, kSCNetworkInterfaceTypeVPN
)) {
891 CFDictionaryRef overrides
;
893 overrides
= __SCNetworkInterfaceGetTemplateOverrides(interface
, kSCNetworkInterfaceTypePPP
);
894 if (overrides
!= NULL
) {
895 CFMutableDictionaryRef newConfig
;
897 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
898 CFDictionaryApplyFunction(overrides
, mergeDict
, newConfig
);
904 if (!__SCNetworkInterfaceSetConfiguration(interface
, NULL
, config
, TRUE
)) {
905 SCLog(TRUE
, LOG_DEBUG
,
906 CFSTR("SCNetworkService __SCNetworkInterfaceSetConfiguration failed(), interface=%@, type=NULL"),
913 // add the interface [entity] to the service
914 (void) __SCNetworkServiceSetInterfaceEntity((SCNetworkServiceRef
)servicePrivate
,
915 servicePrivate
->interface
);
917 // push the [deep] interface configuration into the service.
918 interface_config
= __SCNetworkInterfaceCopyDeepConfiguration(NULL
, servicePrivate
->interface
);
919 __SCNetworkInterfaceSetDeepConfiguration(NULL
, servicePrivate
->interface
, interface_config
);
920 if (interface_config
!= NULL
) CFRelease(interface_config
);
922 // set the service name to match that of the associated interface
924 // Note: It might seem a bit odd to call SCNetworkServiceGetName
925 // followed by an immediate call to SCNetworkServiceSetName. The
926 // trick here is that if no name has previously been set, the
927 // "get" function will return the name of the associated interface.
929 // ... and we "set" a name to ensure that applications that do
930 // not use the APIs will still find a UserDefinedName property
931 // in the SCDynamicStore.
933 interface_name
= SCNetworkServiceGetName((SCNetworkServiceRef
)servicePrivate
);
934 if (interface_name
!= NULL
) {
935 (void) SCNetworkServiceSetName((SCNetworkServiceRef
)servicePrivate
,
939 return (SCNetworkServiceRef
)servicePrivate
;
944 SCNetworkServiceEstablishDefaultConfiguration(SCNetworkServiceRef service
)
947 SCNetworkInterfaceRef interface
;
949 CFArrayRef protocolTypes
;
950 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
952 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
953 _SCErrorSet(kSCStatusInvalidArgument
);
957 interface
= SCNetworkServiceGetInterface(service
);
958 if (interface
== NULL
) {
962 protocolTypes
= SCNetworkInterfaceGetSupportedProtocolTypes(interface
);
963 n
= (protocolTypes
!= NULL
) ? CFArrayGetCount(protocolTypes
) : 0;
964 for (i
= 0; i
< n
; i
++) {
966 CFDictionaryRef newEntity
= NULL
;
968 SCNetworkProtocolRef protocol
= NULL
;
969 CFStringRef protocolType
;
971 protocolType
= CFArrayGetValueAtIndex(protocolTypes
, i
);
972 ok
= SCNetworkServiceAddProtocolType(service
, protocolType
);
973 if (!ok
&& (SCError() != kSCStatusKeyExists
)) {
974 // could not add protocol
978 protocol
= SCNetworkServiceCopyProtocol(service
, protocolType
);
979 if (protocol
== NULL
) {
980 // oops, somethings wrong (should never happen)
984 newEntity
= _protocolTemplate(service
, protocolType
);
985 ok
= SCNetworkProtocolSetConfiguration(protocol
, newEntity
);
987 // could not set default configuration
991 enabled
= !CFDictionaryContainsKey(newEntity
, kSCResvInactive
);
992 ok
= SCNetworkProtocolSetEnabled(protocol
, enabled
);
994 // could not enable/disable protocol
1000 if (newEntity
!= NULL
) CFRelease(newEntity
);
1001 if (protocol
!= NULL
) CFRelease(protocol
);
1009 SCNetworkServiceGetEnabled(SCNetworkServiceRef service
)
1013 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1015 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1016 _SCErrorSet(kSCStatusInvalidArgument
);
1020 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1021 servicePrivate
->serviceID
, // service
1023 enabled
= __getPrefsEnabled(servicePrivate
->prefs
, path
);
1030 SCNetworkInterfaceRef
1031 SCNetworkServiceGetInterface(SCNetworkServiceRef service
)
1033 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1035 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1036 _SCErrorSet(kSCStatusInvalidArgument
);
1040 if (servicePrivate
->interface
== NULL
) {
1041 CFDictionaryRef entity
;
1044 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1045 servicePrivate
->serviceID
, // service
1046 kSCEntNetInterface
); // entity
1047 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1050 if (isA_CFDictionary(entity
)) {
1051 servicePrivate
->interface
= _SCNetworkInterfaceCreateWithEntity(NULL
, entity
, service
);
1055 return servicePrivate
->interface
;
1060 SCNetworkServiceGetName(SCNetworkServiceRef service
)
1062 CFDictionaryRef entity
;
1063 SCNetworkInterfaceRef interface
;
1064 CFStringRef name
= NULL
;
1066 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1068 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1069 _SCErrorSet(kSCStatusInvalidArgument
);
1073 if (servicePrivate
->name
!= NULL
) {
1074 return servicePrivate
->name
;
1077 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1078 servicePrivate
->serviceID
, // service
1080 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1083 if (isA_CFDictionary(entity
)) {
1084 name
= CFDictionaryGetValue(entity
, kSCPropUserDefinedName
);
1085 if (isA_CFString(name
)) {
1086 servicePrivate
->name
= CFRetain(name
);
1090 interface
= SCNetworkServiceGetInterface(service
);
1091 while (interface
!= NULL
) {
1092 SCNetworkInterfaceRef childInterface
;
1093 CFStringRef interfaceType
;
1095 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
1096 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeVPN
)) {
1100 childInterface
= SCNetworkInterfaceGetInterface(interface
);
1101 if ((childInterface
== NULL
) ||
1102 CFEqual(childInterface
, kSCNetworkInterfaceIPv4
)) {
1106 interface
= childInterface
;
1109 if (interface
!= NULL
) {
1111 CFStringRef interface_name
= NULL
;
1112 CFStringRef suffix
= NULL
;
1115 // check if the [stored] service name matches the non-localized interface
1116 // name. If so, return the localized name.
1118 // Also, the older "Built-in XXX" interface names are too long for the
1119 // current UI. If we find that the [stored] service name matches the older
1120 // name, return the newer (and shorter) localized name.
1122 // Note: the user/admin will no longer be able to set the service name
1123 // to "Built-in Ethernet".
1125 for (i
= 0; i
< 3; i
++) {
1126 if (servicePrivate
->name
== NULL
) {
1127 // if no [stored] service name to compare
1133 // compare the non-localized interface name
1134 interface_name
= __SCNetworkInterfaceGetNonLocalizedDisplayName(interface
);
1135 if (interface_name
!= NULL
) {
1136 CFRetain(interface_name
);
1139 #if !TARGET_OS_IPHONE
1141 // compare the older "Built-in XXX" localized name
1142 interface_name
= __SCNetworkInterfaceCopyXLocalizedDisplayName(interface
);
1145 // compare the older "Built-in XXX" non-localized name
1146 interface_name
= __SCNetworkInterfaceCopyXNonLocalizedDisplayName(interface
);
1148 #endif // !TARGET_OS_IPHONE
1153 if (interface_name
!= NULL
) {
1154 Boolean match
= FALSE
;
1156 if (CFEqual(name
, interface_name
)) {
1157 // if service name matches the OLD localized
1160 } else if (CFStringHasPrefix(name
, interface_name
)) {
1161 CFIndex prefixLen
= CFStringGetLength(interface_name
);
1162 CFIndex suffixLen
= CFStringGetLength(name
);
1164 suffix
= CFStringCreateWithSubstring(NULL
,
1166 CFRangeMake(prefixLen
, suffixLen
- prefixLen
));
1169 CFRelease(interface_name
);
1172 CFRelease(servicePrivate
->name
);
1173 servicePrivate
->name
= NULL
;
1180 // if the service name has not been set, use the localized interface name
1182 if (servicePrivate
->name
== NULL
) {
1183 interface_name
= SCNetworkInterfaceGetLocalizedDisplayName(interface
);
1184 if (interface_name
!= NULL
) {
1185 if (suffix
!= NULL
) {
1186 servicePrivate
->name
= CFStringCreateWithFormat(NULL
,
1192 servicePrivate
->name
= CFRetain(interface_name
);
1196 if (suffix
!= NULL
) CFRelease(suffix
);
1199 return servicePrivate
->name
;
1204 SCNetworkServiceGetServiceID(SCNetworkServiceRef service
)
1206 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1208 if (!isA_SCNetworkService(service
)) {
1209 _SCErrorSet(kSCStatusInvalidArgument
);
1213 return servicePrivate
->serviceID
;
1218 SCNetworkServiceGetTypeID(void)
1220 pthread_once(&initialized
, __SCNetworkServiceInitialize
); /* initialize runtime */
1221 return __kSCNetworkServiceTypeID
;
1226 SCNetworkServiceRemove(SCNetworkServiceRef service
)
1230 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1233 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1234 _SCErrorSet(kSCStatusInvalidArgument
);
1238 // remove service from all sets
1240 sets
= SCNetworkSetCopyAll(servicePrivate
->prefs
);
1245 n
= CFArrayGetCount(sets
);
1246 for (i
= 0; i
< n
; i
++) {
1247 SCNetworkSetRef set
;
1249 set
= CFArrayGetValueAtIndex(sets
, i
);
1250 ok
= SCNetworkSetRemoveService(set
, service
);
1251 if (!ok
&& (SCError() != kSCStatusNoKey
)) {
1261 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1262 servicePrivate
->serviceID
, // service
1264 ok
= SCPreferencesPathRemoveValue(servicePrivate
->prefs
, path
);
1272 SCNetworkServiceRemoveProtocolType(SCNetworkServiceRef service
, CFStringRef protocolType
)
1274 CFDictionaryRef entity
;
1277 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1279 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1280 _SCErrorSet(kSCStatusInvalidArgument
);
1284 if (!__SCNetworkProtocolIsValidType(protocolType
)) {
1285 _SCErrorSet(kSCStatusInvalidArgument
);
1289 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1290 servicePrivate
->serviceID
, // service
1291 protocolType
); // entity
1293 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1294 if (entity
== NULL
) {
1295 // if "protocol" does not exist
1296 _SCErrorSet(kSCStatusNoKey
);
1300 ok
= SCPreferencesPathRemoveValue(servicePrivate
->prefs
, path
);
1310 SCNetworkServiceSetEnabled(SCNetworkServiceRef service
, Boolean enabled
)
1314 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1316 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1317 _SCErrorSet(kSCStatusInvalidArgument
);
1321 // make sure that we do not enable a network service if the
1322 // associated interface is a member of a bond or bridge.
1324 SCNetworkInterfaceRef interface
;
1326 interface
= SCNetworkServiceGetInterface(service
);
1327 if ((interface
!= NULL
) &&
1328 __SCNetworkInterfaceIsMember(servicePrivate
->prefs
, interface
)) {
1329 _SCErrorSet(kSCStatusKeyExists
);
1334 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1335 servicePrivate
->serviceID
, // service
1337 ok
= __setPrefsEnabled(servicePrivate
->prefs
, path
, enabled
);
1345 SCNetworkServiceSetName(SCNetworkServiceRef service
, CFStringRef name
)
1347 CFDictionaryRef entity
;
1350 CFStringRef saveName
= NULL
;
1351 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1353 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1354 _SCErrorSet(kSCStatusInvalidArgument
);
1359 if (!isA_CFString(name
)) {
1360 _SCErrorSet(kSCStatusInvalidArgument
);
1363 saveName
= CFRetain(name
);
1367 SCNetworkInterfaceRef interface
;
1369 interface
= SCNetworkServiceGetInterface(service
);
1370 while (interface
!= NULL
) {
1371 SCNetworkInterfaceRef childInterface
;
1373 childInterface
= SCNetworkInterfaceGetInterface(interface
);
1374 if (childInterface
== NULL
) {
1378 interface
= childInterface
;
1381 if (interface
!= NULL
) {
1382 CFStringRef interface_name
;
1384 interface_name
= SCNetworkInterfaceGetLocalizedDisplayName(interface
);
1385 if (interface_name
!= NULL
) {
1386 if (CFEqual(name
, interface_name
)) {
1387 // if service name matches the localized interface name
1388 // then store the non-localized name.
1389 interface_name
= __SCNetworkInterfaceGetNonLocalizedDisplayName(interface
);
1390 if (interface_name
!= NULL
) {
1391 CFRelease(saveName
);
1392 saveName
= CFRetain(interface_name
);
1394 } else if (CFStringHasPrefix(name
, interface_name
)) {
1395 CFIndex prefixLen
= CFStringGetLength(interface_name
);
1397 CFIndex suffixLen
= CFStringGetLength(name
);
1399 // if service name matches the localized interface name plus
1400 // a few extra characters) then store the non-localized name with
1402 suffix
= CFStringCreateWithSubstring(NULL
,
1404 CFRangeMake(prefixLen
, suffixLen
- prefixLen
));
1405 interface_name
= __SCNetworkInterfaceGetNonLocalizedDisplayName(interface
);
1406 if (interface_name
!= NULL
) {
1407 CFRelease(saveName
);
1408 saveName
= CFStringCreateWithFormat(NULL
,
1420 #define PREVENT_DUPLICATE_SERVICE_NAMES
1421 #ifdef PREVENT_DUPLICATE_SERVICE_NAMES
1425 // ensure that each service is uniquely named within its sets
1427 sets
= SCNetworkSetCopyAll(servicePrivate
->prefs
);
1432 set_count
= CFArrayGetCount(sets
);
1433 for (set_index
= 0; set_index
< set_count
; set_index
++) {
1434 CFIndex service_index
;
1435 Boolean isDup
= FALSE
;
1436 Boolean isMember
= FALSE
;
1437 CFIndex service_count
;
1438 CFArrayRef services
;
1439 SCNetworkSetRef set
= CFArrayGetValueAtIndex(sets
, set_index
);
1441 services
= SCNetworkSetCopyServices(set
);
1443 service_count
= CFArrayGetCount(services
);
1444 for (service_index
= 0; service_index
< service_count
; service_index
++) {
1445 CFStringRef otherID
;
1446 CFStringRef otherName
;
1447 SCNetworkServiceRef otherService
;
1449 otherService
= CFArrayGetValueAtIndex(services
, service_index
);
1451 otherID
= SCNetworkServiceGetServiceID(otherService
);
1452 if (CFEqual(servicePrivate
->serviceID
, otherID
)) {
1453 // if the service is a member of this set
1458 otherName
= SCNetworkServiceGetName(otherService
);
1459 if ((otherName
!= NULL
) && CFEqual(name
, otherName
)) {
1465 CFRelease(services
);
1467 if (isMember
&& isDup
) {
1469 * if this service is a member of the set and
1470 * the "name" is not unique.
1473 if (saveName
!= NULL
) CFRelease(saveName
);
1474 _SCErrorSet(kSCStatusKeyExists
);
1482 #endif /* PREVENT_DUPLICATE_SERVICE_NAMES */
1484 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1485 servicePrivate
->serviceID
, // service
1487 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1488 if (isA_CFDictionary(entity
) ||
1489 ((entity
== NULL
) && (name
!= NULL
))) {
1490 CFMutableDictionaryRef newEntity
;
1492 if (entity
!= NULL
) {
1493 newEntity
= CFDictionaryCreateMutableCopy(NULL
, 0, entity
);
1495 newEntity
= CFDictionaryCreateMutable(NULL
,
1497 &kCFTypeDictionaryKeyCallBacks
,
1498 &kCFTypeDictionaryValueCallBacks
);
1500 if (saveName
!= NULL
) {
1501 CFDictionarySetValue(newEntity
, kSCPropUserDefinedName
, saveName
);
1503 CFDictionaryRemoveValue(newEntity
, kSCPropUserDefinedName
);
1505 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, newEntity
);
1506 CFRelease(newEntity
);
1509 if (saveName
!= NULL
) CFRelease(saveName
);
1511 if (servicePrivate
->name
!= NULL
) CFRelease(servicePrivate
->name
);
1512 if (name
!= NULL
) CFRetain(name
);
1513 servicePrivate
->name
= name
;
1520 #pragma mark SCNetworkService SPIs
1523 SCNetworkServicePrimaryRank
1524 SCNetworkServiceGetPrimaryRank(SCNetworkServiceRef service
)
1526 CFDictionaryRef entity
;
1529 SCNetworkServicePrimaryRank rank
= kSCNetworkServicePrimaryRankDefault
;
1530 CFStringRef rankStr
= NULL
;
1531 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1533 if (!isA_SCNetworkService(service
)) {
1534 _SCErrorSet(kSCStatusInvalidArgument
);
1538 if (servicePrivate
->prefs
!= NULL
) {
1539 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
,
1540 servicePrivate
->serviceID
,
1542 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1544 if (isA_CFDictionary(entity
)) {
1545 rankStr
= CFDictionaryGetValue(entity
, kSCPropNetServicePrimaryRank
);
1546 ok
= __str_to_rank(rankStr
, &rank
);
1548 } else if (servicePrivate
->store
!= NULL
) {
1549 path
= SCDynamicStoreKeyCreateNetworkServiceEntity(NULL
,
1550 kSCDynamicStoreDomainState
,
1551 servicePrivate
->serviceID
,
1553 entity
= SCDynamicStoreCopyValue(servicePrivate
->store
, path
);
1555 if (entity
!= NULL
) {
1556 if (isA_CFDictionary(entity
)) {
1557 rankStr
= CFDictionaryGetValue(entity
, kSCPropNetServicePrimaryRank
);
1558 ok
= __str_to_rank(rankStr
, &rank
);
1563 _SCErrorSet(kSCStatusInvalidArgument
);
1568 rank
= kSCNetworkServicePrimaryRankDefault
;
1569 _SCErrorSet(kSCStatusInvalidArgument
);
1570 } else if (rank
== kSCNetworkServicePrimaryRankDefault
) {
1571 _SCErrorSet(kSCStatusOK
);
1579 SCNetworkServiceSetPrimaryRank(SCNetworkServiceRef service
,
1580 SCNetworkServicePrimaryRank newRank
)
1583 CFDictionaryRef entity
;
1584 CFMutableDictionaryRef newEntity
;
1585 CFStringRef path
= NULL
;
1586 CFStringRef rankStr
= NULL
;
1587 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1589 if (!isA_SCNetworkService(service
)) {
1590 _SCErrorSet(kSCStatusInvalidArgument
);
1594 ok
= __rank_to_str(newRank
, &rankStr
);
1596 _SCErrorSet(kSCStatusInvalidArgument
);
1600 if (servicePrivate
->prefs
!= NULL
) {
1601 if ((newRank
== kSCNetworkServicePrimaryRankDefault
) || (newRank
== kSCNetworkServicePrimaryRankNever
)) {
1602 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
,
1603 servicePrivate
->serviceID
,
1605 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1606 if (entity
!= NULL
) {
1607 if (!isA_CFDictionary(entity
)) {
1609 _SCErrorSet(kSCStatusFailed
);
1612 newEntity
= CFDictionaryCreateMutableCopy(NULL
, 0, entity
);
1614 newEntity
= CFDictionaryCreateMutable(NULL
,
1616 &kCFTypeDictionaryKeyCallBacks
,
1617 &kCFTypeDictionaryValueCallBacks
);
1619 if (rankStr
!= NULL
) {
1620 CFDictionarySetValue(newEntity
, kSCPropNetServicePrimaryRank
, rankStr
);
1622 CFDictionaryRemoveValue(newEntity
, kSCPropNetServicePrimaryRank
);
1624 if (CFDictionaryGetCount(newEntity
) > 0) {
1625 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, newEntity
);
1627 ok
= SCPreferencesPathRemoveValue(servicePrivate
->prefs
, path
);
1629 CFRelease(newEntity
);
1634 _SCErrorSet(kSCStatusInvalidArgument
);
1637 } else if (servicePrivate
->store
!= NULL
) {
1638 path
= SCDynamicStoreKeyCreateNetworkServiceEntity(NULL
,
1639 kSCDynamicStoreDomainState
,
1640 servicePrivate
->serviceID
,
1642 entity
= SCDynamicStoreCopyValue(servicePrivate
->store
, path
);
1643 if (entity
!= NULL
) {
1644 if (!isA_CFDictionary(entity
)) {
1647 _SCErrorSet(kSCStatusFailed
);
1650 newEntity
= CFDictionaryCreateMutableCopy(NULL
, 0, entity
);
1653 newEntity
= CFDictionaryCreateMutable(NULL
,
1655 &kCFTypeDictionaryKeyCallBacks
,
1656 &kCFTypeDictionaryValueCallBacks
);
1658 if (rankStr
!= NULL
) {
1659 CFDictionarySetValue(newEntity
, kSCPropNetServicePrimaryRank
, rankStr
);
1661 CFDictionaryRemoveValue(newEntity
, kSCPropNetServicePrimaryRank
);
1663 if (CFDictionaryGetCount(newEntity
) > 0) {
1664 ok
= SCDynamicStoreSetValue(servicePrivate
->store
, path
, newEntity
);
1666 ok
= SCDynamicStoreRemoveValue(servicePrivate
->store
, path
);
1668 CFRelease(newEntity
);
1673 _SCErrorSet(kSCStatusInvalidArgument
);
1679 if (path
!= NULL
) CFRelease(path
);
1685 _SCNetworkServiceIsVPN(SCNetworkServiceRef service
)
1687 SCNetworkInterfaceRef interface
;
1688 CFStringRef interfaceType
;
1690 interface
= SCNetworkServiceGetInterface(service
);
1691 if (interface
== NULL
) {
1695 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
1696 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
)) {
1697 interface
= SCNetworkInterfaceGetInterface(interface
);
1698 if (interface
== NULL
) {
1702 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
1703 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeL2TP
)) {
1706 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPTP
)) {
1709 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeVPN
)) {
1711 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeIPSec
)) {
1720 SCNetworkServiceSetExternalID(SCNetworkServiceRef service
, CFStringRef identifierDomain
, CFStringRef identifier
)
1722 CFStringRef prefs_path
;
1723 CFDictionaryRef service_dictionary
;
1724 SCNetworkServicePrivateRef service_private
= (SCNetworkServicePrivateRef
)service
;
1725 Boolean success
= FALSE
;
1726 CFStringRef prefixed_domain
;
1728 if (!isA_SCNetworkService(service
) || (service_private
->prefs
== NULL
) || !isA_CFString(identifierDomain
)) {
1729 _SCErrorSet(kSCStatusInvalidArgument
);
1733 if (identifier
!= NULL
&& !isA_CFString(identifier
)) {
1734 _SCErrorSet(kSCStatusInvalidArgument
);
1738 prefixed_domain
= CFStringCreateWithFormat(kCFAllocatorDefault
, 0, CFSTR("%s%@"), EXTERNAL_ID_DOMAIN_PREFIX
, identifierDomain
);
1740 prefs_path
= SCPreferencesPathKeyCreateNetworkServiceEntity(kCFAllocatorDefault
,
1741 service_private
->serviceID
,
1744 service_dictionary
= SCPreferencesPathGetValue(service_private
->prefs
, prefs_path
);
1745 if (isA_CFDictionary(service_dictionary
) || ((service_dictionary
== NULL
) && (identifier
!= NULL
))) {
1746 CFMutableDictionaryRef new_service_dictionary
;
1748 if (service_dictionary
!= NULL
) {
1749 new_service_dictionary
= CFDictionaryCreateMutableCopy(kCFAllocatorDefault
, 0, service_dictionary
);
1751 new_service_dictionary
= CFDictionaryCreateMutable(kCFAllocatorDefault
,
1753 &kCFTypeDictionaryKeyCallBacks
,
1754 &kCFTypeDictionaryValueCallBacks
);
1757 if (identifier
!= NULL
) {
1758 CFDictionarySetValue(new_service_dictionary
, prefixed_domain
, identifier
);
1760 CFDictionaryRemoveValue(new_service_dictionary
, prefixed_domain
);
1762 success
= SCPreferencesPathSetValue(service_private
->prefs
, prefs_path
, new_service_dictionary
);
1763 CFRelease(new_service_dictionary
);
1765 CFRelease(prefs_path
);
1767 if (identifier
!= NULL
) {
1768 if (service_private
->externalIDs
== NULL
) {
1769 service_private
->externalIDs
= CFDictionaryCreateMutable(kCFAllocatorDefault
,
1771 &kCFTypeDictionaryKeyCallBacks
,
1772 &kCFTypeDictionaryValueCallBacks
);
1774 CFDictionarySetValue(service_private
->externalIDs
, prefixed_domain
, identifier
);
1776 if (service_private
->externalIDs
!= NULL
) {
1777 CFDictionaryRemoveValue(service_private
->externalIDs
, prefixed_domain
);
1781 CFRelease(prefixed_domain
);
1784 _SCErrorSet(kSCStatusFailed
);
1792 SCNetworkServiceCopyExternalID(SCNetworkServiceRef service
, CFStringRef identifierDomain
)
1794 SCNetworkServicePrivateRef service_private
= (SCNetworkServicePrivateRef
)service
;
1795 CFStringRef identifier
= NULL
;
1796 CFStringRef prefixed_domain
;
1798 if (!isA_SCNetworkService(service
) || (service_private
->prefs
== NULL
) || !isA_CFString(identifierDomain
)) {
1799 _SCErrorSet(kSCStatusInvalidArgument
);
1803 prefixed_domain
= CFStringCreateWithFormat(kCFAllocatorDefault
, 0, CFSTR("%s%@"), EXTERNAL_ID_DOMAIN_PREFIX
, identifierDomain
);
1805 if (service_private
->externalIDs
!= NULL
) {
1806 identifier
= CFDictionaryGetValue(service_private
->externalIDs
, prefixed_domain
);
1807 if (identifier
!= NULL
) {
1808 CFRetain(identifier
);
1812 if (identifier
== NULL
) {
1813 CFStringRef prefs_path
;
1814 CFDictionaryRef service_dictionary
;
1816 prefs_path
= SCPreferencesPathKeyCreateNetworkServiceEntity(kCFAllocatorDefault
,
1817 service_private
->serviceID
,
1820 service_dictionary
= SCPreferencesPathGetValue(service_private
->prefs
, prefs_path
);
1821 if (isA_CFDictionary(service_dictionary
)) {
1822 identifier
= CFDictionaryGetValue(service_dictionary
, prefixed_domain
);
1823 if (identifier
!= NULL
) {
1824 CFRetain(identifier
);
1825 if (service_private
->externalIDs
== NULL
) {
1826 service_private
->externalIDs
= CFDictionaryCreateMutable(kCFAllocatorDefault
,
1828 &kCFTypeDictionaryKeyCallBacks
,
1829 &kCFTypeDictionaryValueCallBacks
);
1831 CFDictionarySetValue(service_private
->externalIDs
, prefixed_domain
, identifier
);
1834 CFRelease(prefs_path
);
1837 CFRelease(prefixed_domain
);
1839 if (identifier
== NULL
) {
1840 _SCErrorSet(kSCStatusNoKey
);