2 * Copyright (c) 2004-2015 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>
38 #include "SCPreferencesInternal.h"
42 #define EXTERNAL_ID_DOMAIN_PREFIX "_"
44 static CFStringRef
__SCNetworkServiceCopyDescription (CFTypeRef cf
);
45 static void __SCNetworkServiceDeallocate (CFTypeRef cf
);
46 static Boolean
__SCNetworkServiceEqual (CFTypeRef cf1
, CFTypeRef cf2
);
47 static CFHashCode
__SCNetworkServiceHash (CFTypeRef cf
);
50 static CFTypeID __kSCNetworkServiceTypeID
= _kCFRuntimeNotATypeID
;
53 static const CFRuntimeClass __SCNetworkServiceClass
= {
55 "SCNetworkService", // className
58 __SCNetworkServiceDeallocate
, // dealloc
59 __SCNetworkServiceEqual
, // equal
60 __SCNetworkServiceHash
, // hash
61 NULL
, // copyFormattingDesc
62 __SCNetworkServiceCopyDescription
// copyDebugDesc
66 static pthread_once_t initialized
= PTHREAD_ONCE_INIT
;
70 __SCNetworkServiceCopyDescription(CFTypeRef cf
)
72 CFAllocatorRef allocator
= CFGetAllocator(cf
);
73 CFMutableStringRef result
;
74 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)cf
;
76 result
= CFStringCreateMutable(allocator
, 0);
77 CFStringAppendFormat(result
, NULL
, CFSTR("<SCNetworkService %p [%p]> {"), cf
, allocator
);
78 CFStringAppendFormat(result
, NULL
, CFSTR("id = %@"), servicePrivate
->serviceID
);
79 if (servicePrivate
->prefs
!= NULL
) {
80 CFStringAppendFormat(result
, NULL
, CFSTR(", prefs = %p"), servicePrivate
->prefs
);
81 } else if (servicePrivate
->store
!= NULL
) {
82 CFStringAppendFormat(result
, NULL
, CFSTR(", store = %p"), servicePrivate
->store
);
84 if (servicePrivate
->name
!= NULL
) {
85 CFStringAppendFormat(result
, NULL
, CFSTR(", name = %@"), servicePrivate
->name
);
87 CFStringAppendFormat(result
, NULL
, CFSTR("}"));
94 __SCNetworkServiceDeallocate(CFTypeRef cf
)
96 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)cf
;
98 /* release resources */
100 CFRelease(servicePrivate
->serviceID
);
101 if (servicePrivate
->interface
!= NULL
) CFRelease(servicePrivate
->interface
);
102 if (servicePrivate
->prefs
!= NULL
) CFRelease(servicePrivate
->prefs
);
103 if (servicePrivate
->store
!= NULL
) CFRelease(servicePrivate
->store
);
104 if (servicePrivate
->name
!= NULL
) CFRelease(servicePrivate
->name
);
105 if (servicePrivate
->externalIDs
!= NULL
) CFRelease(servicePrivate
->externalIDs
);
112 __SCNetworkServiceEqual(CFTypeRef cf1
, CFTypeRef cf2
)
114 SCNetworkServicePrivateRef s1
= (SCNetworkServicePrivateRef
)cf1
;
115 SCNetworkServicePrivateRef s2
= (SCNetworkServicePrivateRef
)cf2
;
120 if (s1
->prefs
!= s2
->prefs
)
121 return FALSE
; // if not the same prefs
123 if (!CFEqual(s1
->serviceID
, s2
->serviceID
))
124 return FALSE
; // if not the same service identifier
131 __SCNetworkServiceHash(CFTypeRef cf
)
133 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)cf
;
135 return CFHash(servicePrivate
->serviceID
);
140 __SCNetworkServiceInitialize(void)
142 __kSCNetworkServiceTypeID
= _CFRuntimeRegisterClass(&__SCNetworkServiceClass
);
147 __private_extern__ SCNetworkServicePrivateRef
148 __SCNetworkServiceCreatePrivate(CFAllocatorRef allocator
,
149 SCPreferencesRef prefs
,
150 CFStringRef serviceID
,
151 SCNetworkInterfaceRef interface
)
153 SCNetworkServicePrivateRef servicePrivate
;
156 /* initialize runtime */
157 pthread_once(&initialized
, __SCNetworkServiceInitialize
);
159 /* allocate target */
160 size
= sizeof(SCNetworkServicePrivate
) - sizeof(CFRuntimeBase
);
161 servicePrivate
= (SCNetworkServicePrivateRef
)_CFRuntimeCreateInstance(allocator
,
162 __kSCNetworkServiceTypeID
,
165 if (servicePrivate
== NULL
) {
169 servicePrivate
->prefs
= (prefs
!= NULL
) ? CFRetain(prefs
): NULL
;
170 servicePrivate
->serviceID
= CFStringCreateCopy(NULL
, serviceID
);
171 servicePrivate
->interface
= (interface
!= NULL
) ? CFRetain(interface
) : NULL
;
172 servicePrivate
->name
= NULL
;
174 return servicePrivate
;
179 #pragma mark Service ordering
183 _SCNetworkServiceCompare(const void *val1
, const void *val2
, void *context
)
187 CFArrayRef order
= (CFArrayRef
)context
;
188 SCNetworkServiceRef s1
= (SCNetworkServiceRef
)val1
;
189 SCNetworkServiceRef s2
= (SCNetworkServiceRef
)val2
;
191 id1
= SCNetworkServiceGetServiceID(s1
);
192 id2
= SCNetworkServiceGetServiceID(s2
);
199 range
= CFRangeMake(0, CFArrayGetCount(order
));
200 o1
= CFArrayGetFirstIndexOfValue(order
, range
, id1
);
201 o2
= CFArrayGetFirstIndexOfValue(order
, range
, id2
);
204 return (o2
!= kCFNotFound
) ? kCFCompareGreaterThan
: kCFCompareLessThan
;
205 } else if (o1
< o2
) {
206 return (o1
!= kCFNotFound
) ? kCFCompareLessThan
: kCFCompareGreaterThan
;
210 return CFStringCompare(id1
, id2
, 0);
215 #pragma mark SCNetworkService APIs
221 __private_extern__ CFArrayRef
/* of SCNetworkServiceRef's */
222 __SCNetworkServiceCopyAllEnabled(SCPreferencesRef prefs
)
224 CFMutableArrayRef array
= NULL
;
229 sets
= SCNetworkSetCopyAll(prefs
);
234 n_sets
= CFArrayGetCount(sets
);
235 for (i_sets
= 0; i_sets
< n_sets
; i_sets
++) {
241 set
= CFArrayGetValueAtIndex(sets
, i_sets
);
242 services
= SCNetworkSetCopyServices(set
);
243 if (services
== NULL
) {
247 n_services
= CFArrayGetCount(services
);
248 for (i_services
= 0; i_services
< n_services
; i_services
++) {
249 SCNetworkServiceRef service
;
251 service
= CFArrayGetValueAtIndex(services
, i_services
);
252 if (!SCNetworkServiceGetEnabled(service
)) {
257 if ((array
== NULL
) ||
258 !CFArrayContainsValue(array
,
259 CFRangeMake(0, CFArrayGetCount(array
)),
262 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
264 CFArrayAppendValue(array
, service
);
275 __private_extern__ Boolean
276 __SCNetworkServiceExistsForInterface(CFArrayRef services
, SCNetworkInterfaceRef interface
)
281 n
= isA_CFArray(services
) ? CFArrayGetCount(services
) : 0;
282 for (i
= 0; i
< n
; i
++) {
283 SCNetworkServiceRef service
;
284 SCNetworkInterfaceRef service_interface
;
286 service
= CFArrayGetValueAtIndex(services
, i
);
288 service_interface
= SCNetworkServiceGetInterface(service
);
289 while (service_interface
!= NULL
) {
290 if (CFEqual(interface
, service_interface
)) {
294 service_interface
= SCNetworkInterfaceGetInterface(service_interface
);
303 mergeDict(const void *key
, const void *value
, void *context
)
305 CFMutableDictionaryRef newDict
= (CFMutableDictionaryRef
)context
;
307 CFDictionarySetValue(newDict
, key
, value
);
312 static CF_RETURNS_RETAINED CFDictionaryRef
313 _protocolTemplate(SCNetworkServiceRef service
, CFStringRef protocolType
)
315 SCNetworkInterfaceRef interface
;
316 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
317 CFDictionaryRef
template = NULL
;
319 interface
= servicePrivate
->interface
;
320 if (interface
!= NULL
) {
321 SCNetworkInterfaceRef childInterface
;
322 CFStringRef childInterfaceType
= NULL
;
323 CFStringRef interfaceType
;
326 interfaceType
= SCNetworkInterfaceGetInterfaceType(servicePrivate
->interface
);
327 childInterface
= SCNetworkInterfaceGetInterface(servicePrivate
->interface
);
328 if (childInterface
!= NULL
) {
329 childInterfaceType
= SCNetworkInterfaceGetInterfaceType(childInterface
);
332 template = __copyProtocolTemplate(interfaceType
, childInterfaceType
, protocolType
);
333 if (template != NULL
) {
334 CFDictionaryRef overrides
;
336 // move to the interface at the lowest layer
337 while (childInterface
!= NULL
) {
338 interface
= childInterface
;
339 childInterface
= SCNetworkInterfaceGetInterface(interface
);
342 overrides
= __SCNetworkInterfaceGetTemplateOverrides(interface
, protocolType
);
343 if (overrides
!= NULL
) {
344 CFMutableDictionaryRef newTemplate
;
346 newTemplate
= CFDictionaryCreateMutableCopy(NULL
, 0, template);
347 CFDictionaryApplyFunction(overrides
, mergeDict
, newTemplate
);
349 template = newTemplate
;
354 if (template == NULL
) {
355 template = CFDictionaryCreate(NULL
,
359 &kCFTypeDictionaryKeyCallBacks
,
360 &kCFTypeDictionaryValueCallBacks
);
368 SCNetworkServiceAddProtocolType(SCNetworkServiceRef service
, CFStringRef protocolType
)
370 CFDictionaryRef entity
;
371 CFDictionaryRef newEntity
= NULL
;
374 SCNetworkProtocolRef protocol
;
375 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
377 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
378 _SCErrorSet(kSCStatusInvalidArgument
);
382 if (!__SCNetworkProtocolIsValidType(protocolType
)) {
383 _SCErrorSet(kSCStatusInvalidArgument
);
387 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
388 servicePrivate
->serviceID
, // service
389 protocolType
); // entity
391 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
392 if (entity
!= NULL
) {
393 // if "protocol" already exists
394 _SCErrorSet(kSCStatusKeyExists
);
398 newEntity
= CFDictionaryCreate(NULL
,
402 &kCFTypeDictionaryKeyCallBacks
,
403 &kCFTypeDictionaryValueCallBacks
);
404 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, newEntity
);
405 CFRelease(newEntity
);
410 protocol
= SCNetworkServiceCopyProtocol(service
, protocolType
);
411 assert(protocol
!= NULL
);
413 newEntity
= _protocolTemplate(service
, protocolType
);
414 ok
= SCNetworkProtocolSetConfiguration(protocol
, newEntity
);
415 CFRelease(newEntity
);
425 CFArrayRef
/* of SCNetworkServiceRef's */
426 SCNetworkServiceCopyAll(SCPreferencesRef prefs
)
428 CFMutableArrayRef array
;
431 CFDictionaryRef services
;
433 path
= SCPreferencesPathKeyCreateNetworkServices(NULL
);
434 services
= SCPreferencesPathGetValue(prefs
, path
);
437 if ((services
!= NULL
) && !isA_CFDictionary(services
)) {
441 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
443 n
= (services
!= NULL
) ? CFDictionaryGetCount(services
) : 0;
446 const void * keys_q
[N_QUICK
];
447 const void ** keys
= keys_q
;
448 const void * vals_q
[N_QUICK
];
449 const void ** vals
= vals_q
;
451 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
452 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
453 vals
= CFAllocatorAllocate(NULL
, n
* sizeof(CFPropertyListRef
), 0);
455 CFDictionaryGetKeysAndValues(services
, keys
, vals
);
456 for (i
= 0; i
< n
; i
++) {
457 CFDictionaryRef entity
;
458 SCNetworkServicePrivateRef servicePrivate
;
460 if (!isA_CFDictionary(vals
[i
])) {
461 SC_log(LOG_INFO
, "error w/service \"%@\"", keys
[i
]);
465 entity
= CFDictionaryGetValue(vals
[i
], kSCEntNetInterface
);
466 if (!isA_CFDictionary(entity
)) {
468 SC_log(LOG_INFO
, "no \"%@\" entity for service \"%@\"",
474 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, prefs
, keys
[i
], NULL
);
475 assert(servicePrivate
!= NULL
);
476 CFArrayAppendValue(array
, (SCNetworkServiceRef
)servicePrivate
);
477 CFRelease(servicePrivate
);
479 if (keys
!= keys_q
) {
480 CFAllocatorDeallocate(NULL
, keys
);
481 CFAllocatorDeallocate(NULL
, vals
);
490 CFArrayRef
/* of SCNetworkInterfaceRef's */
491 __SCNetworkServiceCopyAllInterfaces(SCPreferencesRef prefs
)
493 CFMutableArrayRef interfaces
= NULL
;
494 CFArrayRef services
= NULL
;
495 CFIndex servicesCount
= 0;
496 SCNetworkServiceRef service
= NULL
;
497 SCNetworkInterfaceRef interface
= NULL
;
499 services
= SCNetworkServiceCopyAll(prefs
);
500 if (services
== NULL
) {
504 servicesCount
= CFArrayGetCount(services
);
505 if (servicesCount
== 0) {
509 interfaces
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
511 for (CFIndex idx
= 0; idx
< servicesCount
; idx
++) {
512 service
= CFArrayGetValueAtIndex(services
, idx
);
513 interface
= SCNetworkServiceGetInterface(service
);
515 if (isA_SCNetworkInterface(interface
) == NULL
) {
518 CFArrayAppendValue(interfaces
, interface
);
521 if (CFArrayGetCount(interfaces
) == 0) {
522 // Do not return an empty array
523 CFRelease(interfaces
);
529 if (services
!= NULL
) {
537 * build a list of all of a services entity types that are associated
538 * with the services interface. The list will include :
540 * - entity types associated with the interface type (Ethernet, FireWire, PPP, ...)
541 * - entity types associated with the interface sub-type (PPPSerial, PPPoE, L2TP, PPTP, ...)
542 * - entity types associated with the hardware device (Ethernet, AirPort, FireWire, Modem, ...)
545 _copyInterfaceEntityTypes(CFDictionaryRef protocols
)
547 CFDictionaryRef interface
;
548 CFMutableSetRef interface_entity_types
;
550 interface_entity_types
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
552 interface
= CFDictionaryGetValue(protocols
, kSCEntNetInterface
);
553 if (isA_CFDictionary(interface
)) {
554 CFStringRef entities
[] = { kSCPropNetInterfaceType
,
555 kSCPropNetInterfaceSubType
,
556 kSCPropNetInterfaceHardware
};
559 // include the "Interface" entity itself
560 CFSetAddValue(interface_entity_types
, kSCEntNetInterface
);
562 // include the entities associated with the interface
563 for (i
= 0; i
< sizeof(entities
)/sizeof(entities
[0]); i
++) {
566 entity
= CFDictionaryGetValue(interface
, entities
[i
]);
567 if (isA_CFString(entity
)) {
568 CFSetAddValue(interface_entity_types
, entity
);
573 * and, because we've found some misguided network preference code
574 * developers leaving [PPP] entity dictionaries around even though
575 * they are unused and/or unneeded...
577 CFSetAddValue(interface_entity_types
, kSCEntNetPPP
);
580 return interface_entity_types
;
585 SCNetworkServiceCopy(SCPreferencesRef prefs
, CFStringRef serviceID
)
587 CFDictionaryRef entity
;
589 SCNetworkServicePrivateRef servicePrivate
;
591 if (!isA_CFString(serviceID
)) {
592 _SCErrorSet(kSCStatusInvalidArgument
);
596 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
597 serviceID
, // service
598 kSCEntNetInterface
); // entity
599 entity
= SCPreferencesPathGetValue(prefs
, path
);
602 if (!isA_CFDictionary(entity
)) {
603 // a "service" must have an "interface"
604 _SCErrorSet(kSCStatusNoKey
);
608 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, prefs
, serviceID
, NULL
);
609 return (SCNetworkServiceRef
)servicePrivate
;
614 _SCNetworkServiceCopyActive(SCDynamicStoreRef store
, CFStringRef serviceID
)
616 SCNetworkServicePrivateRef servicePrivate
;
618 if (!isA_CFString(serviceID
)) {
619 _SCErrorSet(kSCStatusInvalidArgument
);
623 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, NULL
, serviceID
, NULL
);
624 assert(servicePrivate
!= NULL
);
626 servicePrivate
->store
= CFRetain(store
);
628 return (SCNetworkServiceRef
)servicePrivate
;
633 SCNetworkServiceCopyProtocol(SCNetworkServiceRef service
, CFStringRef protocolType
)
635 CFSetRef non_protocol_entities
;
637 CFDictionaryRef protocols
;
638 SCNetworkProtocolPrivateRef protocolPrivate
= NULL
;
639 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
641 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
642 _SCErrorSet(kSCStatusInvalidArgument
);
646 if (!isA_CFString(protocolType
)) {
647 _SCErrorSet(kSCStatusInvalidArgument
);
651 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
652 servicePrivate
->serviceID
, // service
654 protocols
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
657 if (!isA_CFDictionary(protocols
)) {
659 _SCErrorSet(kSCStatusFailed
);
663 non_protocol_entities
= _copyInterfaceEntityTypes(protocols
);
664 if (CFSetContainsValue(non_protocol_entities
, protocolType
)) {
665 // if the "protocolType" matches an interface entity type
666 _SCErrorSet(kSCStatusInvalidArgument
);
670 if (!CFDictionaryContainsKey(protocols
, protocolType
)) {
671 // if the "protocolType" entity does not exist
672 _SCErrorSet(kSCStatusNoKey
);
676 protocolPrivate
= __SCNetworkProtocolCreatePrivate(NULL
, protocolType
, service
);
680 CFRelease(non_protocol_entities
);
682 return (SCNetworkProtocolRef
)protocolPrivate
;
686 CFArrayRef
/* of SCNetworkProtocolRef's */
687 SCNetworkServiceCopyProtocols(SCNetworkServiceRef service
)
689 CFMutableArrayRef array
;
691 CFSetRef non_protocol_entities
;
693 CFDictionaryRef protocols
;
694 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
696 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
697 _SCErrorSet(kSCStatusInvalidArgument
);
701 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
702 servicePrivate
->serviceID
, // service
704 protocols
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
707 if (!isA_CFDictionary(protocols
)) {
709 _SCErrorSet(kSCStatusFailed
);
713 non_protocol_entities
= _copyInterfaceEntityTypes(protocols
);
715 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
717 n
= CFDictionaryGetCount(protocols
);
720 const void * keys_q
[N_QUICK
];
721 const void ** keys
= keys_q
;
722 const void * vals_q
[N_QUICK
];
723 const void ** vals
= vals_q
;
725 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
726 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
727 vals
= CFAllocatorAllocate(NULL
, n
* sizeof(CFPropertyListRef
), 0);
729 CFDictionaryGetKeysAndValues(protocols
, keys
, vals
);
730 for (i
= 0; i
< n
; i
++) {
731 SCNetworkProtocolPrivateRef protocolPrivate
;
733 if (!isA_CFDictionary(vals
[i
])) {
734 // if it's not a dictionary then it can't be a protocol entity
738 if (CFSetContainsValue(non_protocol_entities
, keys
[i
])) {
739 // skip any non-protocol (interface) entities
743 protocolPrivate
= __SCNetworkProtocolCreatePrivate(NULL
, keys
[i
], service
);
744 CFArrayAppendValue(array
, (SCNetworkProtocolRef
)protocolPrivate
);
746 CFRelease(protocolPrivate
);
748 if (keys
!= keys_q
) {
749 CFAllocatorDeallocate(NULL
, keys
);
750 CFAllocatorDeallocate(NULL
, vals
);
754 CFRelease(non_protocol_entities
);
761 __SCNetworkServiceSetInterfaceEntity(SCNetworkServiceRef service
,
762 SCNetworkInterfaceRef interface
)
764 CFDictionaryRef entity
;
767 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
769 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
770 servicePrivate
->serviceID
, // service
771 kSCEntNetInterface
); // entity
772 entity
= __SCNetworkInterfaceCopyInterfaceEntity(interface
);
773 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, entity
);
782 SCNetworkServiceCreate(SCPreferencesRef prefs
, SCNetworkInterfaceRef interface
)
784 CFArrayRef components
;
785 CFArrayRef interface_config
;
786 CFStringRef interface_name
;
787 SCNetworkInterfaceRef newInterface
;
790 CFStringRef serviceID
;
791 SCNetworkServicePrivateRef servicePrivate
;
792 CFArrayRef supported_protocols
;
794 if (!isA_SCNetworkInterface(interface
)) {
795 _SCErrorSet(kSCStatusInvalidArgument
);
799 // only allow network interfaces which support one or more protocols
800 // to be added to a service. The one exception is that we allow
801 // third-party interface types to be configured.
802 supported_protocols
= SCNetworkInterfaceGetSupportedProtocolTypes(interface
);
803 if (supported_protocols
== NULL
) {
804 CFStringRef interface_type
;
806 interface_type
= SCNetworkInterfaceGetInterfaceType(interface
);
807 if (CFStringFind(interface_type
, CFSTR("."), 0).location
== kCFNotFound
) {
808 _SCErrorSet(kSCStatusInvalidArgument
);
813 // do not allow creation of a network service if the interface is a
814 // member of a bond or bridge
815 if (__SCNetworkInterfaceIsMember(prefs
, interface
)) {
816 _SCErrorSet(kSCStatusKeyExists
);
820 // establish the service
821 prefix
= SCPreferencesPathKeyCreateNetworkServices(NULL
);
822 path
= __SCPreferencesPathCreateUniqueChild_WithMoreSCFCompatibility(prefs
, prefix
);
823 if (path
== NULL
) path
= SCPreferencesPathCreateUniqueChild(prefs
, prefix
);
829 components
= CFStringCreateArrayBySeparatingStrings(NULL
, path
, CFSTR("/"));
832 serviceID
= CFArrayGetValueAtIndex(components
, 2);
833 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, prefs
, serviceID
, NULL
);
834 CFRelease(components
);
836 // duplicate the interface and associate the copy with the new service
837 newInterface
= (SCNetworkInterfaceRef
)__SCNetworkInterfaceCreateCopy(NULL
,
841 servicePrivate
->interface
= newInterface
;
843 // establish "default" configuration(s) for the interface
844 for (interface
= newInterface
;
846 interface
= SCNetworkInterfaceGetInterface(interface
)) {
847 SCNetworkInterfaceRef childInterface
;
848 CFStringRef childInterfaceType
= NULL
;
849 CFDictionaryRef config
;
850 CFStringRef interfaceType
;
852 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
853 childInterface
= SCNetworkInterfaceGetInterface(interface
);
854 if (childInterface
!= NULL
) {
855 childInterfaceType
= SCNetworkInterfaceGetInterfaceType(childInterface
);
858 config
= __copyInterfaceTemplate(interfaceType
, childInterfaceType
);
859 if (config
!= NULL
) {
860 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeBluetooth
) ||
861 CFEqual(interfaceType
, kSCNetworkInterfaceTypeIrDA
) ||
862 CFEqual(interfaceType
, kSCNetworkInterfaceTypeModem
) ||
863 CFEqual(interfaceType
, kSCNetworkInterfaceTypeSerial
) ||
864 CFEqual(interfaceType
, kSCNetworkInterfaceTypeWWAN
)) {
865 CFDictionaryRef overrides
;
867 overrides
= __SCNetworkInterfaceGetTemplateOverrides(interface
, kSCNetworkInterfaceTypeModem
);
869 // a ConnectionScript (and related keys) from the interface
870 // should trump the settings from the configuration template.
871 if (overrides
!= NULL
) {
872 CFMutableDictionaryRef newConfig
;
874 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
875 if (CFDictionaryContainsKey(overrides
, kSCPropNetModemConnectionScript
)) {
876 CFDictionaryRemoveValue(newConfig
, kSCPropNetModemConnectionPersonality
);
877 CFDictionaryRemoveValue(newConfig
, kSCPropNetModemConnectionScript
);
878 CFDictionaryRemoveValue(newConfig
, kSCPropNetModemDeviceVendor
);
879 CFDictionaryRemoveValue(newConfig
, kSCPropNetModemDeviceModel
);
881 CFDictionaryApplyFunction(overrides
, mergeDict
, newConfig
);
885 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
) ||
886 CFEqual(interfaceType
, kSCNetworkInterfaceTypeVPN
)) {
887 CFDictionaryRef overrides
;
889 overrides
= __SCNetworkInterfaceGetTemplateOverrides(interface
, kSCNetworkInterfaceTypePPP
);
890 if (overrides
!= NULL
) {
891 CFMutableDictionaryRef newConfig
;
893 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
894 CFDictionaryApplyFunction(overrides
, mergeDict
, newConfig
);
900 if (!__SCNetworkInterfaceSetConfiguration(interface
, NULL
, config
, TRUE
)) {
901 SC_log(LOG_INFO
, "__SCNetworkInterfaceSetConfiguration failed(), interface=%@, type=NULL",
908 // add the interface [entity] to the service
909 (void) __SCNetworkServiceSetInterfaceEntity((SCNetworkServiceRef
)servicePrivate
,
910 servicePrivate
->interface
);
912 // push the [deep] interface configuration into the service.
913 interface_config
= __SCNetworkInterfaceCopyDeepConfiguration(NULL
, servicePrivate
->interface
);
914 __SCNetworkInterfaceSetDeepConfiguration(NULL
, servicePrivate
->interface
, interface_config
);
915 if (interface_config
!= NULL
) CFRelease(interface_config
);
917 // set the service name to match that of the associated interface
919 // Note: It might seem a bit odd to call SCNetworkServiceGetName
920 // followed by an immediate call to SCNetworkServiceSetName. The
921 // trick here is that if no name has previously been set, the
922 // "get" function will return the name of the associated interface.
924 // ... and we "set" a name to ensure that applications that do
925 // not use the APIs will still find a UserDefinedName property
926 // in the SCDynamicStore.
928 interface_name
= SCNetworkServiceGetName((SCNetworkServiceRef
)servicePrivate
);
929 if (interface_name
!= NULL
) {
930 (void) SCNetworkServiceSetName((SCNetworkServiceRef
)servicePrivate
,
934 return (SCNetworkServiceRef
)servicePrivate
;
939 SCNetworkServiceEstablishDefaultConfiguration(SCNetworkServiceRef service
)
942 SCNetworkInterfaceRef interface
;
944 CFArrayRef protocolTypes
;
945 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
947 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
948 _SCErrorSet(kSCStatusInvalidArgument
);
952 interface
= SCNetworkServiceGetInterface(service
);
953 if (interface
== NULL
) {
957 protocolTypes
= SCNetworkInterfaceGetSupportedProtocolTypes(interface
);
958 n
= (protocolTypes
!= NULL
) ? CFArrayGetCount(protocolTypes
) : 0;
959 for (i
= 0; i
< n
; i
++) {
961 CFDictionaryRef newEntity
= NULL
;
963 SCNetworkProtocolRef protocol
= NULL
;
964 CFStringRef protocolType
;
966 protocolType
= CFArrayGetValueAtIndex(protocolTypes
, i
);
967 ok
= SCNetworkServiceAddProtocolType(service
, protocolType
);
968 if (!ok
&& (SCError() != kSCStatusKeyExists
)) {
969 // could not add protocol
973 protocol
= SCNetworkServiceCopyProtocol(service
, protocolType
);
974 if (protocol
== NULL
) {
975 // oops, somethings wrong (should never happen)
979 newEntity
= _protocolTemplate(service
, protocolType
);
980 ok
= SCNetworkProtocolSetConfiguration(protocol
, newEntity
);
982 // could not set default configuration
986 enabled
= !CFDictionaryContainsKey(newEntity
, kSCResvInactive
);
987 ok
= SCNetworkProtocolSetEnabled(protocol
, enabled
);
989 // could not enable/disable protocol
995 if (newEntity
!= NULL
) CFRelease(newEntity
);
996 if (protocol
!= NULL
) CFRelease(protocol
);
1004 SCNetworkServiceGetEnabled(SCNetworkServiceRef service
)
1008 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1010 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1011 _SCErrorSet(kSCStatusInvalidArgument
);
1015 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1016 servicePrivate
->serviceID
, // service
1018 enabled
= __getPrefsEnabled(servicePrivate
->prefs
, path
);
1025 SCNetworkInterfaceRef
1026 SCNetworkServiceGetInterface(SCNetworkServiceRef service
)
1028 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1030 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1031 _SCErrorSet(kSCStatusInvalidArgument
);
1035 if (servicePrivate
->interface
== NULL
) {
1036 CFDictionaryRef entity
;
1039 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1040 servicePrivate
->serviceID
, // service
1041 kSCEntNetInterface
); // entity
1042 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1045 if (isA_CFDictionary(entity
)) {
1046 servicePrivate
->interface
= _SCNetworkInterfaceCreateWithEntity(NULL
, entity
, service
);
1050 return servicePrivate
->interface
;
1055 SCNetworkServiceGetName(SCNetworkServiceRef service
)
1057 CFDictionaryRef entity
;
1058 SCNetworkInterfaceRef interface
;
1059 CFStringRef name
= NULL
;
1061 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1062 Boolean useSystemInterfaces
= TRUE
;
1064 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1065 _SCErrorSet(kSCStatusInvalidArgument
);
1069 if (servicePrivate
->name
!= NULL
) {
1070 return servicePrivate
->name
;
1073 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1074 servicePrivate
->serviceID
, // service
1076 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1079 useSystemInterfaces
= ((__SCPreferencesUsingDefaultPrefs(servicePrivate
->prefs
)) &&
1080 (__SCPreferencesGetLimitSCNetworkConfiguration(servicePrivate
->prefs
) == FALSE
));
1082 if (isA_CFDictionary(entity
)) {
1083 name
= CFDictionaryGetValue(entity
, kSCPropUserDefinedName
);
1084 if (isA_CFString(name
)) {
1085 servicePrivate
->name
= CFRetain(name
);
1086 if (useSystemInterfaces
== FALSE
) {
1087 return servicePrivate
->name
;
1092 interface
= SCNetworkServiceGetInterface(service
);
1093 while (interface
!= NULL
) {
1094 SCNetworkInterfaceRef childInterface
;
1095 CFStringRef interfaceType
;
1097 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
1098 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeVPN
)) {
1102 childInterface
= SCNetworkInterfaceGetInterface(interface
);
1103 if ((childInterface
== NULL
) ||
1104 CFEqual(childInterface
, kSCNetworkInterfaceIPv4
)) {
1108 interface
= childInterface
;
1111 if (interface
!= NULL
) {
1113 CFStringRef interface_name
= NULL
;
1114 CFStringRef suffix
= NULL
;
1117 // check if the [stored] service name matches the non-localized interface
1118 // name. If so, return the localized name.
1120 // Also, the older "Built-in XXX" interface names are too long for the
1121 // current UI. If we find that the [stored] service name matches the older
1122 // name, return the newer (and shorter) localized name.
1124 // Note: the user/admin will no longer be able to set the service name
1125 // to "Built-in Ethernet".
1127 for (i
= 0; i
< 3; i
++) {
1128 if (servicePrivate
->name
== NULL
) {
1129 // if no [stored] service name to compare
1135 // compare the non-localized interface name
1136 interface_name
= __SCNetworkInterfaceGetNonLocalizedDisplayName(interface
);
1137 if (interface_name
!= NULL
) {
1138 CFRetain(interface_name
);
1141 #if !TARGET_OS_IPHONE
1143 // compare the older "Built-in XXX" localized name
1144 interface_name
= __SCNetworkInterfaceCopyXLocalizedDisplayName(interface
);
1147 // compare the older "Built-in XXX" non-localized name
1148 interface_name
= __SCNetworkInterfaceCopyXNonLocalizedDisplayName(interface
);
1150 #endif // !TARGET_OS_IPHONE
1155 if (interface_name
!= NULL
) {
1156 Boolean match
= FALSE
;
1158 if (CFEqual(name
, interface_name
)) {
1159 // if service name matches the OLD localized
1162 } else if (CFStringHasPrefix(name
, interface_name
)) {
1163 CFIndex prefixLen
= CFStringGetLength(interface_name
);
1164 CFIndex suffixLen
= CFStringGetLength(name
);
1166 suffix
= CFStringCreateWithSubstring(NULL
,
1168 CFRangeMake(prefixLen
, suffixLen
- prefixLen
));
1171 CFRelease(interface_name
);
1174 CFRelease(servicePrivate
->name
);
1175 servicePrivate
->name
= NULL
;
1182 // if the service name has not been set, use the localized interface name
1184 if (servicePrivate
->name
== NULL
) {
1185 interface_name
= SCNetworkInterfaceGetLocalizedDisplayName(interface
);
1186 if (interface_name
!= NULL
) {
1187 if (suffix
!= NULL
) {
1188 servicePrivate
->name
= CFStringCreateWithFormat(NULL
,
1194 servicePrivate
->name
= CFRetain(interface_name
);
1198 if (suffix
!= NULL
) CFRelease(suffix
);
1201 return servicePrivate
->name
;
1206 SCNetworkServiceGetServiceID(SCNetworkServiceRef service
)
1208 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1210 if (!isA_SCNetworkService(service
)) {
1211 _SCErrorSet(kSCStatusInvalidArgument
);
1215 return servicePrivate
->serviceID
;
1220 SCNetworkServiceGetTypeID(void)
1222 pthread_once(&initialized
, __SCNetworkServiceInitialize
); /* initialize runtime */
1223 return __kSCNetworkServiceTypeID
;
1228 SCNetworkServiceRemove(SCNetworkServiceRef service
)
1232 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1235 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1236 _SCErrorSet(kSCStatusInvalidArgument
);
1240 // remove service from all sets
1242 sets
= SCNetworkSetCopyAll(servicePrivate
->prefs
);
1247 n
= CFArrayGetCount(sets
);
1248 for (i
= 0; i
< n
; i
++) {
1249 SCNetworkSetRef set
;
1251 set
= CFArrayGetValueAtIndex(sets
, i
);
1252 ok
= SCNetworkSetRemoveService(set
, service
);
1253 if (!ok
&& (SCError() != kSCStatusNoKey
)) {
1263 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1264 servicePrivate
->serviceID
, // service
1266 ok
= SCPreferencesPathRemoveValue(servicePrivate
->prefs
, path
);
1274 SCNetworkServiceRemoveProtocolType(SCNetworkServiceRef service
, CFStringRef protocolType
)
1276 CFDictionaryRef entity
;
1279 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1281 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1282 _SCErrorSet(kSCStatusInvalidArgument
);
1286 if (!__SCNetworkProtocolIsValidType(protocolType
)) {
1287 _SCErrorSet(kSCStatusInvalidArgument
);
1291 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1292 servicePrivate
->serviceID
, // service
1293 protocolType
); // entity
1295 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1296 if (entity
== NULL
) {
1297 // if "protocol" does not exist
1298 _SCErrorSet(kSCStatusNoKey
);
1302 ok
= SCPreferencesPathRemoveValue(servicePrivate
->prefs
, path
);
1312 SCNetworkServiceSetEnabled(SCNetworkServiceRef service
, Boolean enabled
)
1316 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1318 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1319 _SCErrorSet(kSCStatusInvalidArgument
);
1323 // make sure that we do not enable a network service if the
1324 // associated interface is a member of a bond or bridge.
1326 SCNetworkInterfaceRef interface
;
1328 interface
= SCNetworkServiceGetInterface(service
);
1329 if ((interface
!= NULL
) &&
1330 __SCNetworkInterfaceIsMember(servicePrivate
->prefs
, interface
)) {
1331 _SCErrorSet(kSCStatusKeyExists
);
1336 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1337 servicePrivate
->serviceID
, // service
1339 ok
= __setPrefsEnabled(servicePrivate
->prefs
, path
, enabled
);
1347 SCNetworkServiceSetName(SCNetworkServiceRef service
, CFStringRef name
)
1349 CFDictionaryRef entity
;
1352 CFStringRef saveName
= NULL
;
1353 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1355 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1356 _SCErrorSet(kSCStatusInvalidArgument
);
1361 if (!isA_CFString(name
)) {
1362 _SCErrorSet(kSCStatusInvalidArgument
);
1365 saveName
= CFRetain(name
);
1369 SCNetworkInterfaceRef interface
;
1371 interface
= SCNetworkServiceGetInterface(service
);
1372 while (interface
!= NULL
) {
1373 SCNetworkInterfaceRef childInterface
;
1375 childInterface
= SCNetworkInterfaceGetInterface(interface
);
1376 if (childInterface
== NULL
) {
1380 interface
= childInterface
;
1383 if (interface
!= NULL
) {
1384 CFStringRef interface_name
;
1386 interface_name
= SCNetworkInterfaceGetLocalizedDisplayName(interface
);
1387 if (interface_name
!= NULL
) {
1388 if (CFEqual(name
, interface_name
)) {
1389 // if service name matches the localized interface name
1390 // then store the non-localized name.
1391 interface_name
= __SCNetworkInterfaceGetNonLocalizedDisplayName(interface
);
1392 if (interface_name
!= NULL
) {
1393 CFRelease(saveName
);
1394 saveName
= CFRetain(interface_name
);
1396 } else if (CFStringHasPrefix(name
, interface_name
)) {
1397 CFIndex prefixLen
= CFStringGetLength(interface_name
);
1399 CFIndex suffixLen
= CFStringGetLength(name
);
1401 // if service name matches the localized interface name plus
1402 // a few extra characters) then store the non-localized name with
1404 suffix
= CFStringCreateWithSubstring(NULL
,
1406 CFRangeMake(prefixLen
, suffixLen
- prefixLen
));
1407 interface_name
= __SCNetworkInterfaceGetNonLocalizedDisplayName(interface
);
1408 if (interface_name
!= NULL
) {
1409 CFRelease(saveName
);
1410 saveName
= CFStringCreateWithFormat(NULL
,
1422 #define PREVENT_DUPLICATE_SERVICE_NAMES
1423 #ifdef PREVENT_DUPLICATE_SERVICE_NAMES
1427 // ensure that each service is uniquely named within its sets
1429 sets
= SCNetworkSetCopyAll(servicePrivate
->prefs
);
1434 set_count
= CFArrayGetCount(sets
);
1435 for (set_index
= 0; set_index
< set_count
; set_index
++) {
1436 CFIndex service_index
;
1437 Boolean isDup
= FALSE
;
1438 Boolean isMember
= FALSE
;
1439 CFIndex service_count
;
1440 CFArrayRef services
;
1441 SCNetworkSetRef set
= CFArrayGetValueAtIndex(sets
, set_index
);
1443 services
= SCNetworkSetCopyServices(set
);
1445 service_count
= CFArrayGetCount(services
);
1446 for (service_index
= 0; service_index
< service_count
; service_index
++) {
1447 CFStringRef otherID
;
1448 CFStringRef otherName
;
1449 SCNetworkServiceRef otherService
;
1451 otherService
= CFArrayGetValueAtIndex(services
, service_index
);
1453 otherID
= SCNetworkServiceGetServiceID(otherService
);
1454 if (CFEqual(servicePrivate
->serviceID
, otherID
)) {
1455 // if the service is a member of this set
1460 otherName
= SCNetworkServiceGetName(otherService
);
1461 if ((otherName
!= NULL
) && CFEqual(name
, otherName
)) {
1467 CFRelease(services
);
1469 if (isMember
&& isDup
) {
1471 * if this service is a member of the set and
1472 * the "name" is not unique.
1475 if (saveName
!= NULL
) CFRelease(saveName
);
1476 _SCErrorSet(kSCStatusKeyExists
);
1484 #endif /* PREVENT_DUPLICATE_SERVICE_NAMES */
1486 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1487 servicePrivate
->serviceID
, // service
1489 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1490 if (isA_CFDictionary(entity
) ||
1491 ((entity
== NULL
) && (name
!= NULL
))) {
1492 CFMutableDictionaryRef newEntity
;
1494 if (entity
!= NULL
) {
1495 newEntity
= CFDictionaryCreateMutableCopy(NULL
, 0, entity
);
1497 newEntity
= CFDictionaryCreateMutable(NULL
,
1499 &kCFTypeDictionaryKeyCallBacks
,
1500 &kCFTypeDictionaryValueCallBacks
);
1502 if (saveName
!= NULL
) {
1503 CFDictionarySetValue(newEntity
, kSCPropUserDefinedName
, saveName
);
1505 CFDictionaryRemoveValue(newEntity
, kSCPropUserDefinedName
);
1507 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, newEntity
);
1508 CFRelease(newEntity
);
1511 if (saveName
!= NULL
) CFRelease(saveName
);
1513 if (servicePrivate
->name
!= NULL
) CFRelease(servicePrivate
->name
);
1514 if (name
!= NULL
) CFRetain(name
);
1515 servicePrivate
->name
= name
;
1522 #pragma mark SCNetworkService SPIs
1525 SCNetworkServicePrimaryRank
1526 SCNetworkServiceGetPrimaryRank(SCNetworkServiceRef service
)
1528 CFDictionaryRef entity
;
1531 SCNetworkServicePrimaryRank rank
= kSCNetworkServicePrimaryRankDefault
;
1532 CFStringRef rankStr
= NULL
;
1533 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1535 if (!isA_SCNetworkService(service
)) {
1536 _SCErrorSet(kSCStatusInvalidArgument
);
1540 if (servicePrivate
->prefs
!= NULL
) {
1541 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
,
1542 servicePrivate
->serviceID
,
1544 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1546 if (isA_CFDictionary(entity
)) {
1547 rankStr
= CFDictionaryGetValue(entity
, kSCPropNetServicePrimaryRank
);
1548 ok
= __str_to_rank(rankStr
, &rank
);
1550 } else if (servicePrivate
->store
!= NULL
) {
1551 path
= SCDynamicStoreKeyCreateNetworkServiceEntity(NULL
,
1552 kSCDynamicStoreDomainState
,
1553 servicePrivate
->serviceID
,
1555 entity
= SCDynamicStoreCopyValue(servicePrivate
->store
, path
);
1557 if (entity
!= NULL
) {
1558 if (isA_CFDictionary(entity
)) {
1559 rankStr
= CFDictionaryGetValue(entity
, kSCPropNetServicePrimaryRank
);
1560 ok
= __str_to_rank(rankStr
, &rank
);
1565 _SCErrorSet(kSCStatusInvalidArgument
);
1570 rank
= kSCNetworkServicePrimaryRankDefault
;
1571 _SCErrorSet(kSCStatusInvalidArgument
);
1572 } else if (rank
== kSCNetworkServicePrimaryRankDefault
) {
1573 _SCErrorSet(kSCStatusOK
);
1581 SCNetworkServiceSetPrimaryRank(SCNetworkServiceRef service
,
1582 SCNetworkServicePrimaryRank newRank
)
1585 CFDictionaryRef entity
;
1586 CFMutableDictionaryRef newEntity
;
1587 CFStringRef path
= NULL
;
1588 CFStringRef rankStr
= NULL
;
1589 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1591 if (!isA_SCNetworkService(service
)) {
1592 _SCErrorSet(kSCStatusInvalidArgument
);
1596 ok
= __rank_to_str(newRank
, &rankStr
);
1598 _SCErrorSet(kSCStatusInvalidArgument
);
1602 if (servicePrivate
->prefs
!= NULL
) {
1604 case kSCNetworkServicePrimaryRankDefault
:
1605 case kSCNetworkServicePrimaryRankNever
:
1606 case kSCNetworkServicePrimaryRankScoped
:
1607 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
,
1608 servicePrivate
->serviceID
,
1610 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1611 if (entity
!= NULL
) {
1612 if (!isA_CFDictionary(entity
)) {
1614 _SCErrorSet(kSCStatusFailed
);
1617 newEntity
= CFDictionaryCreateMutableCopy(NULL
, 0, entity
);
1619 newEntity
= CFDictionaryCreateMutable(NULL
,
1621 &kCFTypeDictionaryKeyCallBacks
,
1622 &kCFTypeDictionaryValueCallBacks
);
1624 if (rankStr
!= NULL
) {
1625 CFDictionarySetValue(newEntity
, kSCPropNetServicePrimaryRank
, rankStr
);
1627 CFDictionaryRemoveValue(newEntity
, kSCPropNetServicePrimaryRank
);
1629 if (CFDictionaryGetCount(newEntity
) > 0) {
1630 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, newEntity
);
1632 ok
= SCPreferencesPathRemoveValue(servicePrivate
->prefs
, path
);
1634 CFRelease(newEntity
);
1640 _SCErrorSet(kSCStatusInvalidArgument
);
1643 } else if (servicePrivate
->store
!= NULL
) {
1644 path
= SCDynamicStoreKeyCreateNetworkServiceEntity(NULL
,
1645 kSCDynamicStoreDomainState
,
1646 servicePrivate
->serviceID
,
1648 entity
= SCDynamicStoreCopyValue(servicePrivate
->store
, path
);
1649 if (entity
!= NULL
) {
1650 if (!isA_CFDictionary(entity
)) {
1653 _SCErrorSet(kSCStatusFailed
);
1656 newEntity
= CFDictionaryCreateMutableCopy(NULL
, 0, entity
);
1659 newEntity
= CFDictionaryCreateMutable(NULL
,
1661 &kCFTypeDictionaryKeyCallBacks
,
1662 &kCFTypeDictionaryValueCallBacks
);
1664 if (rankStr
!= NULL
) {
1665 CFDictionarySetValue(newEntity
, kSCPropNetServicePrimaryRank
, rankStr
);
1667 CFDictionaryRemoveValue(newEntity
, kSCPropNetServicePrimaryRank
);
1669 if (CFDictionaryGetCount(newEntity
) > 0) {
1670 ok
= SCDynamicStoreSetValue(servicePrivate
->store
, path
, newEntity
);
1672 ok
= SCDynamicStoreRemoveValue(servicePrivate
->store
, path
);
1674 CFRelease(newEntity
);
1679 _SCErrorSet(kSCStatusInvalidArgument
);
1685 if (path
!= NULL
) CFRelease(path
);
1691 _SCNetworkServiceIsVPN(SCNetworkServiceRef service
)
1693 SCNetworkInterfaceRef interface
;
1694 CFStringRef interfaceType
;
1696 interface
= SCNetworkServiceGetInterface(service
);
1697 if (interface
== NULL
) {
1701 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
1702 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
)) {
1703 interface
= SCNetworkInterfaceGetInterface(interface
);
1704 if (interface
== NULL
) {
1708 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
1709 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeL2TP
)) {
1712 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPTP
)) {
1715 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeVPN
)) {
1717 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeIPSec
)) {
1726 SCNetworkServiceSetExternalID(SCNetworkServiceRef service
, CFStringRef identifierDomain
, CFStringRef identifier
)
1728 CFStringRef prefs_path
;
1729 CFDictionaryRef service_dictionary
;
1730 SCNetworkServicePrivateRef service_private
= (SCNetworkServicePrivateRef
)service
;
1731 Boolean success
= FALSE
;
1732 CFStringRef prefixed_domain
;
1734 if (!isA_SCNetworkService(service
) || (service_private
->prefs
== NULL
) || !isA_CFString(identifierDomain
)) {
1735 _SCErrorSet(kSCStatusInvalidArgument
);
1739 if (identifier
!= NULL
&& !isA_CFString(identifier
)) {
1740 _SCErrorSet(kSCStatusInvalidArgument
);
1744 prefixed_domain
= CFStringCreateWithFormat(NULL
, 0, CFSTR("%s%@"), EXTERNAL_ID_DOMAIN_PREFIX
, identifierDomain
);
1746 prefs_path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
,
1747 service_private
->serviceID
,
1750 service_dictionary
= SCPreferencesPathGetValue(service_private
->prefs
, prefs_path
);
1751 if (isA_CFDictionary(service_dictionary
) || ((service_dictionary
== NULL
) && (identifier
!= NULL
))) {
1752 CFMutableDictionaryRef new_service_dictionary
;
1754 if (service_dictionary
!= NULL
) {
1755 new_service_dictionary
= CFDictionaryCreateMutableCopy(NULL
, 0, service_dictionary
);
1757 new_service_dictionary
= CFDictionaryCreateMutable(NULL
,
1759 &kCFTypeDictionaryKeyCallBacks
,
1760 &kCFTypeDictionaryValueCallBacks
);
1763 if (identifier
!= NULL
) {
1764 CFDictionarySetValue(new_service_dictionary
, prefixed_domain
, identifier
);
1766 CFDictionaryRemoveValue(new_service_dictionary
, prefixed_domain
);
1768 success
= SCPreferencesPathSetValue(service_private
->prefs
, prefs_path
, new_service_dictionary
);
1769 CFRelease(new_service_dictionary
);
1771 CFRelease(prefs_path
);
1773 if (identifier
!= NULL
) {
1774 if (service_private
->externalIDs
== NULL
) {
1775 service_private
->externalIDs
= CFDictionaryCreateMutable(NULL
,
1777 &kCFTypeDictionaryKeyCallBacks
,
1778 &kCFTypeDictionaryValueCallBacks
);
1780 CFDictionarySetValue(service_private
->externalIDs
, prefixed_domain
, identifier
);
1782 if (service_private
->externalIDs
!= NULL
) {
1783 CFDictionaryRemoveValue(service_private
->externalIDs
, prefixed_domain
);
1787 CFRelease(prefixed_domain
);
1790 _SCErrorSet(kSCStatusFailed
);
1798 SCNetworkServiceCopyExternalID(SCNetworkServiceRef service
, CFStringRef identifierDomain
)
1800 SCNetworkServicePrivateRef service_private
= (SCNetworkServicePrivateRef
)service
;
1801 CFStringRef identifier
= NULL
;
1802 CFStringRef prefixed_domain
;
1804 if (!isA_SCNetworkService(service
) || (service_private
->prefs
== NULL
) || !isA_CFString(identifierDomain
)) {
1805 _SCErrorSet(kSCStatusInvalidArgument
);
1809 prefixed_domain
= CFStringCreateWithFormat(NULL
, 0, CFSTR("%s%@"), EXTERNAL_ID_DOMAIN_PREFIX
, identifierDomain
);
1811 if (service_private
->externalIDs
!= NULL
) {
1812 identifier
= CFDictionaryGetValue(service_private
->externalIDs
, prefixed_domain
);
1813 if (identifier
!= NULL
) {
1814 CFRetain(identifier
);
1818 if (identifier
== NULL
) {
1819 CFStringRef prefs_path
;
1820 CFDictionaryRef service_dictionary
;
1822 prefs_path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
,
1823 service_private
->serviceID
,
1826 service_dictionary
= SCPreferencesPathGetValue(service_private
->prefs
, prefs_path
);
1827 if (isA_CFDictionary(service_dictionary
)) {
1828 identifier
= CFDictionaryGetValue(service_dictionary
, prefixed_domain
);
1829 if (identifier
!= NULL
) {
1830 CFRetain(identifier
);
1831 if (service_private
->externalIDs
== NULL
) {
1832 service_private
->externalIDs
= CFDictionaryCreateMutable(NULL
,
1834 &kCFTypeDictionaryKeyCallBacks
,
1835 &kCFTypeDictionaryValueCallBacks
);
1837 CFDictionarySetValue(service_private
->externalIDs
, prefixed_domain
, identifier
);
1840 CFRelease(prefs_path
);
1843 CFRelease(prefixed_domain
);
1845 if (identifier
== NULL
) {
1846 _SCErrorSet(kSCStatusNoKey
);
1854 CFStringRef oldServiceID
;
1855 CFStringRef newServiceID
;
1856 } serviceContext
, *serviceContextRef
;
1860 replaceServiceID(const void *value
, void *context
)
1862 CFStringRef link
= NULL
;
1863 CFStringRef oldLink
;
1864 CFMutableArrayRef newServiceOrder
;
1866 serviceContextRef service_context
= (serviceContextRef
)context
;
1867 CFArrayRef serviceOrder
= NULL
;
1868 SCNetworkSetRef set
= (SCNetworkSetRef
)value
;
1869 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1871 // update service order
1872 serviceOrder
= SCNetworkSetGetServiceOrder(set
);
1873 if ((isA_CFArray(serviceOrder
) != NULL
) &&
1874 (CFArrayContainsValue(serviceOrder
,
1875 CFRangeMake(0, CFArrayGetCount(serviceOrder
)),
1876 service_context
->oldServiceID
) == TRUE
)) {
1878 CFIndex serviceOrderIndex
;
1880 // replacing all instances of old service ID with new one
1881 newServiceOrder
= CFArrayCreateMutableCopy(NULL
, 0, serviceOrder
);
1882 count
= CFArrayGetCount(newServiceOrder
);
1883 for (serviceOrderIndex
= 0; serviceOrderIndex
< count
; serviceOrderIndex
++) {
1884 CFStringRef serviceID
;
1886 serviceID
= CFArrayGetValueAtIndex(newServiceOrder
, serviceOrderIndex
);
1887 if (CFEqual(serviceID
, service_context
->oldServiceID
)) {
1888 CFArraySetValueAtIndex(newServiceOrder
, serviceOrderIndex
, service_context
->newServiceID
);
1891 SCNetworkSetSetServiceOrder(set
, newServiceOrder
);
1892 CFRelease(newServiceOrder
);
1895 // check if service with old serviceID is part of the set
1896 path
= SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL
, // allocator
1897 setPrivate
->setID
, // set
1898 service_context
->oldServiceID
, // service
1900 oldLink
= SCPreferencesPathGetLink(setPrivate
->prefs
, path
);
1901 if (oldLink
== NULL
) {
1902 // don't make any changes if service with old serviceID is not found
1906 // remove link between "set" and old "service"
1907 SCPreferencesPathRemoveValue(setPrivate
->prefs
, path
);
1910 // create the link between "set" and the "service"
1911 path
= SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL
, // allocator
1912 setPrivate
->setID
, // set
1913 service_context
->newServiceID
, // service
1915 link
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1916 service_context
->newServiceID
, // service
1918 SCPreferencesPathSetLink(setPrivate
->prefs
, path
, link
);
1934 _SCNetworkServiceSetServiceID(SCNetworkServiceRef service
, CFStringRef newServiceID
)
1936 CFArrayRef allSets
= NULL
;
1937 CFDictionaryRef entity
;
1938 CFStringRef newPath
;
1940 CFStringRef oldPath
= NULL
;
1941 serviceContext service_context
;
1942 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1944 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1945 _SCErrorSet(kSCStatusInvalidArgument
);
1949 if (!isA_CFString(newServiceID
)) {
1950 _SCErrorSet(kSCStatusInvalidArgument
);
1954 if (CFEqual(newServiceID
, servicePrivate
->serviceID
)) {
1955 // no work needs to be done if new service ID is equal to current service ID
1959 newPath
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1960 newServiceID
, // service
1962 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, newPath
);
1963 if (isA_CFDictionary(entity
)) {
1964 // if the new service already exists
1965 _SCErrorSet(kSCStatusKeyExists
);
1969 oldPath
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1970 servicePrivate
->serviceID
, // service
1972 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, oldPath
);
1973 if (!isA_CFDictionary(entity
)) {
1974 // if the service has already been removed
1975 _SCErrorSet(kSCStatusNoKey
);
1979 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, newPath
, entity
);
1982 ok
= SCPreferencesPathRemoveValue(servicePrivate
->prefs
, oldPath
);
1985 allSets
= SCNetworkSetCopyAll(servicePrivate
->prefs
);
1987 service_context
.newServiceID
= newServiceID
;
1988 service_context
.oldServiceID
= servicePrivate
->serviceID
;
1990 // find all sets w/oldServiceID and update
1991 // ... and update the serviceOrder
1992 CFArrayApplyFunction(allSets
,
1993 CFRangeMake(0, CFArrayGetCount(allSets
)),
1997 if (servicePrivate
->interface
!= NULL
) {
1998 SCNetworkInterfaceRef newInterface
;
2000 // duplicate the interface and associate the copy with the new service ID
2001 newInterface
= (SCNetworkInterfaceRef
)__SCNetworkInterfaceCreateCopy(NULL
,
2002 servicePrivate
->interface
,
2003 servicePrivate
->prefs
,
2005 CFRelease(servicePrivate
->interface
);
2006 servicePrivate
->interface
= newInterface
;
2009 // replace serviceID with new one
2010 CFRetain(newServiceID
);
2011 CFRelease(servicePrivate
->serviceID
);
2012 servicePrivate
->serviceID
= newServiceID
;
2016 if (oldPath
!= NULL
) {
2019 if (newPath
!= NULL
) {
2022 if (allSets
!= NULL
) {
2028 #define kVPNProtocolPayloadInfo CFSTR("com.apple.payload")
2029 #define kSCEntNetLoginWindowEAPOL CFSTR("EAPOL.LoginWindow")
2032 copyInterfaceConfiguration(SCNetworkServiceRef oldService
, SCNetworkServiceRef newService
)
2034 SCNetworkInterfaceRef oldInterface
;
2035 SCNetworkInterfaceRef newInterface
;
2037 oldInterface
= SCNetworkServiceGetInterface(oldService
);
2038 newInterface
= SCNetworkServiceGetInterface(newService
);
2040 while (oldInterface
!= NULL
) {
2041 CFDictionaryRef configuration
;
2042 CFStringRef interfaceType
;
2044 if (newInterface
== NULL
) {
2045 // oops ... interface layering does not match
2049 // copy interface configuration
2050 configuration
= SCNetworkInterfaceGetConfiguration(oldInterface
);
2052 if ((configuration
!= NULL
) ||
2053 (SCError() == kSCStatusOK
)) {
2054 if (SCNetworkInterfaceSetConfiguration(newInterface
, configuration
) == FALSE
) {
2055 SC_log(LOG_INFO
, "problem setting interface configuration");
2060 // special case: PPP/L2TP + IPSec
2061 interfaceType
= SCNetworkInterfaceGetInterfaceType(oldInterface
);
2062 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
)) {
2063 SCNetworkInterfaceRef childInterface
;
2065 childInterface
= SCNetworkInterfaceGetInterface(oldInterface
);
2066 if (childInterface
!= NULL
) {
2067 CFStringRef childInterfaceType
;
2069 childInterfaceType
= SCNetworkInterfaceGetInterfaceType(childInterface
);
2071 if (CFEqual(childInterfaceType
, kSCNetworkInterfaceTypeL2TP
)) {
2072 configuration
= SCNetworkInterfaceGetExtendedConfiguration(oldInterface
, kSCEntNetIPSec
);
2073 if ((configuration
!= NULL
) ||
2074 (SCError() == kSCStatusOK
)) {
2075 if (SCNetworkInterfaceSetExtendedConfiguration(newInterface
, kSCEntNetIPSec
, configuration
) == FALSE
) {
2076 SC_log(LOG_INFO
, "problem setting child interface configuration");
2083 // special case: 802.1x
2084 configuration
= SCNetworkInterfaceGetExtendedConfiguration(oldInterface
, kSCEntNetEAPOL
);
2085 if ((configuration
!= NULL
) ||
2086 (SCError() == kSCStatusOK
)) {
2087 (void) SCNetworkInterfaceSetExtendedConfiguration(newInterface
, kSCEntNetEAPOL
, configuration
);
2090 // special case: Managed Client
2091 configuration
= SCNetworkInterfaceGetExtendedConfiguration(oldInterface
, kVPNProtocolPayloadInfo
);
2092 if ((configuration
!= NULL
) ||
2093 (SCError() == kSCStatusOK
)) {
2094 (void) SCNetworkInterfaceSetExtendedConfiguration(newInterface
, kVPNProtocolPayloadInfo
, configuration
);
2097 // special case: Network Pref
2098 configuration
= SCNetworkInterfaceGetExtendedConfiguration(oldInterface
, kSCValNetPPPAuthProtocolEAP
);
2099 if ((configuration
!= NULL
) ||
2100 (SCError() == kSCStatusOK
)) {
2101 (void) SCNetworkInterfaceSetExtendedConfiguration(newInterface
, kSCValNetPPPAuthProtocolEAP
, configuration
);
2104 // special case: Remote Pref
2105 configuration
= SCNetworkInterfaceGetExtendedConfiguration(oldInterface
, kSCEntNetLoginWindowEAPOL
);
2106 if ((configuration
!= NULL
) ||
2107 (SCError() == kSCStatusOK
)) {
2108 (void) SCNetworkInterfaceSetExtendedConfiguration(newInterface
, kSCEntNetLoginWindowEAPOL
, configuration
);
2111 // special case: Network Extension
2112 configuration
= SCNetworkInterfaceGetExtendedConfiguration(oldInterface
, kSCNetworkInterfaceTypeIPSec
);
2113 if ((configuration
!= NULL
) ||
2114 (SCError() == kSCStatusOK
)) {
2115 (void) SCNetworkInterfaceSetExtendedConfiguration(newInterface
, kSCNetworkInterfaceTypeIPSec
, configuration
);
2118 oldInterface
= SCNetworkInterfaceGetInterface(oldInterface
);
2119 newInterface
= SCNetworkInterfaceGetInterface(newInterface
);
2127 __SCNetworkServiceAddProtocolToService(SCNetworkServiceRef service
, CFStringRef protocolType
, CFDictionaryRef configuration
, Boolean enabled
)
2130 SCNetworkProtocolRef protocol
;
2132 protocol
= SCNetworkServiceCopyProtocol(service
, protocolType
);
2134 if ((protocol
== NULL
) &&
2135 (SCError() == kSCStatusNoKey
)) {
2136 ok
= SCNetworkServiceAddProtocolType(service
, protocolType
);
2138 protocol
= SCNetworkServiceCopyProtocol(service
, protocolType
);
2141 if (protocol
!= NULL
) {
2142 SCNetworkProtocolSetConfiguration(protocol
, configuration
);
2143 SCNetworkProtocolSetEnabled(protocol
, enabled
);
2144 CFRelease(protocol
);
2153 __SCNetworkServiceMigrateNew(SCPreferencesRef prefs
,
2154 SCNetworkServiceRef service
,
2155 CFDictionaryRef bsdMapping
,
2156 CFDictionaryRef setMapping
,
2157 CFDictionaryRef serviceSetMapping
)
2159 CFStringRef deviceName
= NULL
;
2161 SCNetworkInterfaceRef interface
= NULL
;
2162 CFDictionaryRef interfaceEntity
= NULL
;
2163 CFMutableDictionaryRef interfaceEntityMutable
= NULL
;
2164 SCNetworkSetRef newSet
= NULL
;
2165 SCPreferencesRef ni_prefs
= NULL
;
2166 SCNetworkInterfaceRef ni_interface
= NULL
;
2167 SCNetworkInterfaceRef oldInterface
= NULL
;
2168 SCNetworkSetRef oldSet
= NULL
;
2169 SCNetworkServiceRef newService
= NULL
;
2170 CFStringRef serviceID
= NULL
;
2171 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
) service
;
2172 CFMutableDictionaryRef servicesMutable
= NULL
;
2173 CFArrayRef setList
= NULL
;
2174 Boolean success
= FALSE
;
2175 CFStringRef targetDeviceName
= NULL
;
2176 CFStringRef userDefinedName
= NULL
;
2177 CFStringRef userDefinedNameInterface
= NULL
;
2178 CFArrayRef protocols
= NULL
;
2179 CFStringRef subType
;
2181 if ((isA_SCNetworkService(service
) == NULL
) ||
2182 (isA_SCNetworkInterface(servicePrivate
->interface
) == NULL
) ||
2183 (servicePrivate
->prefs
== NULL
)) {
2186 serviceID
= servicePrivate
->serviceID
;
2188 newService
= SCNetworkServiceCopy(prefs
, serviceID
);
2189 if (newService
!= NULL
) {
2190 // Cannot add service if it already exists
2191 SC_log(LOG_INFO
, "Service already exists");
2195 oldInterface
= SCNetworkServiceGetInterface(service
);
2196 interfaceEntity
= __SCNetworkInterfaceCopyInterfaceEntity(oldInterface
);
2197 if (interfaceEntity
== NULL
) {
2198 SC_log(LOG_INFO
, "No interface entity");
2201 interfaceEntityMutable
= CFDictionaryCreateMutableCopy(NULL
, 0, interfaceEntity
);
2203 if (isA_CFDictionary(bsdMapping
) != NULL
) {
2204 deviceName
= CFDictionaryGetValue(interfaceEntityMutable
, kSCPropNetInterfaceDeviceName
);
2205 if (isA_CFString(deviceName
) != NULL
) {
2206 targetDeviceName
= CFDictionaryGetValue(bsdMapping
, deviceName
);
2207 if (targetDeviceName
!= NULL
) {
2209 CFDictionarySetValue(interfaceEntityMutable
, kSCPropNetInterfaceDeviceName
, targetDeviceName
);
2210 ni_prefs
= __SCPreferencesCreateNIPrefsFromPrefs(prefs
);
2211 ni_interface
= __SCNetworkInterfaceCreateWithNIPreferencesUsingBSDName(NULL
, ni_prefs
, targetDeviceName
);
2212 if (ni_interface
!= NULL
) {
2213 userDefinedNameInterface
= __SCNetworkInterfaceGetUserDefinedName(ni_interface
);
2217 if (userDefinedNameInterface
== NULL
) {
2218 userDefinedNameInterface
= CFDictionaryGetValue(interfaceEntityMutable
, kSCPropUserDefinedName
);
2221 subType
= CFDictionaryGetValue(interfaceEntityMutable
, kSCPropNetInterfaceSubType
);
2222 interface
= _SCNetworkInterfaceCreateWithEntity(NULL
, interfaceEntityMutable
, NULL
);
2223 if (userDefinedNameInterface
!= NULL
) {
2224 __SCNetworkInterfaceSetUserDefinedName(interface
, userDefinedNameInterface
);
2226 // Supporting PPPoE subtype
2227 if (subType
!= NULL
&&
2228 CFEqual(subType
, kSCValNetInterfaceSubTypePPPoE
)) {
2229 SCNetworkInterfaceRef childInterface
= SCNetworkInterfaceGetInterface(interface
);
2230 if (childInterface
!= NULL
) {
2231 __SCNetworkInterfaceSetUserDefinedName(childInterface
, userDefinedNameInterface
);
2234 newService
= SCNetworkServiceCreate(prefs
, interface
);
2235 if (newService
== NULL
) {
2236 SC_log(LOG_INFO
, "SCNetworkServiceCreate() failed");
2240 enabled
= SCNetworkServiceGetEnabled(service
);
2241 SCNetworkServiceSetEnabled(newService
, enabled
);
2243 if (SCNetworkServiceEstablishDefaultConfiguration(newService
) == FALSE
) {
2244 SCNetworkServiceRemove(newService
);
2245 SC_log(LOG_INFO
, "SCNetworkServiceEstablishDefaultConfiguration() failed");
2250 _SCNetworkServiceSetServiceID(newService
, serviceID
);
2252 userDefinedName
= SCNetworkServiceGetName(service
);
2253 if (userDefinedName
!= NULL
&&
2254 SCNetworkServiceSetName(newService
, userDefinedName
) == FALSE
) {
2255 SC_log(LOG_INFO
, "SCNetworkServiceSetName(, %@) failed", userDefinedName
);
2258 // Determine which sets to add service
2259 if (setMapping
!= NULL
&&
2260 serviceSetMapping
!= NULL
) {
2261 setList
= CFDictionaryGetValue(serviceSetMapping
, service
);
2262 if (setList
!= NULL
) {
2263 for (CFIndex idx
= 0; idx
< CFArrayGetCount(setList
); idx
++) {
2264 oldSet
= CFArrayGetValueAtIndex(setList
, idx
);
2265 newSet
= CFDictionaryGetValue(setMapping
, oldSet
);
2267 if (newSet
== NULL
) {
2270 if (SCNetworkSetAddService(newSet
, newService
) == FALSE
) {
2271 SC_log(LOG_INFO
, "SCNetworkSetAddService() failed");
2278 protocols
= SCNetworkServiceCopyProtocols(service
);
2279 if (protocols
!= NULL
) {
2281 for (CFIndex idx
= 0; idx
< CFArrayGetCount(protocols
); idx
++) {
2282 SCNetworkProtocolRef protocol
= CFArrayGetValueAtIndex(protocols
, idx
);
2283 CFDictionaryRef configuration
= SCNetworkProtocolGetConfiguration(protocol
);
2284 CFStringRef protocolType
= SCNetworkProtocolGetProtocolType(protocol
);
2285 enabled
= SCNetworkProtocolGetEnabled(protocol
);
2286 __SCNetworkServiceAddProtocolToService(newService
, protocolType
, configuration
, enabled
);
2288 CFRelease(protocols
);
2291 copyInterfaceConfiguration(service
, newService
);
2295 if (interface
!= NULL
) {
2296 CFRelease(interface
);
2298 if (interfaceEntity
!= NULL
) {
2299 CFRelease(interfaceEntity
);
2301 if (interfaceEntityMutable
!= NULL
) {
2302 CFRelease(interfaceEntityMutable
);
2304 if (newService
!= NULL
) {
2305 CFRelease(newService
);
2307 if (servicesMutable
!= NULL
) {
2308 CFRelease(servicesMutable
);
2310 if (ni_prefs
!= NULL
) {
2311 CFRelease(ni_prefs
);
2313 if (ni_interface
!= NULL
) {
2314 CFRelease(ni_interface
);
2322 __SCNetworkServiceCreate(SCPreferencesRef prefs
,
2323 SCNetworkInterfaceRef interface
,
2324 CFStringRef userDefinedName
)
2326 SCNetworkSetRef currentSet
= NULL
;
2328 SCNetworkServiceRef service
= NULL
;
2330 if (interface
== NULL
) {
2334 if (userDefinedName
== NULL
) {
2335 userDefinedName
= __SCNetworkInterfaceGetUserDefinedName(interface
);
2336 if (userDefinedName
== NULL
) {
2337 SC_log(LOG_INFO
, "No userDefinedName");
2341 service
= SCNetworkServiceCreate(prefs
, interface
);
2342 if (service
== NULL
) {
2343 SC_log(LOG_INFO
, "SCNetworkServiceCreate() failed: %s", SCErrorString(SCError()));
2345 ok
= SCNetworkServiceSetName(service
, userDefinedName
);
2347 SC_log(LOG_INFO
, "SCNetworkServiceSetName() failed: %s", SCErrorString(SCError()));
2348 SCNetworkServiceRemove(service
);
2352 ok
= SCNetworkServiceEstablishDefaultConfiguration(service
);
2354 SC_log(LOG_INFO
, "SCNetworkServiceEstablishDefaultConfiguration() failed: %s", SCErrorString(SCError()));
2355 SCNetworkServiceRemove(service
);
2359 currentSet
= SCNetworkSetCopyCurrent(prefs
);
2360 if (currentSet
== NULL
) {
2361 SC_log(LOG_INFO
, "No current set");
2362 if (service
!= NULL
) {
2363 SCNetworkServiceRemove(service
);
2367 if (service
!= NULL
) {
2368 ok
= SCNetworkSetAddService(currentSet
, service
);
2370 SC_log(LOG_INFO
, "Could not add service to the current set");
2371 SCNetworkServiceRemove(service
);
2377 if (service
!= NULL
) {
2380 if (currentSet
!= NULL
) {
2381 CFRelease(currentSet
);