2 * Copyright (c) 2004-2011 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
__SCNetworkServiceCopyDescription (CFTypeRef cf
);
43 static void __SCNetworkServiceDeallocate (CFTypeRef cf
);
44 static Boolean
__SCNetworkServiceEqual (CFTypeRef cf1
, CFTypeRef cf2
);
45 static CFHashCode
__SCNetworkServiceHash (CFTypeRef cf
);
48 static CFTypeID __kSCNetworkServiceTypeID
= _kCFRuntimeNotATypeID
;
51 static const CFRuntimeClass __SCNetworkServiceClass
= {
53 "SCNetworkService", // className
56 __SCNetworkServiceDeallocate
, // dealloc
57 __SCNetworkServiceEqual
, // equal
58 __SCNetworkServiceHash
, // hash
59 NULL
, // copyFormattingDesc
60 __SCNetworkServiceCopyDescription
// copyDebugDesc
64 static pthread_once_t initialized
= PTHREAD_ONCE_INIT
;
68 __SCNetworkServiceCopyDescription(CFTypeRef cf
)
70 CFAllocatorRef allocator
= CFGetAllocator(cf
);
71 CFMutableStringRef result
;
72 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)cf
;
74 result
= CFStringCreateMutable(allocator
, 0);
75 CFStringAppendFormat(result
, NULL
, CFSTR("<SCNetworkService %p [%p]> {"), cf
, allocator
);
76 CFStringAppendFormat(result
, NULL
, CFSTR("id = %@"), servicePrivate
->serviceID
);
77 if (servicePrivate
->prefs
!= NULL
) {
78 CFStringAppendFormat(result
, NULL
, CFSTR(", prefs = %p"), servicePrivate
->prefs
);
79 } else if (servicePrivate
->store
!= NULL
) {
80 CFStringAppendFormat(result
, NULL
, CFSTR(", store = %p"), servicePrivate
->store
);
82 if (servicePrivate
->name
!= NULL
) {
83 CFStringAppendFormat(result
, NULL
, CFSTR(", name = %@"), servicePrivate
->name
);
85 CFStringAppendFormat(result
, NULL
, CFSTR("}"));
92 __SCNetworkServiceDeallocate(CFTypeRef cf
)
94 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)cf
;
96 /* release resources */
98 CFRelease(servicePrivate
->serviceID
);
99 if (servicePrivate
->interface
!= NULL
) CFRelease(servicePrivate
->interface
);
100 if (servicePrivate
->prefs
!= NULL
) CFRelease(servicePrivate
->prefs
);
101 if (servicePrivate
->store
!= NULL
) CFRelease(servicePrivate
->store
);
102 if (servicePrivate
->name
!= NULL
) CFRelease(servicePrivate
->name
);
109 __SCNetworkServiceEqual(CFTypeRef cf1
, CFTypeRef cf2
)
111 SCNetworkServicePrivateRef s1
= (SCNetworkServicePrivateRef
)cf1
;
112 SCNetworkServicePrivateRef s2
= (SCNetworkServicePrivateRef
)cf2
;
117 if (s1
->prefs
!= s2
->prefs
)
118 return FALSE
; // if not the same prefs
120 if (!CFEqual(s1
->serviceID
, s2
->serviceID
))
121 return FALSE
; // if not the same service identifier
128 __SCNetworkServiceHash(CFTypeRef cf
)
130 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)cf
;
132 return CFHash(servicePrivate
->serviceID
);
137 __SCNetworkServiceInitialize(void)
139 __kSCNetworkServiceTypeID
= _CFRuntimeRegisterClass(&__SCNetworkServiceClass
);
144 __private_extern__ SCNetworkServicePrivateRef
145 __SCNetworkServiceCreatePrivate(CFAllocatorRef allocator
,
146 SCPreferencesRef prefs
,
147 CFStringRef serviceID
,
148 SCNetworkInterfaceRef interface
)
150 SCNetworkServicePrivateRef servicePrivate
;
153 /* initialize runtime */
154 pthread_once(&initialized
, __SCNetworkServiceInitialize
);
156 /* allocate target */
157 size
= sizeof(SCNetworkServicePrivate
) - sizeof(CFRuntimeBase
);
158 servicePrivate
= (SCNetworkServicePrivateRef
)_CFRuntimeCreateInstance(allocator
,
159 __kSCNetworkServiceTypeID
,
162 if (servicePrivate
== NULL
) {
166 servicePrivate
->prefs
= (prefs
!= NULL
) ? CFRetain(prefs
): NULL
;
167 servicePrivate
->serviceID
= CFStringCreateCopy(NULL
, serviceID
);
168 servicePrivate
->interface
= (interface
!= NULL
) ? CFRetain(interface
) : NULL
;
169 servicePrivate
->name
= NULL
;
171 return servicePrivate
;
176 #pragma mark Service ordering
180 _SCNetworkServiceCompare(const void *val1
, const void *val2
, void *context
)
184 CFArrayRef order
= (CFArrayRef
)context
;
185 SCNetworkServiceRef s1
= (SCNetworkServiceRef
)val1
;
186 SCNetworkServiceRef s2
= (SCNetworkServiceRef
)val2
;
188 id1
= SCNetworkServiceGetServiceID(s1
);
189 id2
= SCNetworkServiceGetServiceID(s2
);
196 range
= CFRangeMake(0, CFArrayGetCount(order
));
197 o1
= CFArrayGetFirstIndexOfValue(order
, range
, id1
);
198 o2
= CFArrayGetFirstIndexOfValue(order
, range
, id2
);
201 return (o2
!= kCFNotFound
) ? kCFCompareGreaterThan
: kCFCompareLessThan
;
202 } else if (o1
< o2
) {
203 return (o1
!= kCFNotFound
) ? kCFCompareLessThan
: kCFCompareGreaterThan
;
207 return CFStringCompare(id1
, id2
, 0);
212 #pragma mark SCNetworkService APIs
218 __private_extern__ CFArrayRef
/* of SCNetworkServiceRef's */
219 __SCNetworkServiceCopyAllEnabled(SCPreferencesRef prefs
)
221 CFMutableArrayRef array
= NULL
;
226 sets
= SCNetworkSetCopyAll(prefs
);
231 n_sets
= CFArrayGetCount(sets
);
232 for (i_sets
= 0; i_sets
< n_sets
; i_sets
++) {
238 set
= CFArrayGetValueAtIndex(sets
, i_sets
);
239 services
= SCNetworkSetCopyServices(set
);
240 if (services
== NULL
) {
244 n_services
= CFArrayGetCount(services
);
245 for (i_services
= 0; i_services
< n_services
; i_services
++) {
246 SCNetworkServiceRef service
;
248 service
= CFArrayGetValueAtIndex(services
, i_services
);
249 if (!SCNetworkServiceGetEnabled(service
)) {
254 if ((array
== NULL
) ||
255 !CFArrayContainsValue(array
,
256 CFRangeMake(0, CFArrayGetCount(array
)),
259 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
261 CFArrayAppendValue(array
, service
);
272 __private_extern__ Boolean
273 __SCNetworkServiceExistsForInterface(CFArrayRef services
, SCNetworkInterfaceRef interface
)
278 n
= isA_CFArray(services
) ? CFArrayGetCount(services
) : 0;
279 for (i
= 0; i
< n
; i
++) {
280 SCNetworkServiceRef service
;
281 SCNetworkInterfaceRef service_interface
;
283 service
= CFArrayGetValueAtIndex(services
, i
);
285 service_interface
= SCNetworkServiceGetInterface(service
);
286 while (service_interface
!= NULL
) {
287 if (CFEqual(interface
, service_interface
)) {
291 service_interface
= SCNetworkInterfaceGetInterface(service_interface
);
299 __private_extern__ CFStringRef
300 __SCNetworkServiceNextName(SCNetworkServiceRef service
)
302 CFArrayRef components
;
305 CFMutableArrayRef newComponents
;
308 name
= SCNetworkServiceGetName(service
);
313 components
= CFStringCreateArrayBySeparatingStrings(NULL
, name
, CFSTR(" "));
314 if (components
!= NULL
) {
315 newComponents
= CFArrayCreateMutableCopy(NULL
, 0, components
);
316 CFRelease(components
);
318 newComponents
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
319 CFArrayAppendValue(newComponents
, name
);
322 n
= CFArrayGetCount(newComponents
);
326 str
= CFArrayGetValueAtIndex(newComponents
, n
- 1);
327 suffix
= CFStringGetIntValue(str
);
329 CFArrayRemoveValueAtIndex(newComponents
, n
- 1);
335 name
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%d"), suffix
);
336 CFArrayAppendValue(newComponents
, name
);
339 name
= CFStringCreateByCombiningStrings(NULL
, newComponents
, CFSTR(" "));
340 CFRelease(newComponents
);
347 mergeDict(const void *key
, const void *value
, void *context
)
349 CFMutableDictionaryRef newDict
= (CFMutableDictionaryRef
)context
;
351 CFDictionarySetValue(newDict
, key
, value
);
356 static CFDictionaryRef
357 _protocolTemplate(SCNetworkServiceRef service
, CFStringRef protocolType
)
359 SCNetworkInterfaceRef interface
;
360 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
361 CFDictionaryRef
template = NULL
;
363 interface
= servicePrivate
->interface
;
364 if (interface
!= NULL
) {
365 SCNetworkInterfaceRef childInterface
;
366 CFStringRef childInterfaceType
= NULL
;
367 CFStringRef interfaceType
;
370 interfaceType
= SCNetworkInterfaceGetInterfaceType(servicePrivate
->interface
);
371 childInterface
= SCNetworkInterfaceGetInterface(servicePrivate
->interface
);
372 if (childInterface
!= NULL
) {
373 childInterfaceType
= SCNetworkInterfaceGetInterfaceType(childInterface
);
376 template = __copyProtocolTemplate(interfaceType
, childInterfaceType
, protocolType
);
377 if (template != NULL
) {
378 CFDictionaryRef overrides
;
380 // move to the interface at the lowest layer
381 while (childInterface
!= NULL
) {
382 interface
= childInterface
;
383 childInterface
= SCNetworkInterfaceGetInterface(interface
);
386 overrides
= __SCNetworkInterfaceGetTemplateOverrides(interface
, protocolType
);
387 if (overrides
!= NULL
) {
388 CFMutableDictionaryRef newTemplate
;
390 newTemplate
= CFDictionaryCreateMutableCopy(NULL
, 0, template);
391 CFDictionaryApplyFunction(overrides
, mergeDict
, newTemplate
);
393 template = newTemplate
;
398 if (template == NULL
) {
399 template = CFDictionaryCreate(NULL
,
403 &kCFTypeDictionaryKeyCallBacks
,
404 &kCFTypeDictionaryValueCallBacks
);
412 SCNetworkServiceAddProtocolType(SCNetworkServiceRef service
, CFStringRef protocolType
)
414 CFDictionaryRef entity
;
415 CFDictionaryRef newEntity
= NULL
;
418 SCNetworkProtocolRef protocol
;
419 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
421 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
422 _SCErrorSet(kSCStatusInvalidArgument
);
426 if (!__SCNetworkProtocolIsValidType(protocolType
)) {
427 _SCErrorSet(kSCStatusInvalidArgument
);
431 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
432 servicePrivate
->serviceID
, // service
433 protocolType
); // entity
435 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
436 if (entity
!= NULL
) {
437 // if "protocol" already exists
438 _SCErrorSet(kSCStatusKeyExists
);
442 newEntity
= CFDictionaryCreate(NULL
,
446 &kCFTypeDictionaryKeyCallBacks
,
447 &kCFTypeDictionaryValueCallBacks
);
448 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, newEntity
);
449 CFRelease(newEntity
);
454 protocol
= SCNetworkServiceCopyProtocol(service
, protocolType
);
455 newEntity
= _protocolTemplate(service
, protocolType
);
456 ok
= SCNetworkProtocolSetConfiguration(protocol
, newEntity
);
457 CFRelease(newEntity
);
467 CFArrayRef
/* of SCNetworkServiceRef's */
468 SCNetworkServiceCopyAll(SCPreferencesRef prefs
)
470 CFMutableArrayRef array
;
473 CFDictionaryRef services
;
475 path
= SCPreferencesPathKeyCreateNetworkServices(NULL
);
476 services
= SCPreferencesPathGetValue(prefs
, path
);
479 if ((services
!= NULL
) && !isA_CFDictionary(services
)) {
483 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
485 n
= (services
!= NULL
) ? CFDictionaryGetCount(services
) : 0;
488 const void * keys_q
[N_QUICK
];
489 const void ** keys
= keys_q
;
490 const void * vals_q
[N_QUICK
];
491 const void ** vals
= vals_q
;
493 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
494 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
495 vals
= CFAllocatorAllocate(NULL
, n
* sizeof(CFPropertyListRef
), 0);
497 CFDictionaryGetKeysAndValues(services
, keys
, vals
);
498 for (i
= 0; i
< n
; i
++) {
499 CFDictionaryRef entity
;
500 SCNetworkServicePrivateRef servicePrivate
;
502 if (!isA_CFDictionary(vals
[i
])) {
505 CFSTR("SCNetworkServiceCopyAll(): error w/service \"%@\"\n"),
510 entity
= CFDictionaryGetValue(vals
[i
], kSCEntNetInterface
);
511 if (!isA_CFDictionary(entity
)) {
515 CFSTR("SCNetworkServiceCopyAll(): no \"%@\" entity for service \"%@\"\n"),
521 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, prefs
, keys
[i
], NULL
);
522 CFArrayAppendValue(array
, (SCNetworkServiceRef
)servicePrivate
);
523 CFRelease(servicePrivate
);
525 if (keys
!= keys_q
) {
526 CFAllocatorDeallocate(NULL
, keys
);
527 CFAllocatorDeallocate(NULL
, vals
);
536 * build a list of all of a servives entity types that are associated
537 * with the services interface. The list will include :
539 * - entity types associated with the interface type (Ethernet, FireWire, PPP, ...)
540 * - entity types associated with the interface sub-type (PPPSerial, PPPoE, L2TP, PPTP, ...)
541 * - entity types associated with the hardware device (Ethernet, AirPort, FireWire, Modem, ...)
544 _copyInterfaceEntityTypes(CFDictionaryRef protocols
)
546 CFDictionaryRef interface
;
547 CFMutableSetRef interface_entity_types
;
549 interface_entity_types
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
551 interface
= CFDictionaryGetValue(protocols
, kSCEntNetInterface
);
552 if (isA_CFDictionary(interface
)) {
553 CFStringRef entities
[] = { kSCPropNetInterfaceType
,
554 kSCPropNetInterfaceSubType
,
555 kSCPropNetInterfaceHardware
};
558 // include the "Interface" entity itself
559 CFSetAddValue(interface_entity_types
, kSCEntNetInterface
);
561 // include the entities associated with the interface
562 for (i
= 0; i
< sizeof(entities
)/sizeof(entities
[0]); i
++) {
565 entity
= CFDictionaryGetValue(interface
, entities
[i
]);
566 if (isA_CFString(entity
)) {
567 CFSetAddValue(interface_entity_types
, entity
);
572 * and, because we've found some misguided network preference code
573 * developers leaving [PPP] entity dictionaries around even though
574 * they are unused and/or unneeded...
576 CFSetAddValue(interface_entity_types
, kSCEntNetPPP
);
579 return interface_entity_types
;
584 SCNetworkServiceCopy(SCPreferencesRef prefs
, CFStringRef serviceID
)
586 CFDictionaryRef entity
;
588 SCNetworkServicePrivateRef servicePrivate
;
590 if (!isA_CFString(serviceID
)) {
591 _SCErrorSet(kSCStatusInvalidArgument
);
595 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
596 serviceID
, // service
597 kSCEntNetInterface
); // entity
598 entity
= SCPreferencesPathGetValue(prefs
, path
);
601 if (!isA_CFDictionary(entity
)) {
602 // a "service" must have an "interface"
603 _SCErrorSet(kSCStatusNoKey
);
607 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, prefs
, serviceID
, NULL
);
608 return (SCNetworkServiceRef
)servicePrivate
;
613 _SCNetworkServiceCopyActive(SCDynamicStoreRef store
, CFStringRef serviceID
)
615 SCNetworkServicePrivateRef servicePrivate
;
617 if (!isA_CFString(serviceID
)) {
618 _SCErrorSet(kSCStatusInvalidArgument
);
622 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, NULL
, serviceID
, NULL
);
624 servicePrivate
->store
= CFRetain(store
);
626 return (SCNetworkServiceRef
)servicePrivate
;
631 SCNetworkServiceCopyProtocol(SCNetworkServiceRef service
, CFStringRef protocolType
)
633 CFSetRef non_protocol_entities
;
635 CFDictionaryRef protocols
;
636 SCNetworkProtocolPrivateRef protocolPrivate
= NULL
;
637 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
639 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
640 _SCErrorSet(kSCStatusInvalidArgument
);
644 if (!isA_CFString(protocolType
)) {
645 _SCErrorSet(kSCStatusInvalidArgument
);
649 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
650 servicePrivate
->serviceID
, // service
652 protocols
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
655 if (!isA_CFDictionary(protocols
)) {
657 _SCErrorSet(kSCStatusFailed
);
661 non_protocol_entities
= _copyInterfaceEntityTypes(protocols
);
662 if (CFSetContainsValue(non_protocol_entities
, protocolType
)) {
663 // if the "protocolType" matches an interface entity type
664 _SCErrorSet(kSCStatusInvalidArgument
);
668 if (!CFDictionaryContainsKey(protocols
, protocolType
)) {
669 // if the "protocolType" entity does not exist
670 _SCErrorSet(kSCStatusNoKey
);
674 protocolPrivate
= __SCNetworkProtocolCreatePrivate(NULL
, protocolType
, service
);
678 CFRelease(non_protocol_entities
);
680 return (SCNetworkProtocolRef
)protocolPrivate
;
684 CFArrayRef
/* of SCNetworkProtocolRef's */
685 SCNetworkServiceCopyProtocols(SCNetworkServiceRef service
)
687 CFMutableArrayRef array
;
689 CFSetRef non_protocol_entities
;
691 CFDictionaryRef protocols
;
692 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
694 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
695 _SCErrorSet(kSCStatusInvalidArgument
);
699 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
700 servicePrivate
->serviceID
, // service
702 protocols
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
705 if (!isA_CFDictionary(protocols
)) {
707 _SCErrorSet(kSCStatusFailed
);
711 non_protocol_entities
= _copyInterfaceEntityTypes(protocols
);
713 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
715 n
= CFDictionaryGetCount(protocols
);
718 const void * keys_q
[N_QUICK
];
719 const void ** keys
= keys_q
;
720 const void * vals_q
[N_QUICK
];
721 const void ** vals
= vals_q
;
723 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
724 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
725 vals
= CFAllocatorAllocate(NULL
, n
* sizeof(CFPropertyListRef
), 0);
727 CFDictionaryGetKeysAndValues(protocols
, keys
, vals
);
728 for (i
= 0; i
< n
; i
++) {
729 SCNetworkProtocolPrivateRef protocolPrivate
;
731 if (!isA_CFDictionary(vals
[i
])) {
732 // if it's not a dictionary then it can't be a protocol entity
736 if (CFSetContainsValue(non_protocol_entities
, keys
[i
])) {
737 // skip any non-protocol (interface) entities
741 protocolPrivate
= __SCNetworkProtocolCreatePrivate(NULL
, keys
[i
], service
);
742 CFArrayAppendValue(array
, (SCNetworkProtocolRef
)protocolPrivate
);
744 CFRelease(protocolPrivate
);
746 if (keys
!= keys_q
) {
747 CFAllocatorDeallocate(NULL
, keys
);
748 CFAllocatorDeallocate(NULL
, vals
);
752 CFRelease(non_protocol_entities
);
759 __SCNetworkServiceSetInterfaceEntity(SCNetworkServiceRef service
,
760 SCNetworkInterfaceRef interface
)
762 CFDictionaryRef entity
;
765 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
767 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
768 servicePrivate
->serviceID
, // service
769 kSCEntNetInterface
); // entity
770 entity
= __SCNetworkInterfaceCopyInterfaceEntity(interface
);
771 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, entity
);
780 SCNetworkServiceCreate(SCPreferencesRef prefs
, SCNetworkInterfaceRef interface
)
782 CFArrayRef components
;
783 CFArrayRef interface_config
;
784 CFStringRef interface_name
;
785 SCNetworkInterfaceRef newInterface
;
788 CFStringRef serviceID
;
789 SCNetworkServicePrivateRef servicePrivate
;
790 CFArrayRef supported_protocols
;
792 if (!isA_SCNetworkInterface(interface
)) {
793 _SCErrorSet(kSCStatusInvalidArgument
);
797 // only allow network interfaces which support one or more protocols
798 // to be added to a service. The one exception is that we allow
799 // third-party interface types to be configured.
800 supported_protocols
= SCNetworkInterfaceGetSupportedProtocolTypes(interface
);
801 if (supported_protocols
== NULL
) {
802 CFStringRef interface_type
;
804 interface_type
= SCNetworkInterfaceGetInterfaceType(interface
);
805 if (CFStringFind(interface_type
, CFSTR("."), 0).location
== kCFNotFound
) {
806 _SCErrorSet(kSCStatusInvalidArgument
);
811 // do not allow creation of a network service if the interface is a
812 // member of a bond or bridge
813 if (__SCNetworkInterfaceIsMember(prefs
, interface
)) {
814 _SCErrorSet(kSCStatusKeyExists
);
818 // establish the service
819 prefix
= SCPreferencesPathKeyCreateNetworkServices(NULL
);
820 path
= __SCPreferencesPathCreateUniqueChild_WithMoreSCFCompatibility(prefs
, prefix
);
821 if (path
== NULL
) path
= SCPreferencesPathCreateUniqueChild(prefs
, prefix
);
827 components
= CFStringCreateArrayBySeparatingStrings(NULL
, path
, CFSTR("/"));
830 serviceID
= CFArrayGetValueAtIndex(components
, 2);
831 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, prefs
, serviceID
, NULL
);
832 CFRelease(components
);
834 // duplicate the interface and associate the copy with the new service
835 newInterface
= (SCNetworkInterfaceRef
)__SCNetworkInterfaceCreateCopy(NULL
,
839 servicePrivate
->interface
= newInterface
;
841 // establish "default" configuration(s) for the interface
842 for (interface
= newInterface
;
844 interface
= SCNetworkInterfaceGetInterface(interface
)) {
845 SCNetworkInterfaceRef childInterface
;
846 CFStringRef childInterfaceType
= NULL
;
847 CFDictionaryRef config
;
848 CFStringRef interfaceType
;
850 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
851 childInterface
= SCNetworkInterfaceGetInterface(interface
);
852 if (childInterface
!= NULL
) {
853 childInterfaceType
= SCNetworkInterfaceGetInterfaceType(childInterface
);
856 config
= __copyInterfaceTemplate(interfaceType
, childInterfaceType
);
857 if (config
!= NULL
) {
858 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeBluetooth
) ||
859 CFEqual(interfaceType
, kSCNetworkInterfaceTypeIrDA
) ||
860 CFEqual(interfaceType
, kSCNetworkInterfaceTypeModem
) ||
861 CFEqual(interfaceType
, kSCNetworkInterfaceTypeSerial
) ||
862 CFEqual(interfaceType
, kSCNetworkInterfaceTypeWWAN
)) {
863 CFDictionaryRef overrides
;
865 overrides
= __SCNetworkInterfaceGetTemplateOverrides(interface
, kSCNetworkInterfaceTypeModem
);
867 // a ConnectionScript (and related keys) from the interface
868 // should trump the settings from the configuration template.
869 if (overrides
!= NULL
) {
870 CFMutableDictionaryRef newConfig
;
872 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
873 if (CFDictionaryContainsKey(overrides
, kSCPropNetModemConnectionScript
)) {
874 CFDictionaryRemoveValue(newConfig
, kSCPropNetModemConnectionPersonality
);
875 CFDictionaryRemoveValue(newConfig
, kSCPropNetModemConnectionScript
);
876 CFDictionaryRemoveValue(newConfig
, kSCPropNetModemDeviceVendor
);
877 CFDictionaryRemoveValue(newConfig
, kSCPropNetModemDeviceModel
);
879 CFDictionaryApplyFunction(overrides
, mergeDict
, newConfig
);
883 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
) ||
884 CFEqual(interfaceType
, kSCNetworkInterfaceTypeVPN
)) {
885 CFDictionaryRef overrides
;
887 overrides
= __SCNetworkInterfaceGetTemplateOverrides(interface
, kSCNetworkInterfaceTypePPP
);
888 if (overrides
!= NULL
) {
889 CFMutableDictionaryRef newConfig
;
891 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
892 CFDictionaryApplyFunction(overrides
, mergeDict
, newConfig
);
898 if (!__SCNetworkInterfaceSetConfiguration(interface
, NULL
, config
, TRUE
)) {
899 SCLog(TRUE
, LOG_DEBUG
,
900 CFSTR("SCNetworkService __SCNetworkInterfaceSetConfiguration failed(), interface=%@, type=NULL"),
907 // add the interface [entity] to the service
908 (void) __SCNetworkServiceSetInterfaceEntity((SCNetworkServiceRef
)servicePrivate
,
909 servicePrivate
->interface
);
911 // push the [deep] interface configuration into the service.
912 interface_config
= __SCNetworkInterfaceCopyDeepConfiguration(NULL
, servicePrivate
->interface
);
913 __SCNetworkInterfaceSetDeepConfiguration(NULL
, servicePrivate
->interface
, interface_config
);
914 if (interface_config
!= NULL
) CFRelease(interface_config
);
916 // set the service name to match that of the associated interface
918 // Note: It might seem a bit odd to call SCNetworkServiceGetName
919 // followed by an immediate call to SCNetworkServiceSetName. The
920 // trick here is that if no name has previously been set, the
921 // "get" function will return the name of the associated interface.
923 // ... and we "set" a name to ensure that applications that do
924 // not use the APIs will still find a UserDefinedName property
925 // in the SCDynamicStore.
927 interface_name
= SCNetworkServiceGetName((SCNetworkServiceRef
)servicePrivate
);
928 if (interface_name
!= NULL
) {
929 (void) SCNetworkServiceSetName((SCNetworkServiceRef
)servicePrivate
,
933 return (SCNetworkServiceRef
)servicePrivate
;
938 SCNetworkServiceEstablishDefaultConfiguration(SCNetworkServiceRef service
)
941 SCNetworkInterfaceRef interface
;
943 CFArrayRef protocolTypes
;
944 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
946 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
947 _SCErrorSet(kSCStatusInvalidArgument
);
951 interface
= SCNetworkServiceGetInterface(service
);
952 if (interface
== NULL
) {
956 protocolTypes
= SCNetworkInterfaceGetSupportedProtocolTypes(interface
);
957 n
= (protocolTypes
!= NULL
) ? CFArrayGetCount(protocolTypes
) : 0;
958 for (i
= 0; i
< n
; i
++) {
960 CFDictionaryRef newEntity
= NULL
;
962 SCNetworkProtocolRef protocol
= NULL
;
963 CFStringRef protocolType
;
965 protocolType
= CFArrayGetValueAtIndex(protocolTypes
, i
);
966 ok
= SCNetworkServiceAddProtocolType(service
, protocolType
);
967 if (!ok
&& (SCError() != kSCStatusKeyExists
)) {
968 // could not add protocol
972 protocol
= SCNetworkServiceCopyProtocol(service
, protocolType
);
973 if (protocol
== NULL
) {
974 // oops, somethings wrong (should never happen)
978 newEntity
= _protocolTemplate(service
, protocolType
);
979 ok
= SCNetworkProtocolSetConfiguration(protocol
, newEntity
);
981 // could not set default configuration
985 enabled
= !CFDictionaryContainsKey(newEntity
, kSCResvInactive
);
986 ok
= SCNetworkProtocolSetEnabled(protocol
, enabled
);
988 // could not enable/disable protocol
994 if (newEntity
!= NULL
) CFRelease(newEntity
);
995 if (protocol
!= NULL
) CFRelease(protocol
);
1003 SCNetworkServiceGetEnabled(SCNetworkServiceRef service
)
1007 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1009 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1010 _SCErrorSet(kSCStatusInvalidArgument
);
1014 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1015 servicePrivate
->serviceID
, // service
1017 enabled
= __getPrefsEnabled(servicePrivate
->prefs
, path
);
1024 SCNetworkInterfaceRef
1025 SCNetworkServiceGetInterface(SCNetworkServiceRef service
)
1027 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1029 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1030 _SCErrorSet(kSCStatusInvalidArgument
);
1034 if (servicePrivate
->interface
== NULL
) {
1035 CFDictionaryRef entity
;
1038 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1039 servicePrivate
->serviceID
, // service
1040 kSCEntNetInterface
); // entity
1041 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1044 if (isA_CFDictionary(entity
)) {
1045 servicePrivate
->interface
= _SCNetworkInterfaceCreateWithEntity(NULL
, entity
, service
);
1049 return servicePrivate
->interface
;
1054 SCNetworkServiceGetName(SCNetworkServiceRef service
)
1056 CFDictionaryRef entity
;
1057 SCNetworkInterfaceRef interface
;
1058 CFStringRef name
= NULL
;
1060 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1062 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1063 _SCErrorSet(kSCStatusInvalidArgument
);
1067 if (servicePrivate
->name
!= NULL
) {
1068 return servicePrivate
->name
;
1071 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1072 servicePrivate
->serviceID
, // service
1074 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1077 if (isA_CFDictionary(entity
)) {
1078 name
= CFDictionaryGetValue(entity
, kSCPropUserDefinedName
);
1079 if (isA_CFString(name
)) {
1080 servicePrivate
->name
= CFRetain(name
);
1084 interface
= SCNetworkServiceGetInterface(service
);
1085 while (interface
!= NULL
) {
1086 SCNetworkInterfaceRef childInterface
;
1087 CFStringRef interfaceType
;
1089 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
1090 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeVPN
)) {
1094 childInterface
= SCNetworkInterfaceGetInterface(interface
);
1095 if ((childInterface
== NULL
) ||
1096 CFEqual(childInterface
, kSCNetworkInterfaceIPv4
)) {
1100 interface
= childInterface
;
1103 if (interface
!= NULL
) {
1105 CFStringRef interface_name
= NULL
;
1106 CFStringRef suffix
= NULL
;
1109 // check if the [stored] service name matches the non-localized interface
1110 // name. If so, return the localized name.
1112 // Also, the older "Built-in XXX" interface names are too long for the
1113 // current UI. If we find that the [stored] service name matches the older
1114 // name, return the newer (and shorter) localized name.
1116 // Note: the user/admin will no longer be able to set the service name
1117 // to "Built-in Ethernet".
1119 for (i
= 0; i
< 3; i
++) {
1120 if (servicePrivate
->name
== NULL
) {
1121 // if no [stored] service name to compare
1127 // compare the non-localized interface name
1128 interface_name
= __SCNetworkInterfaceGetNonLocalizedDisplayName(interface
);
1129 if (interface_name
!= NULL
) {
1130 CFRetain(interface_name
);
1133 #if !TARGET_OS_EMBEDDED && !TARGET_IPHONE_SIMULATOR
1135 // compare the older "Built-in XXX" localized name
1136 interface_name
= __SCNetworkInterfaceCopyXLocalizedDisplayName(interface
);
1139 // compare the older "Built-in XXX" non-localized name
1140 interface_name
= __SCNetworkInterfaceCopyXNonLocalizedDisplayName(interface
);
1142 #endif // !TARGET_OS_EMBEDDED && !TARGET_IPHONE_SIMULATOR
1147 if (interface_name
!= NULL
) {
1148 Boolean match
= FALSE
;
1150 if (CFEqual(name
, interface_name
)) {
1151 // if service name matches the OLD localized
1154 } else if (CFStringHasPrefix(name
, interface_name
)) {
1155 CFIndex prefixLen
= CFStringGetLength(interface_name
);
1156 CFIndex suffixLen
= CFStringGetLength(name
);
1158 suffix
= CFStringCreateWithSubstring(NULL
,
1160 CFRangeMake(prefixLen
, suffixLen
- prefixLen
));
1163 CFRelease(interface_name
);
1166 CFRelease(servicePrivate
->name
);
1167 servicePrivate
->name
= NULL
;
1174 // if the service name has not been set, use the localized interface name
1176 if (servicePrivate
->name
== NULL
) {
1177 interface_name
= SCNetworkInterfaceGetLocalizedDisplayName(interface
);
1178 if (interface_name
!= NULL
) {
1179 if (suffix
!= NULL
) {
1180 servicePrivate
->name
= CFStringCreateWithFormat(NULL
,
1186 servicePrivate
->name
= CFRetain(interface_name
);
1190 if (suffix
!= NULL
) CFRelease(suffix
);
1193 return servicePrivate
->name
;
1198 SCNetworkServiceGetServiceID(SCNetworkServiceRef service
)
1200 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1202 if (!isA_SCNetworkService(service
)) {
1203 _SCErrorSet(kSCStatusInvalidArgument
);
1207 return servicePrivate
->serviceID
;
1212 SCNetworkServiceGetTypeID(void)
1214 pthread_once(&initialized
, __SCNetworkServiceInitialize
); /* initialize runtime */
1215 return __kSCNetworkServiceTypeID
;
1220 SCNetworkServiceRemove(SCNetworkServiceRef service
)
1224 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1227 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1228 _SCErrorSet(kSCStatusInvalidArgument
);
1232 // remove service from all sets
1234 sets
= SCNetworkSetCopyAll(servicePrivate
->prefs
);
1239 n
= CFArrayGetCount(sets
);
1240 for (i
= 0; i
< n
; i
++) {
1241 SCNetworkSetRef set
;
1243 set
= CFArrayGetValueAtIndex(sets
, i
);
1244 ok
= SCNetworkSetRemoveService(set
, service
);
1245 if (!ok
&& (SCError() != kSCStatusNoKey
)) {
1255 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1256 servicePrivate
->serviceID
, // service
1258 ok
= SCPreferencesPathRemoveValue(servicePrivate
->prefs
, path
);
1266 SCNetworkServiceRemoveProtocolType(SCNetworkServiceRef service
, CFStringRef protocolType
)
1268 CFDictionaryRef entity
;
1271 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1273 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1274 _SCErrorSet(kSCStatusInvalidArgument
);
1278 if (!__SCNetworkProtocolIsValidType(protocolType
)) {
1279 _SCErrorSet(kSCStatusInvalidArgument
);
1283 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1284 servicePrivate
->serviceID
, // service
1285 protocolType
); // entity
1287 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1288 if (entity
== NULL
) {
1289 // if "protocol" does not exist
1290 _SCErrorSet(kSCStatusNoKey
);
1294 ok
= SCPreferencesPathRemoveValue(servicePrivate
->prefs
, path
);
1304 SCNetworkServiceSetEnabled(SCNetworkServiceRef service
, Boolean enabled
)
1308 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1310 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1311 _SCErrorSet(kSCStatusInvalidArgument
);
1315 // make sure that we do not enable a network service if the
1316 // associated interface is a member of a bond or bridge.
1318 SCNetworkInterfaceRef interface
;
1320 interface
= SCNetworkServiceGetInterface(service
);
1321 if ((interface
!= NULL
) &&
1322 __SCNetworkInterfaceIsMember(servicePrivate
->prefs
, interface
)) {
1323 _SCErrorSet(kSCStatusKeyExists
);
1328 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1329 servicePrivate
->serviceID
, // service
1331 ok
= __setPrefsEnabled(servicePrivate
->prefs
, path
, enabled
);
1339 SCNetworkServiceSetName(SCNetworkServiceRef service
, CFStringRef name
)
1341 CFDictionaryRef entity
;
1344 CFStringRef saveName
= NULL
;
1345 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1347 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1348 _SCErrorSet(kSCStatusInvalidArgument
);
1353 if (!isA_CFString(name
)) {
1354 _SCErrorSet(kSCStatusInvalidArgument
);
1357 saveName
= CFRetain(name
);
1361 SCNetworkInterfaceRef interface
;
1363 interface
= SCNetworkServiceGetInterface(service
);
1364 while (interface
!= NULL
) {
1365 SCNetworkInterfaceRef childInterface
;
1367 childInterface
= SCNetworkInterfaceGetInterface(interface
);
1368 if (childInterface
== NULL
) {
1372 interface
= childInterface
;
1375 if (interface
!= NULL
) {
1376 CFStringRef interface_name
;
1378 interface_name
= SCNetworkInterfaceGetLocalizedDisplayName(interface
);
1379 if (interface_name
!= NULL
) {
1380 if (CFEqual(name
, interface_name
)) {
1381 // if service name matches the localized interface name
1382 // then store the non-localized name.
1383 interface_name
= __SCNetworkInterfaceGetNonLocalizedDisplayName(interface
);
1384 if (interface_name
!= NULL
) {
1385 CFRelease(saveName
);
1386 saveName
= CFRetain(interface_name
);
1388 } else if (CFStringHasPrefix(name
, interface_name
)) {
1389 CFIndex prefixLen
= CFStringGetLength(interface_name
);
1391 CFIndex suffixLen
= CFStringGetLength(name
);
1393 // if service name matches the localized interface name plus
1394 // a few extra characters) then store the non-localized name with
1396 suffix
= CFStringCreateWithSubstring(NULL
,
1398 CFRangeMake(prefixLen
, suffixLen
- prefixLen
));
1399 interface_name
= __SCNetworkInterfaceGetNonLocalizedDisplayName(interface
);
1400 if (interface_name
!= NULL
) {
1401 CFRelease(saveName
);
1402 saveName
= CFStringCreateWithFormat(NULL
,
1414 #define PREVENT_DUPLICATE_SERVICE_NAMES
1415 #ifdef PREVENT_DUPLICATE_SERVICE_NAMES
1419 // ensure that each service is uniquely named within its sets
1421 sets
= SCNetworkSetCopyAll(servicePrivate
->prefs
);
1426 set_count
= CFArrayGetCount(sets
);
1427 for (set_index
= 0; set_index
< set_count
; set_index
++) {
1428 CFIndex service_index
;
1429 Boolean isDup
= FALSE
;
1430 Boolean isMember
= FALSE
;
1431 CFIndex service_count
;
1432 CFArrayRef services
;
1433 SCNetworkSetRef set
= CFArrayGetValueAtIndex(sets
, set_index
);
1435 services
= SCNetworkSetCopyServices(set
);
1437 service_count
= CFArrayGetCount(services
);
1438 for (service_index
= 0; service_index
< service_count
; service_index
++) {
1439 CFStringRef otherID
;
1440 CFStringRef otherName
;
1441 SCNetworkServiceRef otherService
;
1443 otherService
= CFArrayGetValueAtIndex(services
, service_index
);
1445 otherID
= SCNetworkServiceGetServiceID(otherService
);
1446 if (CFEqual(servicePrivate
->serviceID
, otherID
)) {
1447 // if the service is a member of this set
1452 otherName
= SCNetworkServiceGetName(otherService
);
1453 if ((otherName
!= NULL
) && CFEqual(name
, otherName
)) {
1459 CFRelease(services
);
1461 if (isMember
&& isDup
) {
1463 * if this service is a member of the set and
1464 * the "name" is not unique.
1467 if (saveName
!= NULL
) CFRelease(saveName
);
1468 _SCErrorSet(kSCStatusKeyExists
);
1476 #endif /* PREVENT_DUPLICATE_SERVICE_NAMES */
1478 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1479 servicePrivate
->serviceID
, // service
1481 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1482 if (isA_CFDictionary(entity
) ||
1483 ((entity
== NULL
) && (name
!= NULL
))) {
1484 CFMutableDictionaryRef newEntity
;
1486 if (entity
!= NULL
) {
1487 newEntity
= CFDictionaryCreateMutableCopy(NULL
, 0, entity
);
1489 newEntity
= CFDictionaryCreateMutable(NULL
,
1491 &kCFTypeDictionaryKeyCallBacks
,
1492 &kCFTypeDictionaryValueCallBacks
);
1494 if (saveName
!= NULL
) {
1495 CFDictionarySetValue(newEntity
, kSCPropUserDefinedName
, saveName
);
1497 CFDictionaryRemoveValue(newEntity
, kSCPropUserDefinedName
);
1499 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, newEntity
);
1500 CFRelease(newEntity
);
1503 if (saveName
!= NULL
) CFRelease(saveName
);
1505 if (servicePrivate
->name
!= NULL
) CFRelease(servicePrivate
->name
);
1506 if (name
!= NULL
) CFRetain(name
);
1507 servicePrivate
->name
= name
;
1514 #pragma mark SCNetworkService SPIs
1518 str_to_rank(CFStringRef rankStr
, SCNetworkServicePrimaryRank
*rank
)
1520 if (isA_CFString(rankStr
)) {
1521 if (CFEqual(rankStr
, kSCValNetServicePrimaryRankFirst
)) {
1522 *rank
= kSCNetworkServicePrimaryRankFirst
;
1523 } else if (CFEqual(rankStr
, kSCValNetServicePrimaryRankLast
)) {
1524 *rank
= kSCNetworkServicePrimaryRankLast
;
1525 } else if (CFEqual(rankStr
, kSCValNetServicePrimaryRankNever
)) {
1526 *rank
= kSCNetworkServicePrimaryRankNever
;
1530 } else if (rankStr
== NULL
) {
1531 *rank
= kSCNetworkServicePrimaryRankDefault
;
1540 SCNetworkServicePrimaryRank
1541 SCNetworkServiceGetPrimaryRank(SCNetworkServiceRef service
)
1543 CFDictionaryRef entity
;
1546 SCNetworkServicePrimaryRank rank
= kSCNetworkServicePrimaryRankDefault
;
1547 CFStringRef rankStr
= NULL
;
1548 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1550 if (!isA_SCNetworkService(service
)) {
1551 _SCErrorSet(kSCStatusInvalidArgument
);
1555 if (servicePrivate
->prefs
!= NULL
) {
1556 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
,
1557 servicePrivate
->serviceID
,
1559 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1561 if (isA_CFDictionary(entity
)) {
1562 rankStr
= CFDictionaryGetValue(entity
, kSCPropNetServicePrimaryRank
);
1563 ok
= str_to_rank(rankStr
, &rank
);
1565 } else if (servicePrivate
->store
!= NULL
) {
1566 path
= SCDynamicStoreKeyCreateNetworkServiceEntity(NULL
,
1567 kSCDynamicStoreDomainState
,
1568 servicePrivate
->serviceID
,
1570 entity
= SCDynamicStoreCopyValue(servicePrivate
->store
, path
);
1572 if (entity
!= NULL
) {
1573 if (isA_CFDictionary(entity
)) {
1574 rankStr
= CFDictionaryGetValue(entity
, kSCPropNetServicePrimaryRank
);
1575 ok
= str_to_rank(rankStr
, &rank
);
1580 _SCErrorSet(kSCStatusInvalidArgument
);
1585 rank
= kSCNetworkServicePrimaryRankDefault
;
1586 _SCErrorSet(kSCStatusInvalidArgument
);
1587 } else if (rank
== kSCNetworkServicePrimaryRankDefault
) {
1588 _SCErrorSet(kSCStatusOK
);
1596 rank_to_str(SCNetworkServicePrimaryRank rank
, CFStringRef
*rankStr
)
1599 case kSCNetworkServicePrimaryRankDefault
:
1602 case kSCNetworkServicePrimaryRankFirst
:
1603 *rankStr
= kSCValNetServicePrimaryRankFirst
;
1605 case kSCNetworkServicePrimaryRankLast
:
1606 *rankStr
= kSCValNetServicePrimaryRankLast
;
1608 case kSCNetworkServicePrimaryRankNever
:
1609 *rankStr
= kSCValNetServicePrimaryRankNever
;
1620 SCNetworkServiceSetPrimaryRank(SCNetworkServiceRef service
,
1621 SCNetworkServicePrimaryRank newRank
)
1624 CFDictionaryRef entity
;
1625 CFMutableDictionaryRef newEntity
;
1626 CFStringRef path
= NULL
;
1627 CFStringRef rankStr
= NULL
;
1628 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1630 if (!isA_SCNetworkService(service
)) {
1631 _SCErrorSet(kSCStatusInvalidArgument
);
1635 ok
= rank_to_str(newRank
, &rankStr
);
1637 _SCErrorSet(kSCStatusInvalidArgument
);
1641 if (servicePrivate
->prefs
!= NULL
) {
1642 if ((newRank
== kSCNetworkServicePrimaryRankDefault
) || (newRank
== kSCNetworkServicePrimaryRankNever
)) {
1643 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
,
1644 servicePrivate
->serviceID
,
1646 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1647 if (entity
!= NULL
) {
1648 if (!isA_CFDictionary(entity
)) {
1650 _SCErrorSet(kSCStatusFailed
);
1653 newEntity
= CFDictionaryCreateMutableCopy(NULL
, 0, entity
);
1655 newEntity
= CFDictionaryCreateMutable(NULL
,
1657 &kCFTypeDictionaryKeyCallBacks
,
1658 &kCFTypeDictionaryValueCallBacks
);
1660 if (rankStr
!= NULL
) {
1661 CFDictionarySetValue(newEntity
, kSCPropNetServicePrimaryRank
, rankStr
);
1663 CFDictionaryRemoveValue(newEntity
, kSCPropNetServicePrimaryRank
);
1665 if (CFDictionaryGetCount(newEntity
) > 0) {
1666 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, newEntity
);
1668 ok
= SCPreferencesPathRemoveValue(servicePrivate
->prefs
, path
);
1670 CFRelease(newEntity
);
1675 _SCErrorSet(kSCStatusInvalidArgument
);
1678 } else if (servicePrivate
->store
!= NULL
) {
1679 path
= SCDynamicStoreKeyCreateNetworkServiceEntity(NULL
,
1680 kSCDynamicStoreDomainState
,
1681 servicePrivate
->serviceID
,
1683 entity
= SCDynamicStoreCopyValue(servicePrivate
->store
, path
);
1684 if (entity
!= NULL
) {
1685 if (!isA_CFDictionary(entity
)) {
1688 _SCErrorSet(kSCStatusFailed
);
1691 newEntity
= CFDictionaryCreateMutableCopy(NULL
, 0, entity
);
1694 newEntity
= CFDictionaryCreateMutable(NULL
,
1696 &kCFTypeDictionaryKeyCallBacks
,
1697 &kCFTypeDictionaryValueCallBacks
);
1699 if (rankStr
!= NULL
) {
1700 CFDictionarySetValue(newEntity
, kSCPropNetServicePrimaryRank
, rankStr
);
1702 CFDictionaryRemoveValue(newEntity
, kSCPropNetServicePrimaryRank
);
1704 if (CFDictionaryGetCount(newEntity
) > 0) {
1705 ok
= SCDynamicStoreSetValue(servicePrivate
->store
, path
, newEntity
);
1707 ok
= SCDynamicStoreRemoveValue(servicePrivate
->store
, path
);
1709 CFRelease(newEntity
);
1714 _SCErrorSet(kSCStatusInvalidArgument
);
1720 if (path
!= NULL
) CFRelease(path
);
1726 _SCNetworkServiceIsVPN(SCNetworkServiceRef service
)
1728 SCNetworkInterfaceRef interface
;
1729 CFStringRef interfaceType
;
1731 interface
= SCNetworkServiceGetInterface(service
);
1732 if (interface
== NULL
) {
1736 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
1737 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
)) {
1738 interface
= SCNetworkInterfaceGetInterface(interface
);
1739 if (interface
== NULL
) {
1743 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
1744 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeL2TP
)) {
1747 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPTP
)) {
1750 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeVPN
)) {
1752 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeIPSec
)) {