2 * Copyright (c) 2004-2018 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 * Modification History
27 * May 13, 2004 Allan Nathanson <ajn@apple.com>
32 #include <CoreFoundation/CoreFoundation.h>
33 #include <CoreFoundation/CFRuntime.h>
34 #include "SCNetworkConfigurationInternal.h"
35 #include "SCPreferencesInternal.h"
39 #define EXTERNAL_ID_DOMAIN_PREFIX "_"
41 static CFStringRef
__SCNetworkServiceCopyDescription (CFTypeRef cf
);
42 static void __SCNetworkServiceDeallocate (CFTypeRef cf
);
43 static Boolean
__SCNetworkServiceEqual (CFTypeRef cf1
, CFTypeRef cf2
);
44 static CFHashCode
__SCNetworkServiceHash (CFTypeRef cf
);
47 static CFTypeID __kSCNetworkServiceTypeID
= _kCFRuntimeNotATypeID
;
50 static const CFRuntimeClass __SCNetworkServiceClass
= {
52 "SCNetworkService", // className
55 __SCNetworkServiceDeallocate
, // dealloc
56 __SCNetworkServiceEqual
, // equal
57 __SCNetworkServiceHash
, // hash
58 NULL
, // copyFormattingDesc
59 __SCNetworkServiceCopyDescription
// copyDebugDesc
63 static pthread_once_t initialized
= PTHREAD_ONCE_INIT
;
67 __SCNetworkServiceCopyDescription(CFTypeRef cf
)
69 CFAllocatorRef allocator
= CFGetAllocator(cf
);
70 CFMutableStringRef result
;
71 SCNetworkServiceRef service
= (SCNetworkServiceRef
)cf
;
72 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
74 result
= CFStringCreateMutable(allocator
, 0);
75 CFStringAppendFormat(result
, NULL
, CFSTR("<SCNetworkService %p [%p]> {"), service
, 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 if (!__SCNetworkServiceExists(service
)) {
86 CFStringAppendFormat(result
, NULL
, CFSTR(", REMOVED"));
88 CFStringAppendFormat(result
, NULL
, CFSTR("}"));
95 __SCNetworkServiceDeallocate(CFTypeRef cf
)
97 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)cf
;
99 /* release resources */
101 CFRelease(servicePrivate
->serviceID
);
102 if (servicePrivate
->interface
!= NULL
) CFRelease(servicePrivate
->interface
);
103 if (servicePrivate
->prefs
!= NULL
) CFRelease(servicePrivate
->prefs
);
104 if (servicePrivate
->store
!= NULL
) CFRelease(servicePrivate
->store
);
105 if (servicePrivate
->name
!= NULL
) CFRelease(servicePrivate
->name
);
106 if (servicePrivate
->externalIDs
!= NULL
) CFRelease(servicePrivate
->externalIDs
);
113 __SCNetworkServiceEqual(CFTypeRef cf1
, CFTypeRef cf2
)
115 SCNetworkServicePrivateRef s1
= (SCNetworkServicePrivateRef
)cf1
;
116 SCNetworkServicePrivateRef s2
= (SCNetworkServicePrivateRef
)cf2
;
121 if (s1
->prefs
!= s2
->prefs
)
122 return FALSE
; // if not the same prefs
124 if (!CFEqual(s1
->serviceID
, s2
->serviceID
))
125 return FALSE
; // if not the same service identifier
132 __SCNetworkServiceHash(CFTypeRef cf
)
134 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)cf
;
136 return CFHash(servicePrivate
->serviceID
);
141 __SCNetworkServiceInitialize(void)
143 __kSCNetworkServiceTypeID
= _CFRuntimeRegisterClass(&__SCNetworkServiceClass
);
148 __private_extern__ SCNetworkServicePrivateRef
149 __SCNetworkServiceCreatePrivate(CFAllocatorRef allocator
,
150 SCPreferencesRef prefs
,
151 CFStringRef serviceID
,
152 SCNetworkInterfaceRef interface
)
154 SCNetworkServicePrivateRef servicePrivate
;
157 /* initialize runtime */
158 pthread_once(&initialized
, __SCNetworkServiceInitialize
);
160 /* allocate target */
161 size
= sizeof(SCNetworkServicePrivate
) - sizeof(CFRuntimeBase
);
162 servicePrivate
= (SCNetworkServicePrivateRef
)_CFRuntimeCreateInstance(allocator
,
163 __kSCNetworkServiceTypeID
,
166 if (servicePrivate
== NULL
) {
170 /* initialize non-zero/NULL members */
171 servicePrivate
->prefs
= (prefs
!= NULL
) ? CFRetain(prefs
): NULL
;
172 servicePrivate
->serviceID
= CFStringCreateCopy(NULL
, serviceID
);
173 servicePrivate
->interface
= (interface
!= NULL
) ? CFRetain(interface
) : NULL
;
175 return servicePrivate
;
180 #pragma mark Service ordering
184 _SCNetworkServiceCompare(const void *val1
, const void *val2
, void *context
)
188 CFArrayRef order
= (CFArrayRef
)context
;
189 SCNetworkServiceRef s1
= (SCNetworkServiceRef
)val1
;
190 SCNetworkServiceRef s2
= (SCNetworkServiceRef
)val2
;
192 id1
= SCNetworkServiceGetServiceID(s1
);
193 id2
= SCNetworkServiceGetServiceID(s2
);
200 range
= CFRangeMake(0, CFArrayGetCount(order
));
201 o1
= CFArrayGetFirstIndexOfValue(order
, range
, id1
);
202 o2
= CFArrayGetFirstIndexOfValue(order
, range
, id2
);
205 return (o2
!= kCFNotFound
) ? kCFCompareGreaterThan
: kCFCompareLessThan
;
206 } else if (o1
< o2
) {
207 return (o1
!= kCFNotFound
) ? kCFCompareLessThan
: kCFCompareGreaterThan
;
211 return CFStringCompare(id1
, id2
, 0);
216 #pragma mark SCNetworkService APIs
222 __private_extern__ CFArrayRef
/* of SCNetworkServiceRef's */
223 __SCNetworkServiceCopyAllEnabled(SCPreferencesRef prefs
)
225 CFMutableArrayRef array
= NULL
;
230 sets
= SCNetworkSetCopyAll(prefs
);
235 n_sets
= CFArrayGetCount(sets
);
236 for (i_sets
= 0; i_sets
< n_sets
; i_sets
++) {
242 set
= CFArrayGetValueAtIndex(sets
, i_sets
);
243 services
= SCNetworkSetCopyServices(set
);
244 if (services
== NULL
) {
248 n_services
= CFArrayGetCount(services
);
249 for (i_services
= 0; i_services
< n_services
; i_services
++) {
250 SCNetworkServiceRef service
;
252 service
= CFArrayGetValueAtIndex(services
, i_services
);
253 if (!SCNetworkServiceGetEnabled(service
)) {
258 if ((array
== NULL
) ||
259 !CFArrayContainsValue(array
,
260 CFRangeMake(0, CFArrayGetCount(array
)),
263 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
265 CFArrayAppendValue(array
, service
);
276 __private_extern__ Boolean
277 __SCNetworkServiceExistsForInterface(CFArrayRef services
, SCNetworkInterfaceRef interface
)
282 n
= isA_CFArray(services
) ? CFArrayGetCount(services
) : 0;
283 for (i
= 0; i
< n
; i
++) {
284 SCNetworkServiceRef service
;
285 SCNetworkInterfaceRef service_interface
;
287 service
= CFArrayGetValueAtIndex(services
, i
);
289 service_interface
= SCNetworkServiceGetInterface(service
);
290 while (service_interface
!= NULL
) {
291 if (CFEqual(interface
, service_interface
)) {
295 service_interface
= SCNetworkInterfaceGetInterface(service_interface
);
304 mergeDict(const void *key
, const void *value
, void *context
)
306 CFMutableDictionaryRef newDict
= (CFMutableDictionaryRef
)context
;
308 CFDictionarySetValue(newDict
, key
, value
);
313 static CF_RETURNS_RETAINED CFDictionaryRef
314 _protocolTemplate(SCNetworkServiceRef service
, CFStringRef protocolType
)
316 SCNetworkInterfaceRef interface
;
317 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
318 CFDictionaryRef
template = NULL
;
320 interface
= servicePrivate
->interface
;
321 if (interface
!= NULL
) {
322 SCNetworkInterfaceRef childInterface
;
323 CFStringRef childInterfaceType
= NULL
;
324 CFStringRef interfaceType
;
327 interfaceType
= SCNetworkInterfaceGetInterfaceType(servicePrivate
->interface
);
328 childInterface
= SCNetworkInterfaceGetInterface(servicePrivate
->interface
);
329 if (childInterface
!= NULL
) {
330 childInterfaceType
= SCNetworkInterfaceGetInterfaceType(childInterface
);
333 template = __copyProtocolTemplate(interfaceType
, childInterfaceType
, protocolType
);
334 if (template != NULL
) {
335 CFDictionaryRef overrides
;
337 // move to the interface at the lowest layer
338 while (childInterface
!= NULL
) {
339 interface
= childInterface
;
340 childInterface
= SCNetworkInterfaceGetInterface(interface
);
343 overrides
= __SCNetworkInterfaceGetTemplateOverrides(interface
, protocolType
);
344 if (isA_CFDictionary(overrides
)) {
345 CFMutableDictionaryRef newTemplate
;
347 newTemplate
= CFDictionaryCreateMutableCopy(NULL
, 0, template);
348 CFDictionaryApplyFunction(overrides
, mergeDict
, newTemplate
);
350 template = newTemplate
;
355 if (template == NULL
) {
356 template = CFDictionaryCreate(NULL
,
360 &kCFTypeDictionaryKeyCallBacks
,
361 &kCFTypeDictionaryValueCallBacks
);
369 SCNetworkServiceAddProtocolType(SCNetworkServiceRef service
, CFStringRef protocolType
)
371 CFDictionaryRef entity
;
373 CFDictionaryRef newEntity
= NULL
;
376 SCNetworkProtocolRef protocol
= NULL
;
377 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
379 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
380 _SCErrorSet(kSCStatusInvalidArgument
);
384 if (!__SCNetworkProtocolIsValidType(protocolType
)) {
385 _SCErrorSet(kSCStatusInvalidArgument
);
389 if (!__SCNetworkServiceExists(service
)) {
390 SC_log(LOG_ERR
, "SCNetworkServiceAddProtocolType() w/removed service\n service = %@\n protocol = %@",
393 _SC_crash_once("SCNetworkServiceAddProtocolType() w/removed service", NULL
, NULL
);
394 _SCErrorSet(kSCStatusInvalidArgument
);
398 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
399 servicePrivate
->serviceID
, // service
400 protocolType
); // entity
402 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
403 if (entity
!= NULL
) {
404 // if "protocol" already exists
405 _SCErrorSet(kSCStatusKeyExists
);
409 newEntity
= CFDictionaryCreate(NULL
,
413 &kCFTypeDictionaryKeyCallBacks
,
414 &kCFTypeDictionaryValueCallBacks
);
415 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, newEntity
);
416 CFRelease(newEntity
);
422 protocol
= SCNetworkServiceCopyProtocol(service
, protocolType
);
423 assert(protocol
!= NULL
);
425 newEntity
= _protocolTemplate(service
, protocolType
);
426 assert(newEntity
!= NULL
);
428 ok
= SCNetworkProtocolSetConfiguration(protocol
, newEntity
);
430 // could not set default configuration
434 newEnabled
= !CFDictionaryContainsKey(newEntity
, kSCResvInactive
);
435 ok
= SCNetworkProtocolSetEnabled(protocol
, newEnabled
);
437 // could not enable/disable protocol
443 if (newEntity
!= NULL
) CFRelease(newEntity
);
444 if (protocol
!= NULL
) CFRelease(protocol
);
447 SC_log(LOG_DEBUG
, "SCNetworkServiceAddProtocolType(): %@, %@", service
, protocolType
);
455 CFArrayRef
/* of SCNetworkServiceRef's */
456 SCNetworkServiceCopyAll(SCPreferencesRef prefs
)
458 CFMutableArrayRef array
;
461 CFDictionaryRef services
;
463 path
= SCPreferencesPathKeyCreateNetworkServices(NULL
);
464 services
= SCPreferencesPathGetValue(prefs
, path
);
467 if ((services
!= NULL
) && !isA_CFDictionary(services
)) {
471 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
473 n
= (services
!= NULL
) ? CFDictionaryGetCount(services
) : 0;
476 const void * keys_q
[N_QUICK
];
477 const void ** keys
= keys_q
;
478 const void * vals_q
[N_QUICK
];
479 const void ** vals
= vals_q
;
481 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
482 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
483 vals
= CFAllocatorAllocate(NULL
, n
* sizeof(CFPropertyListRef
), 0);
485 CFDictionaryGetKeysAndValues(services
, keys
, vals
);
486 for (i
= 0; i
< n
; i
++) {
487 CFDictionaryRef entity
;
488 SCNetworkServicePrivateRef servicePrivate
;
490 if (!isA_CFDictionary(vals
[i
])) {
491 SC_log(LOG_INFO
, "error w/service \"%@\"", keys
[i
]);
495 entity
= CFDictionaryGetValue(vals
[i
], kSCEntNetInterface
);
496 if (!isA_CFDictionary(entity
)) {
498 SC_log(LOG_INFO
, "no \"%@\" entity for service \"%@\"",
504 if (__SCNetworkInterfaceEntityIsPPTP(entity
)) {
505 SC_log(LOG_INFO
, "PPTP services are no longer supported");
509 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, prefs
, keys
[i
], NULL
);
510 assert(servicePrivate
!= NULL
);
511 CFArrayAppendValue(array
, (SCNetworkServiceRef
)servicePrivate
);
512 CFRelease(servicePrivate
);
514 if (keys
!= keys_q
) {
515 CFAllocatorDeallocate(NULL
, keys
);
516 CFAllocatorDeallocate(NULL
, vals
);
525 CFArrayRef
/* of SCNetworkInterfaceRef's */
526 __SCNetworkServiceCopyAllInterfaces(SCPreferencesRef prefs
)
528 CFMutableArrayRef interfaces
= NULL
;
529 CFArrayRef services
= NULL
;
530 CFIndex servicesCount
= 0;
531 SCNetworkServiceRef service
= NULL
;
532 SCNetworkInterfaceRef interface
= NULL
;
534 services
= SCNetworkServiceCopyAll(prefs
);
535 if (services
== NULL
) {
539 servicesCount
= CFArrayGetCount(services
);
540 if (servicesCount
== 0) {
544 interfaces
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
546 for (CFIndex idx
= 0; idx
< servicesCount
; idx
++) {
547 service
= CFArrayGetValueAtIndex(services
, idx
);
548 interface
= SCNetworkServiceGetInterface(service
);
550 if (isA_SCNetworkInterface(interface
) == NULL
) {
553 CFArrayAppendValue(interfaces
, interface
);
556 if (CFArrayGetCount(interfaces
) == 0) {
557 // Do not return an empty array
558 CFRelease(interfaces
);
564 if (services
!= NULL
) {
572 * build a list of all of a services entity types that are associated
573 * with the services interface. The list will include :
575 * - entity types associated with the interface type (Ethernet, FireWire, PPP, ...)
576 * - entity types associated with the interface sub-type (PPPSerial, PPPoE, L2TP, PPTP, ...)
577 * - entity types associated with the hardware device (Ethernet, AirPort, FireWire, Modem, ...)
580 _copyInterfaceEntityTypes(CFDictionaryRef protocols
)
582 CFDictionaryRef interface
;
583 CFMutableSetRef interface_entity_types
;
585 interface_entity_types
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
587 interface
= CFDictionaryGetValue(protocols
, kSCEntNetInterface
);
588 if (isA_CFDictionary(interface
)) {
589 CFStringRef entities
[] = { kSCPropNetInterfaceType
,
590 kSCPropNetInterfaceSubType
,
591 kSCPropNetInterfaceHardware
};
593 // include the "Interface" entity itself
594 CFSetAddValue(interface_entity_types
, kSCEntNetInterface
);
596 // include the entities associated with the interface
597 for (size_t i
= 0; i
< sizeof(entities
)/sizeof(entities
[0]); i
++) {
600 entity
= CFDictionaryGetValue(interface
, entities
[i
]);
601 if (isA_CFString(entity
)) {
602 CFSetAddValue(interface_entity_types
, entity
);
607 * and, because we've found some misguided network preference code
608 * developers leaving [PPP] entity dictionaries around even though
609 * they are unused and/or unneeded...
611 CFSetAddValue(interface_entity_types
, kSCEntNetPPP
);
614 return interface_entity_types
;
619 SCNetworkServiceCopy(SCPreferencesRef prefs
, CFStringRef serviceID
)
621 CFDictionaryRef entity
;
623 SCNetworkServicePrivateRef servicePrivate
;
625 if (!isA_CFString(serviceID
)) {
626 _SCErrorSet(kSCStatusInvalidArgument
);
630 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
631 serviceID
, // service
632 kSCEntNetInterface
); // entity
633 entity
= SCPreferencesPathGetValue(prefs
, path
);
636 if (!isA_CFDictionary(entity
)) {
637 // a "service" must have an "interface"
638 _SCErrorSet(kSCStatusNoKey
);
642 if (__SCNetworkInterfaceEntityIsPPTP(entity
)) {
643 SC_log(LOG_INFO
, "PPTP services are no longer supported");
644 _SCErrorSet(kSCStatusNoKey
);
648 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, prefs
, serviceID
, NULL
);
649 return (SCNetworkServiceRef
)servicePrivate
;
654 _SCNetworkServiceCopyActive(SCDynamicStoreRef store
, CFStringRef serviceID
)
656 SCNetworkServicePrivateRef servicePrivate
;
658 if (!isA_CFString(serviceID
)) {
659 _SCErrorSet(kSCStatusInvalidArgument
);
663 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, NULL
, serviceID
, NULL
);
664 assert(servicePrivate
!= NULL
);
666 servicePrivate
->store
= CFRetain(store
);
668 return (SCNetworkServiceRef
)servicePrivate
;
673 SCNetworkServiceCopyProtocol(SCNetworkServiceRef service
, CFStringRef protocolType
)
675 CFSetRef non_protocol_entities
;
677 CFDictionaryRef protocols
;
678 SCNetworkProtocolPrivateRef protocolPrivate
= NULL
;
679 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
681 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
682 _SCErrorSet(kSCStatusInvalidArgument
);
686 if (!isA_CFString(protocolType
)) {
687 _SCErrorSet(kSCStatusInvalidArgument
);
691 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
692 servicePrivate
->serviceID
, // service
694 protocols
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
697 if (!isA_CFDictionary(protocols
)) {
699 _SCErrorSet(kSCStatusFailed
);
703 non_protocol_entities
= _copyInterfaceEntityTypes(protocols
);
704 if (CFSetContainsValue(non_protocol_entities
, protocolType
)) {
705 // if the "protocolType" matches an interface entity type
706 _SCErrorSet(kSCStatusInvalidArgument
);
710 if (!CFDictionaryContainsKey(protocols
, protocolType
)) {
711 // if the "protocolType" entity does not exist
712 _SCErrorSet(kSCStatusNoKey
);
716 protocolPrivate
= __SCNetworkProtocolCreatePrivate(NULL
, protocolType
, service
);
720 CFRelease(non_protocol_entities
);
722 return (SCNetworkProtocolRef
)protocolPrivate
;
726 CFArrayRef
/* of SCNetworkProtocolRef's */
727 SCNetworkServiceCopyProtocols(SCNetworkServiceRef service
)
729 CFMutableArrayRef array
;
731 CFSetRef non_protocol_entities
;
733 CFDictionaryRef protocols
;
734 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
736 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
737 _SCErrorSet(kSCStatusInvalidArgument
);
741 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
742 servicePrivate
->serviceID
, // service
744 protocols
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
747 if (!isA_CFDictionary(protocols
)) {
749 _SCErrorSet(kSCStatusFailed
);
753 non_protocol_entities
= _copyInterfaceEntityTypes(protocols
);
755 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
757 n
= CFDictionaryGetCount(protocols
);
760 const void * keys_q
[N_QUICK
];
761 const void ** keys
= keys_q
;
762 const void * vals_q
[N_QUICK
];
763 const void ** vals
= vals_q
;
765 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
766 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
767 vals
= CFAllocatorAllocate(NULL
, n
* sizeof(CFPropertyListRef
), 0);
769 CFDictionaryGetKeysAndValues(protocols
, keys
, vals
);
770 for (i
= 0; i
< n
; i
++) {
771 SCNetworkProtocolPrivateRef protocolPrivate
;
773 if (!isA_CFDictionary(vals
[i
])) {
774 // if it's not a dictionary then it can't be a protocol entity
778 if (CFSetContainsValue(non_protocol_entities
, keys
[i
])) {
779 // skip any non-protocol (interface) entities
783 protocolPrivate
= __SCNetworkProtocolCreatePrivate(NULL
, keys
[i
], service
);
784 CFArrayAppendValue(array
, (SCNetworkProtocolRef
)protocolPrivate
);
786 CFRelease(protocolPrivate
);
788 if (keys
!= keys_q
) {
789 CFAllocatorDeallocate(NULL
, keys
);
790 CFAllocatorDeallocate(NULL
, vals
);
794 CFRelease(non_protocol_entities
);
801 __SCNetworkServiceSetInterfaceEntity(SCNetworkServiceRef service
,
802 SCNetworkInterfaceRef interface
)
804 CFDictionaryRef entity
;
807 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
809 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
810 servicePrivate
->serviceID
, // service
811 kSCEntNetInterface
); // entity
812 entity
= __SCNetworkInterfaceCopyInterfaceEntity(interface
);
813 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, entity
);
822 SCNetworkServiceCreate(SCPreferencesRef prefs
, SCNetworkInterfaceRef interface
)
824 CFArrayRef components
;
825 CFArrayRef interface_config
;
826 CFStringRef interface_name
;
827 SCNetworkInterfaceRef newInterface
;
830 CFStringRef serviceID
;
831 SCNetworkServicePrivateRef servicePrivate
;
832 CFArrayRef supported_protocols
;
834 if (!isA_SCNetworkInterface(interface
)) {
835 _SCErrorSet(kSCStatusInvalidArgument
);
839 // only allow network interfaces which support one or more protocols
840 // to be added to a service. The one exception is that we allow
841 // third-party interface types to be configured.
842 supported_protocols
= SCNetworkInterfaceGetSupportedProtocolTypes(interface
);
843 if (supported_protocols
== NULL
) {
844 CFStringRef interface_type
;
846 interface_type
= SCNetworkInterfaceGetInterfaceType(interface
);
847 if (CFStringFind(interface_type
, CFSTR("."), 0).location
== kCFNotFound
) {
848 _SCErrorSet(kSCStatusInvalidArgument
);
853 // do not allow creation of a network service if the interface is a
854 // member of a bond or bridge
855 if (__SCNetworkInterfaceIsMember(prefs
, interface
)) {
856 _SCErrorSet(kSCStatusKeyExists
);
860 // establish the service
861 prefix
= SCPreferencesPathKeyCreateNetworkServices(NULL
);
862 path
= __SCPreferencesPathCreateUniqueChild_WithMoreSCFCompatibility(prefs
, prefix
);
863 if (path
== NULL
) path
= SCPreferencesPathCreateUniqueChild(prefs
, prefix
);
869 components
= CFStringCreateArrayBySeparatingStrings(NULL
, path
, CFSTR("/"));
872 serviceID
= CFArrayGetValueAtIndex(components
, 2);
873 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, prefs
, serviceID
, NULL
);
874 CFRelease(components
);
876 // duplicate the interface and associate the copy with the new service
877 newInterface
= (SCNetworkInterfaceRef
)__SCNetworkInterfaceCreateCopy(NULL
,
881 servicePrivate
->interface
= newInterface
;
883 // establish "default" configuration(s) for the interface
884 for (interface
= newInterface
;
886 interface
= SCNetworkInterfaceGetInterface(interface
)) {
887 SCNetworkInterfaceRef childInterface
;
888 CFStringRef childInterfaceType
= NULL
;
889 CFDictionaryRef config
;
890 CFStringRef interfaceType
;
892 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
893 childInterface
= SCNetworkInterfaceGetInterface(interface
);
894 if (childInterface
!= NULL
) {
895 childInterfaceType
= SCNetworkInterfaceGetInterfaceType(childInterface
);
898 config
= __copyInterfaceTemplate(interfaceType
, childInterfaceType
);
899 if (config
!= NULL
) {
900 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeBluetooth
) ||
901 CFEqual(interfaceType
, kSCNetworkInterfaceTypeIrDA
) ||
902 CFEqual(interfaceType
, kSCNetworkInterfaceTypeModem
) ||
903 CFEqual(interfaceType
, kSCNetworkInterfaceTypeSerial
) ||
904 CFEqual(interfaceType
, kSCNetworkInterfaceTypeWWAN
)) {
905 CFDictionaryRef overrides
;
907 overrides
= __SCNetworkInterfaceGetTemplateOverrides(interface
, kSCNetworkInterfaceTypeModem
);
909 // a ConnectionScript (and related keys) from the interface
910 // should trump the settings from the configuration template.
911 if (isA_CFDictionary(overrides
)) {
912 CFMutableDictionaryRef newConfig
;
914 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
915 if (CFDictionaryContainsKey(overrides
, kSCPropNetModemConnectionScript
)) {
916 CFDictionaryRemoveValue(newConfig
, kSCPropNetModemConnectionPersonality
);
917 CFDictionaryRemoveValue(newConfig
, kSCPropNetModemConnectionScript
);
918 CFDictionaryRemoveValue(newConfig
, kSCPropNetModemDeviceVendor
);
919 CFDictionaryRemoveValue(newConfig
, kSCPropNetModemDeviceModel
);
921 CFDictionaryApplyFunction(overrides
, mergeDict
, newConfig
);
925 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
) ||
926 CFEqual(interfaceType
, kSCNetworkInterfaceTypeVPN
)) {
927 CFDictionaryRef overrides
;
929 overrides
= __SCNetworkInterfaceGetTemplateOverrides(interface
, kSCNetworkInterfaceTypePPP
);
930 if (isA_CFDictionary(overrides
)) {
931 CFMutableDictionaryRef newConfig
;
933 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
934 CFDictionaryApplyFunction(overrides
, mergeDict
, newConfig
);
940 if (!__SCNetworkInterfaceSetConfiguration(interface
, NULL
, config
, TRUE
)) {
941 SC_log(LOG_INFO
, "__SCNetworkInterfaceSetConfiguration failed(), interface=%@, type=NULL",
948 // add the interface [entity] to the service
949 (void) __SCNetworkServiceSetInterfaceEntity((SCNetworkServiceRef
)servicePrivate
,
950 servicePrivate
->interface
);
952 // push the [deep] interface configuration into the service.
953 interface_config
= __SCNetworkInterfaceCopyDeepConfiguration(NULL
, servicePrivate
->interface
);
954 __SCNetworkInterfaceSetDeepConfiguration(NULL
, servicePrivate
->interface
, interface_config
);
955 if (interface_config
!= NULL
) CFRelease(interface_config
);
957 // set the service name to match that of the associated interface
959 // Note: It might seem a bit odd to call SCNetworkServiceGetName
960 // followed by an immediate call to SCNetworkServiceSetName. The
961 // trick here is that if no name has previously been set, the
962 // "get" function will return the name of the associated interface.
964 // ... and we "set" a name to ensure that applications that do
965 // not use the APIs will still find a UserDefinedName property
966 // in the SCDynamicStore.
968 interface_name
= SCNetworkServiceGetName((SCNetworkServiceRef
)servicePrivate
);
969 if (interface_name
!= NULL
) {
970 (void) SCNetworkServiceSetName((SCNetworkServiceRef
)servicePrivate
,
974 SC_log(LOG_DEBUG
, "SCNetworkServiceCreate(): %@", servicePrivate
);
976 return (SCNetworkServiceRef
)servicePrivate
;
981 SCNetworkServiceEstablishDefaultConfiguration(SCNetworkServiceRef service
)
984 SCNetworkInterfaceRef interface
;
987 CFArrayRef protocolTypes
;
989 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
991 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
992 _SCErrorSet(kSCStatusInvalidArgument
);
996 interface
= SCNetworkServiceGetInterface(service
);
997 if (interface
== NULL
) {
1001 protocolTypes
= SCNetworkInterfaceGetSupportedProtocolTypes(interface
);
1002 n
= (protocolTypes
!= NULL
) ? CFArrayGetCount(protocolTypes
) : 0;
1003 for (i
= 0; i
< n
; i
++) {
1004 CFStringRef protocolType
;
1006 protocolType
= CFArrayGetValueAtIndex(protocolTypes
, i
);
1007 ok
= SCNetworkServiceAddProtocolType(service
, protocolType
);
1010 "SCNetworkServiceEstablishDefaultConfiguration(): could not add protocol \"%@\"",
1015 rankStr
= __SCNetworkInterfaceGetTemplateOverrides(interface
, kSCPropNetServicePrimaryRank
);
1016 if (isA_CFString(rankStr
)) {
1017 SCNetworkServicePrimaryRank rank
;
1019 ok
= __str_to_rank(rankStr
, &rank
);
1022 "SCNetworkServiceEstablishDefaultConfiguration(): unknown rank \"%@\"",
1027 ok
= SCNetworkServiceSetPrimaryRank(service
, rank
);
1030 "SCNetworkServiceEstablishDefaultConfiguration(): could not set rank \"%@\"",
1043 SCNetworkServiceGetEnabled(SCNetworkServiceRef service
)
1047 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1049 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1050 _SCErrorSet(kSCStatusInvalidArgument
);
1054 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1055 servicePrivate
->serviceID
, // service
1057 enabled
= __getPrefsEnabled(servicePrivate
->prefs
, path
);
1064 SCNetworkInterfaceRef
1065 SCNetworkServiceGetInterface(SCNetworkServiceRef service
)
1067 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1069 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1070 _SCErrorSet(kSCStatusInvalidArgument
);
1074 if (servicePrivate
->interface
== NULL
) {
1075 CFDictionaryRef entity
;
1078 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1079 servicePrivate
->serviceID
, // service
1080 kSCEntNetInterface
); // entity
1081 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1084 if (isA_CFDictionary(entity
)) {
1085 servicePrivate
->interface
= _SCNetworkInterfaceCreateWithEntity(NULL
, entity
, service
);
1089 return servicePrivate
->interface
;
1094 SCNetworkServiceGetName(SCNetworkServiceRef service
)
1096 CFDictionaryRef entity
;
1097 SCNetworkInterfaceRef interface
;
1098 CFStringRef name
= NULL
;
1100 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1101 Boolean useSystemInterfaces
= TRUE
;
1103 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1104 _SCErrorSet(kSCStatusInvalidArgument
);
1108 if (servicePrivate
->name
!= NULL
) {
1109 return servicePrivate
->name
;
1112 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1113 servicePrivate
->serviceID
, // service
1115 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1118 useSystemInterfaces
= ((__SCPreferencesUsingDefaultPrefs(servicePrivate
->prefs
)) &&
1119 !__SCPreferencesGetLimitSCNetworkConfiguration(servicePrivate
->prefs
));
1121 if (isA_CFDictionary(entity
)) {
1122 name
= CFDictionaryGetValue(entity
, kSCPropUserDefinedName
);
1123 if (isA_CFString(name
)) {
1124 servicePrivate
->name
= CFRetain(name
);
1125 if (!useSystemInterfaces
) {
1126 return servicePrivate
->name
;
1131 interface
= SCNetworkServiceGetInterface(service
);
1132 while (interface
!= NULL
) {
1133 SCNetworkInterfaceRef childInterface
;
1134 CFStringRef interfaceType
;
1136 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
1137 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeVPN
)) {
1141 childInterface
= SCNetworkInterfaceGetInterface(interface
);
1142 if ((childInterface
== NULL
) ||
1143 CFEqual(childInterface
, kSCNetworkInterfaceIPv4
)) {
1147 interface
= childInterface
;
1150 if (interface
!= NULL
) {
1152 CFStringRef interface_name
= NULL
;
1153 CFStringRef suffix
= NULL
;
1156 // check if the [stored] service name matches the non-localized interface
1157 // name. If so, return the localized name.
1159 // Also, the older "Built-in XXX" interface names are too long for the
1160 // current UI. If we find that the [stored] service name matches the older
1161 // name, return the newer (and shorter) localized name.
1163 // Note: the user/admin will no longer be able to set the service name
1164 // to "Built-in Ethernet".
1166 for (i
= 0; i
< 3; i
++) {
1167 if (servicePrivate
->name
== NULL
) {
1168 // if no [stored] service name to compare
1174 // compare the non-localized interface name
1175 interface_name
= __SCNetworkInterfaceGetNonLocalizedDisplayName(interface
);
1176 if (interface_name
!= NULL
) {
1177 CFRetain(interface_name
);
1180 #if !TARGET_OS_IPHONE
1182 // compare the older "Built-in XXX" localized name
1183 interface_name
= __SCNetworkInterfaceCopyXLocalizedDisplayName(interface
);
1186 // compare the older "Built-in XXX" non-localized name
1187 interface_name
= __SCNetworkInterfaceCopyXNonLocalizedDisplayName(interface
);
1189 #else // !TARGET_OS_IPHONE
1192 #endif // !TARGET_OS_IPHONE
1195 if (interface_name
!= NULL
) {
1196 Boolean match
= FALSE
;
1198 if (CFEqual(name
, interface_name
)) {
1199 // if service name matches the OLD localized
1202 } else if (CFStringHasPrefix(name
, interface_name
)) {
1203 CFIndex prefixLen
= CFStringGetLength(interface_name
);
1204 CFIndex suffixLen
= CFStringGetLength(name
);
1206 suffix
= CFStringCreateWithSubstring(NULL
,
1208 CFRangeMake(prefixLen
, suffixLen
- prefixLen
));
1211 CFRelease(interface_name
);
1214 CFRelease(servicePrivate
->name
);
1215 servicePrivate
->name
= NULL
;
1222 // if the service name has not been set, use the localized interface name
1224 if (servicePrivate
->name
== NULL
) {
1225 interface_name
= SCNetworkInterfaceGetLocalizedDisplayName(interface
);
1226 if (interface_name
!= NULL
) {
1227 if (suffix
!= NULL
) {
1228 servicePrivate
->name
= CFStringCreateWithFormat(NULL
,
1234 servicePrivate
->name
= CFRetain(interface_name
);
1238 if (suffix
!= NULL
) CFRelease(suffix
);
1241 return servicePrivate
->name
;
1246 SCNetworkServiceGetServiceID(SCNetworkServiceRef service
)
1248 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1250 if (!isA_SCNetworkService(service
)) {
1251 _SCErrorSet(kSCStatusInvalidArgument
);
1255 return servicePrivate
->serviceID
;
1260 SCNetworkServiceGetTypeID(void)
1262 pthread_once(&initialized
, __SCNetworkServiceInitialize
); /* initialize runtime */
1263 return __kSCNetworkServiceTypeID
;
1268 SCNetworkServiceRemove(SCNetworkServiceRef service
)
1272 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1275 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1276 _SCErrorSet(kSCStatusInvalidArgument
);
1280 if (!__SCNetworkServiceExists(service
)) {
1281 SC_log(LOG_ERR
, "SCNetworkServiceRemove() w/removed service\n service = %@", service
);
1282 _SC_crash_once("SCNetworkServiceRemove() w/removed service", NULL
, NULL
);
1283 _SCErrorSet(kSCStatusInvalidArgument
);
1287 // remove service from all sets
1289 sets
= SCNetworkSetCopyAll(servicePrivate
->prefs
);
1293 n
= CFArrayGetCount(sets
);
1294 for (CFIndex i
= 0; i
< n
; i
++) {
1295 SCNetworkSetRef set
;
1297 set
= CFArrayGetValueAtIndex(sets
, i
);
1298 ok
= SCNetworkSetRemoveService(set
, service
);
1299 if (!ok
&& (SCError() != kSCStatusNoKey
)) {
1309 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1310 servicePrivate
->serviceID
, // service
1312 ok
= SCPreferencesPathRemoveValue(servicePrivate
->prefs
, path
);
1316 SC_log(LOG_DEBUG
, "SCNetworkServiceRemove(): %@", service
);
1324 SCNetworkServiceRemoveProtocolType(SCNetworkServiceRef service
, CFStringRef protocolType
)
1326 CFDictionaryRef entity
;
1329 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1331 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1332 _SCErrorSet(kSCStatusInvalidArgument
);
1336 if (!__SCNetworkServiceExists(service
)) {
1337 SC_log(LOG_ERR
, "SCNetworkServiceRemoveProtocolType() w/removed service\n service = %@\n protocol = %@",
1340 _SC_crash_once("SCNetworkServiceRemoveProtocolType() w/removed service", NULL
, NULL
);
1341 _SCErrorSet(kSCStatusInvalidArgument
);
1345 if (!__SCNetworkProtocolIsValidType(protocolType
)) {
1346 _SCErrorSet(kSCStatusInvalidArgument
);
1350 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1351 servicePrivate
->serviceID
, // service
1352 protocolType
); // entity
1354 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1355 if (entity
== NULL
) {
1356 // if "protocol" does not exist
1357 _SCErrorSet(kSCStatusNoKey
);
1361 ok
= SCPreferencesPathRemoveValue(servicePrivate
->prefs
, path
);
1366 SC_log(LOG_DEBUG
, "SCNetworkServiceRemoveProtocolType(): %@, %@", service
, protocolType
);
1375 SCNetworkServiceSetEnabled(SCNetworkServiceRef service
, Boolean enabled
)
1379 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1381 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1382 _SCErrorSet(kSCStatusInvalidArgument
);
1386 if (!__SCNetworkServiceExists(service
)) {
1387 SC_log(LOG_ERR
, "SCNetworkServiceSetEnabled() w/removed service\n service = %@", service
);
1388 _SC_crash_once("SCNetworkProtocolSetEnabled() w/removed service", NULL
, NULL
);
1389 _SCErrorSet(kSCStatusInvalidArgument
);
1393 // make sure that we do not enable a network service if the
1394 // associated interface is a member of a bond or bridge.
1396 SCNetworkInterfaceRef interface
;
1398 interface
= SCNetworkServiceGetInterface(service
);
1399 if ((interface
!= NULL
) &&
1400 __SCNetworkInterfaceIsMember(servicePrivate
->prefs
, interface
)) {
1401 _SCErrorSet(kSCStatusKeyExists
);
1406 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1407 servicePrivate
->serviceID
, // service
1409 ok
= __setPrefsEnabled(servicePrivate
->prefs
, path
, enabled
);
1413 SC_log(LOG_DEBUG
, "SCNetworkServiceSetEnabled(): %@ -> %s",
1415 enabled
? "Enabled" : "Disabled");
1423 SCNetworkServiceSetName(SCNetworkServiceRef service
, CFStringRef name
)
1425 CFDictionaryRef entity
;
1428 CFStringRef saveName
= NULL
;
1429 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1431 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1432 _SCErrorSet(kSCStatusInvalidArgument
);
1436 if (!__SCNetworkServiceExists(service
)) {
1437 SC_log(LOG_ERR
, "SCNetworkServiceSetName() w/removed service\n service = %@\n name = %@",
1439 name
!= NULL
? name
: CFSTR("<NULL>"));
1440 _SC_crash_once("SCNetworkServiceSetName() w/removed service", NULL
, NULL
);
1441 _SCErrorSet(kSCStatusInvalidArgument
);
1446 if (!isA_CFString(name
)) {
1447 _SCErrorSet(kSCStatusInvalidArgument
);
1450 saveName
= CFRetain(name
);
1454 SCNetworkInterfaceRef interface
;
1456 interface
= SCNetworkServiceGetInterface(service
);
1457 while (interface
!= NULL
) {
1458 SCNetworkInterfaceRef childInterface
;
1460 childInterface
= SCNetworkInterfaceGetInterface(interface
);
1461 if (childInterface
== NULL
) {
1465 interface
= childInterface
;
1468 if (interface
!= NULL
) {
1469 CFStringRef interface_name
;
1471 interface_name
= SCNetworkInterfaceGetLocalizedDisplayName(interface
);
1472 if (interface_name
!= NULL
) {
1473 if (CFEqual(name
, interface_name
)) {
1474 // if service name matches the localized interface name
1475 // then store the non-localized name.
1476 interface_name
= __SCNetworkInterfaceGetNonLocalizedDisplayName(interface
);
1477 if (interface_name
!= NULL
) {
1478 CFRelease(saveName
);
1479 saveName
= CFRetain(interface_name
);
1481 } else if (CFStringHasPrefix(name
, interface_name
)) {
1482 CFIndex prefixLen
= CFStringGetLength(interface_name
);
1484 CFIndex suffixLen
= CFStringGetLength(name
);
1486 // if service name matches the localized interface name plus
1487 // a few extra characters) then store the non-localized name with
1489 suffix
= CFStringCreateWithSubstring(NULL
,
1491 CFRangeMake(prefixLen
, suffixLen
- prefixLen
));
1492 interface_name
= __SCNetworkInterfaceGetNonLocalizedDisplayName(interface
);
1493 if (interface_name
!= NULL
) {
1494 CFRelease(saveName
);
1495 saveName
= CFStringCreateWithFormat(NULL
,
1507 #define PREVENT_DUPLICATE_SERVICE_NAMES
1508 #ifdef PREVENT_DUPLICATE_SERVICE_NAMES
1512 // ensure that each service is uniquely named within its sets
1514 sets
= SCNetworkSetCopyAll(servicePrivate
->prefs
);
1519 set_count
= CFArrayGetCount(sets
);
1520 for (set_index
= 0; set_index
< set_count
; set_index
++) {
1521 CFIndex service_index
;
1522 Boolean isDup
= FALSE
;
1523 Boolean isMember
= FALSE
;
1524 CFIndex service_count
;
1525 CFArrayRef services
;
1526 SCNetworkSetRef set
= CFArrayGetValueAtIndex(sets
, set_index
);
1528 services
= SCNetworkSetCopyServices(set
);
1530 service_count
= CFArrayGetCount(services
);
1531 for (service_index
= 0; service_index
< service_count
; service_index
++) {
1532 CFStringRef otherID
;
1533 CFStringRef otherName
;
1534 SCNetworkServiceRef otherService
;
1536 otherService
= CFArrayGetValueAtIndex(services
, service_index
);
1538 otherID
= SCNetworkServiceGetServiceID(otherService
);
1539 if (CFEqual(servicePrivate
->serviceID
, otherID
)) {
1540 // if the service is a member of this set
1545 otherName
= SCNetworkServiceGetName(otherService
);
1546 if ((otherName
!= NULL
) && CFEqual(name
, otherName
)) {
1552 CFRelease(services
);
1554 if (isMember
&& isDup
) {
1556 * if this service is a member of the set and
1557 * the "name" is not unique.
1560 if (saveName
!= NULL
) CFRelease(saveName
);
1561 _SCErrorSet(kSCStatusKeyExists
);
1569 #endif /* PREVENT_DUPLICATE_SERVICE_NAMES */
1571 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1572 servicePrivate
->serviceID
, // service
1574 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1575 if (isA_CFDictionary(entity
) ||
1576 ((entity
== NULL
) && (name
!= NULL
))) {
1577 CFMutableDictionaryRef newEntity
;
1579 if (entity
!= NULL
) {
1580 newEntity
= CFDictionaryCreateMutableCopy(NULL
, 0, entity
);
1582 newEntity
= CFDictionaryCreateMutable(NULL
,
1584 &kCFTypeDictionaryKeyCallBacks
,
1585 &kCFTypeDictionaryValueCallBacks
);
1587 if (saveName
!= NULL
) {
1588 CFDictionarySetValue(newEntity
, kSCPropUserDefinedName
, saveName
);
1590 CFDictionaryRemoveValue(newEntity
, kSCPropUserDefinedName
);
1592 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, newEntity
);
1593 CFRelease(newEntity
);
1596 if (saveName
!= NULL
) CFRelease(saveName
);
1598 if (servicePrivate
->name
!= NULL
) CFRelease(servicePrivate
->name
);
1599 if (name
!= NULL
) CFRetain(name
);
1600 servicePrivate
->name
= name
;
1603 SC_log(LOG_DEBUG
, "SCNetworkServiceSetName(): %@", service
);
1611 #pragma mark SCNetworkService SPIs
1616 __SCNetworkServiceExists(SCNetworkServiceRef service
)
1618 CFDictionaryRef entity
;
1620 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1622 if (servicePrivate
->prefs
== NULL
) {
1627 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1628 servicePrivate
->serviceID
, // service
1629 kSCEntNetInterface
); // entity
1630 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1633 if (!isA_CFDictionary(entity
)) {
1634 // a "service" must have an "interface"
1642 SCNetworkServicePrimaryRank
1643 SCNetworkServiceGetPrimaryRank(SCNetworkServiceRef service
)
1645 CFDictionaryRef entity
;
1648 SCNetworkServicePrimaryRank rank
= kSCNetworkServicePrimaryRankDefault
;
1649 CFStringRef rankStr
= NULL
;
1650 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1652 if (!isA_SCNetworkService(service
)) {
1653 _SCErrorSet(kSCStatusInvalidArgument
);
1657 if (servicePrivate
->prefs
!= NULL
) {
1658 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
,
1659 servicePrivate
->serviceID
,
1661 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1663 if (isA_CFDictionary(entity
)) {
1664 rankStr
= CFDictionaryGetValue(entity
, kSCPropNetServicePrimaryRank
);
1665 ok
= __str_to_rank(rankStr
, &rank
);
1667 } else if (servicePrivate
->store
!= NULL
) {
1668 path
= SCDynamicStoreKeyCreateNetworkServiceEntity(NULL
,
1669 kSCDynamicStoreDomainState
,
1670 servicePrivate
->serviceID
,
1672 entity
= SCDynamicStoreCopyValue(servicePrivate
->store
, path
);
1674 if (entity
!= NULL
) {
1675 if (isA_CFDictionary(entity
)) {
1676 rankStr
= CFDictionaryGetValue(entity
, kSCPropNetServicePrimaryRank
);
1677 ok
= __str_to_rank(rankStr
, &rank
);
1682 _SCErrorSet(kSCStatusInvalidArgument
);
1687 rank
= kSCNetworkServicePrimaryRankDefault
;
1688 _SCErrorSet(kSCStatusInvalidArgument
);
1689 } else if (rank
== kSCNetworkServicePrimaryRankDefault
) {
1690 _SCErrorSet(kSCStatusOK
);
1698 SCNetworkServiceSetPrimaryRank(SCNetworkServiceRef service
,
1699 SCNetworkServicePrimaryRank newRank
)
1702 CFDictionaryRef entity
;
1703 CFMutableDictionaryRef newEntity
;
1704 CFStringRef path
= NULL
;
1705 CFStringRef rankStr
= NULL
;
1706 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1708 if (!isA_SCNetworkService(service
)) {
1709 _SCErrorSet(kSCStatusInvalidArgument
);
1713 if ((servicePrivate
->prefs
!= NULL
) && !__SCNetworkServiceExists(service
)) {
1714 SC_log(LOG_ERR
, "SCNetworkServiceSetPrimaryRank() w/removed\n service = %@", service
);
1715 _SC_crash_once("SCNetworkServiceSetPrimaryRank() w/removed service", NULL
, NULL
);
1716 _SCErrorSet(kSCStatusInvalidArgument
);
1720 ok
= __rank_to_str(newRank
, &rankStr
);
1722 _SCErrorSet(kSCStatusInvalidArgument
);
1726 if (servicePrivate
->prefs
!= NULL
) {
1728 case kSCNetworkServicePrimaryRankDefault
:
1729 case kSCNetworkServicePrimaryRankNever
:
1730 case kSCNetworkServicePrimaryRankScoped
:
1731 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
,
1732 servicePrivate
->serviceID
,
1734 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1735 if (entity
!= NULL
) {
1736 if (!isA_CFDictionary(entity
)) {
1738 _SCErrorSet(kSCStatusFailed
);
1741 newEntity
= CFDictionaryCreateMutableCopy(NULL
, 0, entity
);
1743 newEntity
= CFDictionaryCreateMutable(NULL
,
1745 &kCFTypeDictionaryKeyCallBacks
,
1746 &kCFTypeDictionaryValueCallBacks
);
1748 if (rankStr
!= NULL
) {
1749 CFDictionarySetValue(newEntity
, kSCPropNetServicePrimaryRank
, rankStr
);
1751 CFDictionaryRemoveValue(newEntity
, kSCPropNetServicePrimaryRank
);
1753 if (CFDictionaryGetCount(newEntity
) > 0) {
1754 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, newEntity
);
1756 ok
= SCPreferencesPathRemoveValue(servicePrivate
->prefs
, path
);
1758 CFRelease(newEntity
);
1764 _SCErrorSet(kSCStatusInvalidArgument
);
1767 } else if (servicePrivate
->store
!= NULL
) {
1768 path
= SCDynamicStoreKeyCreateNetworkServiceEntity(NULL
,
1769 kSCDynamicStoreDomainState
,
1770 servicePrivate
->serviceID
,
1772 entity
= SCDynamicStoreCopyValue(servicePrivate
->store
, path
);
1773 if (entity
!= NULL
) {
1774 if (!isA_CFDictionary(entity
)) {
1777 _SCErrorSet(kSCStatusFailed
);
1780 newEntity
= CFDictionaryCreateMutableCopy(NULL
, 0, entity
);
1783 newEntity
= CFDictionaryCreateMutable(NULL
,
1785 &kCFTypeDictionaryKeyCallBacks
,
1786 &kCFTypeDictionaryValueCallBacks
);
1788 if (rankStr
!= NULL
) {
1789 CFDictionarySetValue(newEntity
, kSCPropNetServicePrimaryRank
, rankStr
);
1791 CFDictionaryRemoveValue(newEntity
, kSCPropNetServicePrimaryRank
);
1793 if (CFDictionaryGetCount(newEntity
) > 0) {
1794 ok
= SCDynamicStoreSetValue(servicePrivate
->store
, path
, newEntity
);
1796 ok
= SCDynamicStoreRemoveValue(servicePrivate
->store
, path
);
1798 CFRelease(newEntity
);
1803 _SCErrorSet(kSCStatusInvalidArgument
);
1809 if (path
!= NULL
) CFRelease(path
);
1815 _SCNetworkServiceIsVPN(SCNetworkServiceRef service
)
1817 SCNetworkInterfaceRef interface
;
1818 CFStringRef interfaceType
;
1820 interface
= SCNetworkServiceGetInterface(service
);
1821 if (interface
== NULL
) {
1825 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
1826 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
)) {
1827 interface
= SCNetworkInterfaceGetInterface(interface
);
1828 if (interface
== NULL
) {
1832 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
1833 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeL2TP
)) {
1836 #pragma GCC diagnostic push
1837 #pragma GCC diagnostic ignored "-Wdeprecated"
1838 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPTP
)) {
1841 #pragma GCC diagnostic pop
1842 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeVPN
)) {
1844 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeIPSec
)) {
1853 SCNetworkServiceSetExternalID(SCNetworkServiceRef service
, CFStringRef identifierDomain
, CFStringRef identifier
)
1855 CFStringRef prefs_path
;
1856 CFDictionaryRef service_dictionary
;
1857 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1858 Boolean success
= FALSE
;
1859 CFStringRef prefixed_domain
;
1861 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
) || !isA_CFString(identifierDomain
)) {
1862 _SCErrorSet(kSCStatusInvalidArgument
);
1866 if (!__SCNetworkServiceExists(service
)) {
1867 SC_log(LOG_ERR
, "SCNetworkServiceSetExternalID() w/removed\n service = %@\n id = %@",
1870 _SC_crash_once("SCNetworkServiceSetExternalID() w/removed service", NULL
, NULL
);
1871 _SCErrorSet(kSCStatusInvalidArgument
);
1875 if (identifier
!= NULL
&& !isA_CFString(identifier
)) {
1876 _SCErrorSet(kSCStatusInvalidArgument
);
1880 prefixed_domain
= CFStringCreateWithFormat(NULL
, 0, CFSTR("%s%@"), EXTERNAL_ID_DOMAIN_PREFIX
, identifierDomain
);
1882 prefs_path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
,
1883 servicePrivate
->serviceID
,
1886 service_dictionary
= SCPreferencesPathGetValue(servicePrivate
->prefs
, prefs_path
);
1887 if (isA_CFDictionary(service_dictionary
) || ((service_dictionary
== NULL
) && (identifier
!= NULL
))) {
1888 CFMutableDictionaryRef new_service_dictionary
;
1890 if (service_dictionary
!= NULL
) {
1891 new_service_dictionary
= CFDictionaryCreateMutableCopy(NULL
, 0, service_dictionary
);
1893 new_service_dictionary
= CFDictionaryCreateMutable(NULL
,
1895 &kCFTypeDictionaryKeyCallBacks
,
1896 &kCFTypeDictionaryValueCallBacks
);
1899 if (identifier
!= NULL
) {
1900 CFDictionarySetValue(new_service_dictionary
, prefixed_domain
, identifier
);
1902 CFDictionaryRemoveValue(new_service_dictionary
, prefixed_domain
);
1904 success
= SCPreferencesPathSetValue(servicePrivate
->prefs
, prefs_path
, new_service_dictionary
);
1905 CFRelease(new_service_dictionary
);
1907 CFRelease(prefs_path
);
1909 if (identifier
!= NULL
) {
1910 if (servicePrivate
->externalIDs
== NULL
) {
1911 servicePrivate
->externalIDs
= CFDictionaryCreateMutable(NULL
,
1913 &kCFTypeDictionaryKeyCallBacks
,
1914 &kCFTypeDictionaryValueCallBacks
);
1916 CFDictionarySetValue(servicePrivate
->externalIDs
, prefixed_domain
, identifier
);
1918 if (servicePrivate
->externalIDs
!= NULL
) {
1919 CFDictionaryRemoveValue(servicePrivate
->externalIDs
, prefixed_domain
);
1923 CFRelease(prefixed_domain
);
1926 _SCErrorSet(kSCStatusFailed
);
1934 SCNetworkServiceCopyExternalID(SCNetworkServiceRef service
, CFStringRef identifierDomain
)
1936 CFStringRef identifier
= NULL
;
1937 CFStringRef prefixed_domain
;
1938 SCNetworkServicePrivateRef service_private
= (SCNetworkServicePrivateRef
)service
;
1940 if (!isA_SCNetworkService(service
) || (service_private
->prefs
== NULL
) || !isA_CFString(identifierDomain
)) {
1941 _SCErrorSet(kSCStatusInvalidArgument
);
1945 prefixed_domain
= CFStringCreateWithFormat(NULL
, 0, CFSTR("%s%@"), EXTERNAL_ID_DOMAIN_PREFIX
, identifierDomain
);
1947 if (service_private
->externalIDs
!= NULL
) {
1948 identifier
= CFDictionaryGetValue(service_private
->externalIDs
, prefixed_domain
);
1949 if (identifier
!= NULL
) {
1950 CFRetain(identifier
);
1954 if (identifier
== NULL
) {
1955 CFStringRef prefs_path
;
1956 CFDictionaryRef service_dictionary
;
1958 prefs_path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
,
1959 service_private
->serviceID
,
1962 service_dictionary
= SCPreferencesPathGetValue(service_private
->prefs
, prefs_path
);
1963 if (isA_CFDictionary(service_dictionary
)) {
1964 identifier
= CFDictionaryGetValue(service_dictionary
, prefixed_domain
);
1965 if (identifier
!= NULL
) {
1966 CFRetain(identifier
);
1967 if (service_private
->externalIDs
== NULL
) {
1968 service_private
->externalIDs
= CFDictionaryCreateMutable(NULL
,
1970 &kCFTypeDictionaryKeyCallBacks
,
1971 &kCFTypeDictionaryValueCallBacks
);
1973 CFDictionarySetValue(service_private
->externalIDs
, prefixed_domain
, identifier
);
1976 CFRelease(prefs_path
);
1979 CFRelease(prefixed_domain
);
1981 if (identifier
== NULL
) {
1982 _SCErrorSet(kSCStatusNoKey
);
1990 CFStringRef oldServiceID
;
1991 CFStringRef newServiceID
;
1992 } serviceContext
, *serviceContextRef
;
1996 replaceServiceID(const void *value
, void *context
)
1998 CFStringRef link
= NULL
;
1999 CFStringRef oldLink
;
2000 CFMutableArrayRef newServiceOrder
;
2002 serviceContextRef service_context
= (serviceContextRef
)context
;
2003 CFArrayRef serviceOrder
= NULL
;
2004 SCNetworkSetRef set
= (SCNetworkSetRef
)value
;
2005 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
2007 // update service order
2008 serviceOrder
= SCNetworkSetGetServiceOrder(set
);
2009 if ((isA_CFArray(serviceOrder
) != NULL
) &&
2010 CFArrayContainsValue(serviceOrder
,
2011 CFRangeMake(0, CFArrayGetCount(serviceOrder
)),
2012 service_context
->oldServiceID
)) {
2014 CFIndex serviceOrderIndex
;
2016 // replacing all instances of old service ID with new one
2017 newServiceOrder
= CFArrayCreateMutableCopy(NULL
, 0, serviceOrder
);
2018 count
= CFArrayGetCount(newServiceOrder
);
2019 for (serviceOrderIndex
= 0; serviceOrderIndex
< count
; serviceOrderIndex
++) {
2020 CFStringRef serviceID
;
2022 serviceID
= CFArrayGetValueAtIndex(newServiceOrder
, serviceOrderIndex
);
2023 if (CFEqual(serviceID
, service_context
->oldServiceID
)) {
2024 CFArraySetValueAtIndex(newServiceOrder
, serviceOrderIndex
, service_context
->newServiceID
);
2027 SCNetworkSetSetServiceOrder(set
, newServiceOrder
);
2028 CFRelease(newServiceOrder
);
2031 // check if service with old serviceID is part of the set
2032 path
= SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL
, // allocator
2033 setPrivate
->setID
, // set
2034 service_context
->oldServiceID
, // service
2036 oldLink
= SCPreferencesPathGetLink(setPrivate
->prefs
, path
);
2037 if (oldLink
== NULL
) {
2038 // don't make any changes if service with old serviceID is not found
2042 // remove link between "set" and old "service"
2043 (void) SCPreferencesPathRemoveValue(setPrivate
->prefs
, path
);
2046 // create the link between "set" and the "service"
2047 path
= SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL
, // allocator
2048 setPrivate
->setID
, // set
2049 service_context
->newServiceID
, // service
2051 link
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
2052 service_context
->newServiceID
, // service
2054 (void) SCPreferencesPathSetLink(setPrivate
->prefs
, path
, link
);
2070 _SCNetworkServiceSetServiceID(SCNetworkServiceRef service
, CFStringRef newServiceID
)
2072 CFArrayRef allSets
= NULL
;
2073 CFDictionaryRef entity
;
2074 CFStringRef newPath
;
2076 CFStringRef oldPath
= NULL
;
2077 serviceContext service_context
;
2078 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
2080 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
2081 _SCErrorSet(kSCStatusInvalidArgument
);
2085 if (!isA_CFString(newServiceID
)) {
2086 _SCErrorSet(kSCStatusInvalidArgument
);
2090 if (CFEqual(newServiceID
, servicePrivate
->serviceID
)) {
2091 // no work needs to be done if new service ID is equal to current service ID
2095 if (!__SCNetworkServiceExists(service
)) {
2096 SC_log(LOG_ERR
, "_SCNetworkServiceSetServiceID() w/removed service\n service = %@\n serviceID = %@",
2099 _SC_crash_once("_SCNetworkServiceSetServiceID() w/removed service", NULL
, NULL
);
2100 _SCErrorSet(kSCStatusInvalidArgument
);
2104 newPath
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
2105 newServiceID
, // service
2107 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, newPath
);
2108 if (isA_CFDictionary(entity
)) {
2109 // if the new service already exists
2110 _SCErrorSet(kSCStatusKeyExists
);
2114 oldPath
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
2115 servicePrivate
->serviceID
, // service
2117 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, oldPath
);
2118 if (!isA_CFDictionary(entity
)) {
2119 // if the service has already been removed
2120 _SCErrorSet(kSCStatusNoKey
);
2124 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, newPath
, entity
);
2127 ok
= SCPreferencesPathRemoveValue(servicePrivate
->prefs
, oldPath
);
2130 allSets
= SCNetworkSetCopyAll(servicePrivate
->prefs
);
2132 service_context
.newServiceID
= newServiceID
;
2133 service_context
.oldServiceID
= servicePrivate
->serviceID
;
2135 // find all sets w/oldServiceID and update
2136 // ... and update the serviceOrder
2137 CFArrayApplyFunction(allSets
,
2138 CFRangeMake(0, CFArrayGetCount(allSets
)),
2142 if (servicePrivate
->interface
!= NULL
) {
2143 SCNetworkInterfaceRef newInterface
;
2145 // duplicate the interface and associate the copy with the new service ID
2146 newInterface
= (SCNetworkInterfaceRef
)__SCNetworkInterfaceCreateCopy(NULL
,
2147 servicePrivate
->interface
,
2148 servicePrivate
->prefs
,
2150 CFRelease(servicePrivate
->interface
);
2151 servicePrivate
->interface
= newInterface
;
2154 SC_log(LOG_DEBUG
, "_SCNetworkServiceSetServiceID(): %@ --> %@", service
, newServiceID
);
2156 // replace serviceID with new one
2157 CFRetain(newServiceID
);
2158 CFRelease(servicePrivate
->serviceID
);
2159 servicePrivate
->serviceID
= newServiceID
;
2163 if (oldPath
!= NULL
) {
2166 if (newPath
!= NULL
) {
2169 if (allSets
!= NULL
) {
2176 #define kVPNProtocolPayloadInfo CFSTR("com.apple.payload")
2177 #define kSCEntNetLoginWindowEAPOL CFSTR("EAPOL.LoginWindow")
2180 copyInterfaceConfiguration(SCNetworkServiceRef oldService
, SCNetworkServiceRef newService
)
2182 SCNetworkInterfaceRef oldInterface
;
2183 SCNetworkInterfaceRef newInterface
;
2185 oldInterface
= SCNetworkServiceGetInterface(oldService
);
2186 newInterface
= SCNetworkServiceGetInterface(newService
);
2188 while (oldInterface
!= NULL
) {
2189 CFDictionaryRef configuration
;
2190 CFStringRef interfaceType
;
2192 if (newInterface
== NULL
) {
2193 // oops ... interface layering does not match
2197 // copy interface configuration
2198 configuration
= SCNetworkInterfaceGetConfiguration(oldInterface
);
2200 if ((configuration
!= NULL
) ||
2201 (SCError() == kSCStatusOK
)) {
2202 if (!SCNetworkInterfaceSetConfiguration(newInterface
, configuration
)) {
2203 SC_log(LOG_INFO
, "problem setting interface configuration");
2208 // special case: PPP/L2TP + IPSec
2209 interfaceType
= SCNetworkInterfaceGetInterfaceType(oldInterface
);
2210 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
)) {
2211 SCNetworkInterfaceRef childInterface
;
2213 childInterface
= SCNetworkInterfaceGetInterface(oldInterface
);
2214 if (childInterface
!= NULL
) {
2215 CFStringRef childInterfaceType
;
2217 childInterfaceType
= SCNetworkInterfaceGetInterfaceType(childInterface
);
2219 if (CFEqual(childInterfaceType
, kSCNetworkInterfaceTypeL2TP
)) {
2220 configuration
= SCNetworkInterfaceGetExtendedConfiguration(oldInterface
, kSCEntNetIPSec
);
2221 if ((configuration
!= NULL
) ||
2222 (SCError() == kSCStatusOK
)) {
2223 if (!SCNetworkInterfaceSetExtendedConfiguration(newInterface
, kSCEntNetIPSec
, configuration
)) {
2224 SC_log(LOG_INFO
, "problem setting child interface configuration");
2231 // special case: 802.1x
2232 configuration
= SCNetworkInterfaceGetExtendedConfiguration(oldInterface
, kSCEntNetEAPOL
);
2233 if ((configuration
!= NULL
) ||
2234 (SCError() == kSCStatusOK
)) {
2235 (void) SCNetworkInterfaceSetExtendedConfiguration(newInterface
, kSCEntNetEAPOL
, configuration
);
2238 // special case: Managed Client
2239 configuration
= SCNetworkInterfaceGetExtendedConfiguration(oldInterface
, kVPNProtocolPayloadInfo
);
2240 if ((configuration
!= NULL
) ||
2241 (SCError() == kSCStatusOK
)) {
2242 (void) SCNetworkInterfaceSetExtendedConfiguration(newInterface
, kVPNProtocolPayloadInfo
, configuration
);
2245 // special case: Network Pref
2246 configuration
= SCNetworkInterfaceGetExtendedConfiguration(oldInterface
, kSCValNetPPPAuthProtocolEAP
);
2247 if ((configuration
!= NULL
) ||
2248 (SCError() == kSCStatusOK
)) {
2249 (void) SCNetworkInterfaceSetExtendedConfiguration(newInterface
, kSCValNetPPPAuthProtocolEAP
, configuration
);
2252 // special case: Remote Pref
2253 configuration
= SCNetworkInterfaceGetExtendedConfiguration(oldInterface
, kSCEntNetLoginWindowEAPOL
);
2254 if ((configuration
!= NULL
) ||
2255 (SCError() == kSCStatusOK
)) {
2256 (void) SCNetworkInterfaceSetExtendedConfiguration(newInterface
, kSCEntNetLoginWindowEAPOL
, configuration
);
2259 // special case: Network Extension
2260 configuration
= SCNetworkInterfaceGetExtendedConfiguration(oldInterface
, kSCNetworkInterfaceTypeIPSec
);
2261 if ((configuration
!= NULL
) ||
2262 (SCError() == kSCStatusOK
)) {
2263 (void) SCNetworkInterfaceSetExtendedConfiguration(newInterface
, kSCNetworkInterfaceTypeIPSec
, configuration
);
2266 oldInterface
= SCNetworkInterfaceGetInterface(oldInterface
);
2267 newInterface
= SCNetworkInterfaceGetInterface(newInterface
);
2275 __SCNetworkServiceAddProtocolToService(SCNetworkServiceRef service
, CFStringRef protocolType
, CFDictionaryRef configuration
, Boolean enabled
)
2278 SCNetworkProtocolRef protocol
;
2280 protocol
= SCNetworkServiceCopyProtocol(service
, protocolType
);
2282 if ((protocol
== NULL
) &&
2283 (SCError() == kSCStatusNoKey
)) {
2284 ok
= SCNetworkServiceAddProtocolType(service
, protocolType
);
2286 protocol
= SCNetworkServiceCopyProtocol(service
, protocolType
);
2289 if (protocol
!= NULL
) {
2290 SCNetworkProtocolSetConfiguration(protocol
, configuration
);
2291 SCNetworkProtocolSetEnabled(protocol
, enabled
);
2292 CFRelease(protocol
);
2301 __SCNetworkServiceMigrateNew(SCPreferencesRef prefs
,
2302 SCNetworkServiceRef service
,
2303 CFDictionaryRef bsdMapping
,
2304 CFDictionaryRef setMapping
,
2305 CFDictionaryRef serviceSetMapping
)
2307 CFStringRef deviceName
= NULL
;
2309 SCNetworkInterfaceRef interface
= NULL
;
2310 CFDictionaryRef interfaceEntity
= NULL
;
2311 CFMutableDictionaryRef interfaceEntityMutable
= NULL
;
2312 SCNetworkSetRef newSet
= NULL
;
2313 SCPreferencesRef ni_prefs
= NULL
;
2314 SCNetworkInterfaceRef ni_interface
= NULL
;
2315 SCNetworkInterfaceRef oldInterface
= NULL
;
2316 SCNetworkSetRef oldSet
= NULL
;
2317 SCNetworkServiceRef newService
= NULL
;
2318 CFStringRef serviceID
= NULL
;
2319 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
) service
;
2320 CFArrayRef setList
= NULL
;
2321 Boolean success
= FALSE
;
2322 CFStringRef targetDeviceName
= NULL
;
2323 CFStringRef userDefinedName
= NULL
;
2324 CFStringRef userDefinedNameInterface
= NULL
;
2325 CFArrayRef protocols
= NULL
;
2326 CFStringRef subType
;
2328 if ((isA_SCNetworkService(service
) == NULL
) ||
2329 (isA_SCNetworkInterface(servicePrivate
->interface
) == NULL
) ||
2330 (servicePrivate
->prefs
== NULL
)) {
2333 serviceID
= servicePrivate
->serviceID
;
2335 newService
= SCNetworkServiceCopy(prefs
, serviceID
);
2336 if (newService
!= NULL
) {
2337 // Cannot add service if it already exists
2338 SC_log(LOG_INFO
, "Service already exists");
2342 oldInterface
= SCNetworkServiceGetInterface(service
);
2343 interfaceEntity
= __SCNetworkInterfaceCopyInterfaceEntity(oldInterface
);
2344 if (interfaceEntity
== NULL
) {
2345 SC_log(LOG_INFO
, "No interface entity");
2348 interfaceEntityMutable
= CFDictionaryCreateMutableCopy(NULL
, 0, interfaceEntity
);
2350 if (isA_CFDictionary(bsdMapping
) != NULL
) {
2351 deviceName
= CFDictionaryGetValue(interfaceEntityMutable
, kSCPropNetInterfaceDeviceName
);
2352 if (isA_CFString(deviceName
) != NULL
) {
2353 targetDeviceName
= CFDictionaryGetValue(bsdMapping
, deviceName
);
2354 if (targetDeviceName
!= NULL
) {
2356 CFDictionarySetValue(interfaceEntityMutable
, kSCPropNetInterfaceDeviceName
, targetDeviceName
);
2357 ni_prefs
= __SCPreferencesCreateNIPrefsFromPrefs(prefs
);
2358 ni_interface
= __SCNetworkInterfaceCreateWithNIPreferencesUsingBSDName(NULL
, ni_prefs
, targetDeviceName
);
2359 if (ni_interface
!= NULL
) {
2360 userDefinedNameInterface
= __SCNetworkInterfaceGetUserDefinedName(ni_interface
);
2364 if (userDefinedNameInterface
== NULL
) {
2365 userDefinedNameInterface
= CFDictionaryGetValue(interfaceEntityMutable
, kSCPropUserDefinedName
);
2368 subType
= CFDictionaryGetValue(interfaceEntityMutable
, kSCPropNetInterfaceSubType
);
2369 interface
= _SCNetworkInterfaceCreateWithEntity(NULL
, interfaceEntityMutable
, NULL
);
2370 if (userDefinedNameInterface
!= NULL
) {
2371 __SCNetworkInterfaceSetUserDefinedName(interface
, userDefinedNameInterface
);
2373 // Supporting PPPoE subtype
2374 if (subType
!= NULL
&&
2375 CFEqual(subType
, kSCValNetInterfaceSubTypePPPoE
)) {
2376 SCNetworkInterfaceRef childInterface
= SCNetworkInterfaceGetInterface(interface
);
2377 if (childInterface
!= NULL
) {
2378 __SCNetworkInterfaceSetUserDefinedName(childInterface
, userDefinedNameInterface
);
2381 newService
= SCNetworkServiceCreate(prefs
, interface
);
2382 if (newService
== NULL
) {
2383 SC_log(LOG_INFO
, "SCNetworkServiceCreate() failed");
2387 enabled
= SCNetworkServiceGetEnabled(service
);
2388 if (!SCNetworkServiceSetEnabled(newService
, enabled
)) {
2389 SCNetworkServiceRemove(newService
);
2390 SC_log(LOG_INFO
, "SCNetworkServiceSetEnabled() failed");
2394 if (!SCNetworkServiceEstablishDefaultConfiguration(newService
)) {
2395 SCNetworkServiceRemove(newService
);
2396 SC_log(LOG_INFO
, "SCNetworkServiceEstablishDefaultConfiguration() failed");
2401 _SCNetworkServiceSetServiceID(newService
, serviceID
);
2403 userDefinedName
= SCNetworkServiceGetName(service
);
2404 if ((userDefinedName
!= NULL
) &&
2405 !SCNetworkServiceSetName(newService
, userDefinedName
)) {
2406 SC_log(LOG_INFO
, "SCNetworkServiceSetName(, %@) failed", userDefinedName
);
2409 // Determine which sets to add service
2410 if (setMapping
!= NULL
&&
2411 serviceSetMapping
!= NULL
) {
2412 setList
= CFDictionaryGetValue(serviceSetMapping
, service
);
2413 if (setList
!= NULL
) {
2414 for (CFIndex idx
= 0; idx
< CFArrayGetCount(setList
); idx
++) {
2415 oldSet
= CFArrayGetValueAtIndex(setList
, idx
);
2416 newSet
= CFDictionaryGetValue(setMapping
, oldSet
);
2417 if (newSet
== NULL
) {
2421 if (!SCNetworkSetAddService(newSet
, newService
)) {
2422 SC_log(LOG_INFO
, "SCNetworkSetAddService() failed");
2428 protocols
= SCNetworkServiceCopyProtocols(service
);
2429 if (protocols
!= NULL
) {
2431 for (CFIndex idx
= 0; idx
< CFArrayGetCount(protocols
); idx
++) {
2432 SCNetworkProtocolRef protocol
= CFArrayGetValueAtIndex(protocols
, idx
);
2433 CFDictionaryRef configuration
= SCNetworkProtocolGetConfiguration(protocol
);
2434 CFStringRef protocolType
= SCNetworkProtocolGetProtocolType(protocol
);
2435 enabled
= SCNetworkProtocolGetEnabled(protocol
);
2436 __SCNetworkServiceAddProtocolToService(newService
, protocolType
, configuration
, enabled
);
2438 CFRelease(protocols
);
2441 copyInterfaceConfiguration(service
, newService
);
2445 if (interface
!= NULL
) {
2446 CFRelease(interface
);
2448 if (interfaceEntity
!= NULL
) {
2449 CFRelease(interfaceEntity
);
2451 if (interfaceEntityMutable
!= NULL
) {
2452 CFRelease(interfaceEntityMutable
);
2454 if (newService
!= NULL
) {
2455 CFRelease(newService
);
2457 if (ni_prefs
!= NULL
) {
2458 CFRelease(ni_prefs
);
2460 if (ni_interface
!= NULL
) {
2461 CFRelease(ni_interface
);
2469 __SCNetworkServiceCreate(SCPreferencesRef prefs
,
2470 SCNetworkInterfaceRef interface
,
2471 CFStringRef userDefinedName
)
2473 SCNetworkSetRef currentSet
= NULL
;
2475 SCNetworkServiceRef service
= NULL
;
2477 if (interface
== NULL
) {
2481 if (userDefinedName
== NULL
) {
2482 userDefinedName
= __SCNetworkInterfaceGetUserDefinedName(interface
);
2483 if (userDefinedName
== NULL
) {
2484 SC_log(LOG_INFO
, "No userDefinedName");
2488 service
= SCNetworkServiceCreate(prefs
, interface
);
2489 if (service
== NULL
) {
2490 SC_log(LOG_INFO
, "SCNetworkServiceCreate() failed: %s", SCErrorString(SCError()));
2492 ok
= SCNetworkServiceSetName(service
, userDefinedName
);
2494 SC_log(LOG_INFO
, "SCNetworkServiceSetName() failed: %s", SCErrorString(SCError()));
2495 SCNetworkServiceRemove(service
);
2499 ok
= SCNetworkServiceEstablishDefaultConfiguration(service
);
2501 SC_log(LOG_INFO
, "SCNetworkServiceEstablishDefaultConfiguration() failed: %s", SCErrorString(SCError()));
2502 SCNetworkServiceRemove(service
);
2506 currentSet
= SCNetworkSetCopyCurrent(prefs
);
2507 if (currentSet
== NULL
) {
2508 SC_log(LOG_INFO
, "No current set");
2509 if (service
!= NULL
) {
2510 SCNetworkServiceRemove(service
);
2514 if (service
!= NULL
) {
2515 ok
= SCNetworkSetAddService(currentSet
, service
);
2517 SC_log(LOG_INFO
, "Could not add service to the current set");
2518 SCNetworkServiceRemove(service
);
2524 if (service
!= NULL
) {
2527 if (currentSet
!= NULL
) {
2528 CFRelease(currentSet
);
2533 __private_extern__ Boolean
2534 __SCNetworkServiceIsPPTP(SCNetworkServiceRef service
)
2536 CFStringRef intfSubtype
;
2537 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
2539 if (servicePrivate
== NULL
|| servicePrivate
->interface
== NULL
) {
2543 intfSubtype
= __SCNetworkInterfaceGetEntitySubType(servicePrivate
->interface
);
2544 if (intfSubtype
== NULL
) {
2548 #pragma GCC diagnostic push
2549 #pragma GCC diagnostic ignored "-Wdeprecated"
2550 if (CFEqual(intfSubtype
, kSCValNetInterfaceSubTypePPTP
)) {
2553 #pragma GCC diagnostic pop