2 * Copyright (c) 2004-2020 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"
40 #include <CommonCrypto/CommonDigest.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 SCNetworkServiceRef service
= (SCNetworkServiceRef
)cf
;
75 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
77 result
= CFStringCreateMutable(allocator
, 0);
78 CFStringAppendFormat(result
, NULL
, CFSTR("<SCNetworkService %p [%p]> {"), service
, allocator
);
79 CFStringAppendFormat(result
, NULL
, CFSTR("id = %@"), servicePrivate
->serviceID
);
80 if (servicePrivate
->prefs
!= NULL
) {
81 CFStringAppendFormat(result
, NULL
, CFSTR(", prefs = %p"), servicePrivate
->prefs
);
82 } else if (servicePrivate
->store
!= NULL
) {
83 CFStringAppendFormat(result
, NULL
, CFSTR(", store = %p"), servicePrivate
->store
);
85 if (servicePrivate
->name
!= NULL
) {
86 CFStringAppendFormat(result
, NULL
, CFSTR(", name = %@"), servicePrivate
->name
);
88 if (!__SCNetworkServiceExists(service
)) {
89 CFStringAppendFormat(result
, NULL
, CFSTR(", REMOVED"));
91 CFStringAppendFormat(result
, NULL
, CFSTR("}"));
98 __SCNetworkServiceDeallocate(CFTypeRef cf
)
100 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)cf
;
102 /* release resources */
104 CFRelease(servicePrivate
->serviceID
);
105 if (servicePrivate
->interface
!= NULL
) CFRelease(servicePrivate
->interface
);
106 if (servicePrivate
->prefs
!= NULL
) CFRelease(servicePrivate
->prefs
);
107 if (servicePrivate
->store
!= NULL
) CFRelease(servicePrivate
->store
);
108 if (servicePrivate
->name
!= NULL
) CFRelease(servicePrivate
->name
);
109 if (servicePrivate
->externalIDs
!= NULL
) CFRelease(servicePrivate
->externalIDs
);
116 __SCNetworkServiceEqual(CFTypeRef cf1
, CFTypeRef cf2
)
118 SCNetworkServicePrivateRef s1
= (SCNetworkServicePrivateRef
)cf1
;
119 SCNetworkServicePrivateRef s2
= (SCNetworkServicePrivateRef
)cf2
;
124 if (s1
->prefs
!= s2
->prefs
)
125 return FALSE
; // if not the same prefs
127 if (!CFEqual(s1
->serviceID
, s2
->serviceID
))
128 return FALSE
; // if not the same service identifier
135 __SCNetworkServiceHash(CFTypeRef cf
)
137 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)cf
;
139 return CFHash(servicePrivate
->serviceID
);
144 __SCNetworkServiceInitialize(void)
146 __kSCNetworkServiceTypeID
= _CFRuntimeRegisterClass(&__SCNetworkServiceClass
);
151 __private_extern__ SCNetworkServicePrivateRef
152 __SCNetworkServiceCreatePrivate(CFAllocatorRef allocator
,
153 SCPreferencesRef prefs
,
154 CFStringRef serviceID
,
155 SCNetworkInterfaceRef interface
)
157 SCNetworkServicePrivateRef servicePrivate
;
160 /* initialize runtime */
161 pthread_once(&initialized
, __SCNetworkServiceInitialize
);
163 /* allocate target */
164 size
= sizeof(SCNetworkServicePrivate
) - sizeof(CFRuntimeBase
);
165 servicePrivate
= (SCNetworkServicePrivateRef
)_CFRuntimeCreateInstance(allocator
,
166 __kSCNetworkServiceTypeID
,
169 if (servicePrivate
== NULL
) {
173 /* initialize non-zero/NULL members */
174 servicePrivate
->prefs
= (prefs
!= NULL
) ? CFRetain(prefs
): NULL
;
175 servicePrivate
->serviceID
= CFStringCreateCopy(NULL
, serviceID
);
176 servicePrivate
->interface
= (interface
!= NULL
) ? CFRetain(interface
) : NULL
;
178 return servicePrivate
;
183 #pragma mark Service ordering
187 _SCNetworkServiceCompare(const void *val1
, const void *val2
, void *context
)
191 CFArrayRef order
= (CFArrayRef
)context
;
192 SCNetworkServiceRef s1
= (SCNetworkServiceRef
)val1
;
193 SCNetworkServiceRef s2
= (SCNetworkServiceRef
)val2
;
195 id1
= SCNetworkServiceGetServiceID(s1
);
196 id2
= SCNetworkServiceGetServiceID(s2
);
203 range
= CFRangeMake(0, CFArrayGetCount(order
));
204 o1
= CFArrayGetFirstIndexOfValue(order
, range
, id1
);
205 o2
= CFArrayGetFirstIndexOfValue(order
, range
, id2
);
208 return (o2
!= kCFNotFound
) ? kCFCompareGreaterThan
: kCFCompareLessThan
;
209 } else if (o1
< o2
) {
210 return (o1
!= kCFNotFound
) ? kCFCompareLessThan
: kCFCompareGreaterThan
;
214 return CFStringCompare(id1
, id2
, 0);
219 #pragma mark SCNetworkService APIs
225 __private_extern__ CFArrayRef
/* of SCNetworkServiceRef's */
226 __SCNetworkServiceCopyAllEnabled(SCPreferencesRef prefs
)
228 CFMutableArrayRef array
= NULL
;
233 sets
= SCNetworkSetCopyAll(prefs
);
238 n_sets
= CFArrayGetCount(sets
);
239 for (i_sets
= 0; i_sets
< n_sets
; i_sets
++) {
245 set
= CFArrayGetValueAtIndex(sets
, i_sets
);
246 services
= SCNetworkSetCopyServices(set
);
247 if (services
== NULL
) {
251 n_services
= CFArrayGetCount(services
);
252 for (i_services
= 0; i_services
< n_services
; i_services
++) {
253 SCNetworkServiceRef service
;
255 service
= CFArrayGetValueAtIndex(services
, i_services
);
256 if (!SCNetworkServiceGetEnabled(service
)) {
261 if ((array
== NULL
) ||
262 !CFArrayContainsValue(array
,
263 CFRangeMake(0, CFArrayGetCount(array
)),
266 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
268 CFArrayAppendValue(array
, service
);
279 __private_extern__ Boolean
280 __SCNetworkServiceExistsForInterface(CFArrayRef services
, SCNetworkInterfaceRef interface
)
285 n
= isA_CFArray(services
) ? CFArrayGetCount(services
) : 0;
286 for (i
= 0; i
< n
; i
++) {
287 SCNetworkServiceRef service
;
288 SCNetworkInterfaceRef service_interface
;
290 service
= CFArrayGetValueAtIndex(services
, i
);
292 service_interface
= SCNetworkServiceGetInterface(service
);
293 while (service_interface
!= NULL
) {
294 if (CFEqual(interface
, service_interface
)) {
298 service_interface
= SCNetworkInterfaceGetInterface(service_interface
);
307 mergeDict(const void *key
, const void *value
, void *context
)
309 CFMutableDictionaryRef newDict
= (CFMutableDictionaryRef
)context
;
311 CFDictionarySetValue(newDict
, key
, value
);
316 static CF_RETURNS_RETAINED CFDictionaryRef
317 _protocolTemplate(SCNetworkServiceRef service
, CFStringRef protocolType
)
319 SCNetworkInterfaceRef interface
;
320 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
321 CFDictionaryRef
template = NULL
;
323 interface
= servicePrivate
->interface
;
324 if (interface
!= NULL
) {
325 SCNetworkInterfaceRef childInterface
;
326 CFStringRef childInterfaceType
= NULL
;
327 CFStringRef interfaceType
;
330 interfaceType
= SCNetworkInterfaceGetInterfaceType(servicePrivate
->interface
);
331 childInterface
= SCNetworkInterfaceGetInterface(servicePrivate
->interface
);
332 if (childInterface
!= NULL
) {
333 childInterfaceType
= SCNetworkInterfaceGetInterfaceType(childInterface
);
336 template = __copyProtocolTemplate(interfaceType
, childInterfaceType
, protocolType
);
337 if (template != NULL
) {
338 CFDictionaryRef overrides
;
340 // move to the interface at the lowest layer
341 while (childInterface
!= NULL
) {
342 interface
= childInterface
;
343 childInterface
= SCNetworkInterfaceGetInterface(interface
);
346 overrides
= __SCNetworkInterfaceGetTemplateOverrides(interface
, protocolType
);
347 if (isA_CFDictionary(overrides
)) {
348 CFMutableDictionaryRef newTemplate
;
350 newTemplate
= CFDictionaryCreateMutableCopy(NULL
, 0, template);
351 CFDictionaryApplyFunction(overrides
, mergeDict
, newTemplate
);
353 template = newTemplate
;
358 if (template == NULL
) {
359 template = CFDictionaryCreate(NULL
,
363 &kCFTypeDictionaryKeyCallBacks
,
364 &kCFTypeDictionaryValueCallBacks
);
372 SCNetworkServiceAddProtocolType(SCNetworkServiceRef service
, CFStringRef protocolType
)
374 CFDictionaryRef entity
;
376 CFDictionaryRef newEntity
= NULL
;
379 SCNetworkProtocolRef protocol
= NULL
;
380 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
382 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
383 _SCErrorSet(kSCStatusInvalidArgument
);
387 if (!__SCNetworkProtocolIsValidType(protocolType
)) {
388 _SCErrorSet(kSCStatusInvalidArgument
);
392 if (!__SCNetworkServiceExists(service
)) {
393 SC_log(LOG_ERR
, "SCNetworkServiceAddProtocolType() w/removed service\n service = %@\n protocol = %@",
396 _SC_crash_once("SCNetworkServiceAddProtocolType() w/removed service", NULL
, NULL
);
397 _SCErrorSet(kSCStatusInvalidArgument
);
401 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
402 servicePrivate
->serviceID
, // service
403 protocolType
); // entity
405 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
406 if (entity
!= NULL
) {
407 // if "protocol" already exists
408 _SCErrorSet(kSCStatusKeyExists
);
412 newEntity
= CFDictionaryCreate(NULL
,
416 &kCFTypeDictionaryKeyCallBacks
,
417 &kCFTypeDictionaryValueCallBacks
);
418 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, newEntity
);
419 CFRelease(newEntity
);
425 protocol
= SCNetworkServiceCopyProtocol(service
, protocolType
);
426 assert(protocol
!= NULL
);
428 newEntity
= _protocolTemplate(service
, protocolType
);
429 assert(newEntity
!= NULL
);
431 ok
= SCNetworkProtocolSetConfiguration(protocol
, newEntity
);
433 // could not set default configuration
437 newEnabled
= !CFDictionaryContainsKey(newEntity
, kSCResvInactive
);
438 ok
= SCNetworkProtocolSetEnabled(protocol
, newEnabled
);
440 // could not enable/disable protocol
446 if (newEntity
!= NULL
) CFRelease(newEntity
);
447 if (protocol
!= NULL
) CFRelease(protocol
);
450 SC_log(LOG_DEBUG
, "SCNetworkServiceAddProtocolType(): %@, %@", service
, protocolType
);
458 CFArrayRef
/* of SCNetworkServiceRef's */
459 SCNetworkServiceCopyAll(SCPreferencesRef prefs
)
461 CFMutableArrayRef array
;
464 CFDictionaryRef services
;
467 path
= SCPreferencesPathKeyCreateNetworkServices(NULL
);
468 services
= SCPreferencesPathGetValue(prefs
, path
);
471 if ((services
!= NULL
) && !isA_CFDictionary(services
)) {
475 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
477 n
= (services
!= NULL
) ? CFDictionaryGetCount(services
) : 0;
480 const void * keys_q
[N_QUICK
];
481 const void ** keys
= keys_q
;
482 const void * vals_q
[N_QUICK
];
483 const void ** vals
= vals_q
;
485 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
486 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
487 vals
= CFAllocatorAllocate(NULL
, n
* sizeof(CFPropertyListRef
), 0);
489 CFDictionaryGetKeysAndValues(services
, keys
, vals
);
490 for (i
= 0; i
< n
; i
++) {
491 CFDictionaryRef entity
;
492 SCNetworkServicePrivateRef servicePrivate
;
494 if (!isA_CFDictionary(vals
[i
])) {
495 SC_log(LOG_INFO
, "error w/service \"%@\"", keys
[i
]);
499 entity
= CFDictionaryGetValue(vals
[i
], kSCEntNetInterface
);
500 if (!isA_CFDictionary(entity
)) {
502 SC_log(LOG_INFO
, "no \"%@\" entity for service \"%@\"",
508 if (__SCNetworkInterfaceEntityIsPPTP(entity
)) {
509 SC_log(LOG_INFO
, "PPTP services are no longer supported");
513 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, prefs
, keys
[i
], NULL
);
514 assert(servicePrivate
!= NULL
);
515 CFArrayAppendValue(array
, (SCNetworkServiceRef
)servicePrivate
);
516 CFRelease(servicePrivate
);
518 if (keys
!= keys_q
) {
519 CFAllocatorDeallocate(NULL
, keys
);
520 CFAllocatorDeallocate(NULL
, vals
);
529 CFArrayRef
/* of SCNetworkInterfaceRef's */
530 __SCNetworkServiceCopyAllInterfaces(SCPreferencesRef prefs
)
532 CFMutableArrayRef interfaces
= NULL
;
533 CFArrayRef services
= NULL
;
534 CFIndex servicesCount
= 0;
535 SCNetworkServiceRef service
= NULL
;
536 SCNetworkInterfaceRef interface
= NULL
;
538 services
= SCNetworkServiceCopyAll(prefs
);
539 if (services
== NULL
) {
543 servicesCount
= CFArrayGetCount(services
);
544 if (servicesCount
== 0) {
548 interfaces
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
550 for (CFIndex idx
= 0; idx
< servicesCount
; idx
++) {
551 service
= CFArrayGetValueAtIndex(services
, idx
);
552 interface
= SCNetworkServiceGetInterface(service
);
554 if (!isA_SCNetworkInterface(interface
)) {
557 CFArrayAppendValue(interfaces
, interface
);
560 if (CFArrayGetCount(interfaces
) == 0) {
561 // Do not return an empty array
562 CFRelease(interfaces
);
568 if (services
!= NULL
) {
576 * build a list of all of a services entity types that are associated
577 * with the services interface. The list will include :
579 * - entity types associated with the interface type (Ethernet, FireWire, PPP, ...)
580 * - entity types associated with the interface sub-type (PPPSerial, PPPoE, L2TP, PPTP, ...)
581 * - entity types associated with the hardware device (Ethernet, AirPort, FireWire, Modem, ...)
584 _copyInterfaceEntityTypes(CFDictionaryRef protocols
)
586 CFDictionaryRef interface
;
587 CFMutableSetRef interface_entity_types
;
589 interface_entity_types
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
591 interface
= CFDictionaryGetValue(protocols
, kSCEntNetInterface
);
592 if (isA_CFDictionary(interface
)) {
593 CFStringRef entities
[] = { kSCPropNetInterfaceType
,
594 kSCPropNetInterfaceSubType
,
595 kSCPropNetInterfaceHardware
};
597 // include the "Interface" entity itself
598 CFSetAddValue(interface_entity_types
, kSCEntNetInterface
);
600 // include the entities associated with the interface
601 for (size_t i
= 0; i
< sizeof(entities
)/sizeof(entities
[0]); i
++) {
604 entity
= CFDictionaryGetValue(interface
, entities
[i
]);
605 if (isA_CFString(entity
)) {
606 CFSetAddValue(interface_entity_types
, entity
);
611 * and, because we've found some misguided network preference code
612 * developers leaving [PPP] entity dictionaries around even though
613 * they are unused and/or unneeded...
615 CFSetAddValue(interface_entity_types
, kSCEntNetPPP
);
618 return interface_entity_types
;
623 SCNetworkServiceCopy(SCPreferencesRef prefs
, CFStringRef serviceID
)
625 CFDictionaryRef entity
;
627 SCNetworkServicePrivateRef servicePrivate
;
629 if (!isA_CFString(serviceID
)) {
630 _SCErrorSet(kSCStatusInvalidArgument
);
634 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
635 serviceID
, // service
636 kSCEntNetInterface
); // entity
637 entity
= SCPreferencesPathGetValue(prefs
, path
);
640 if (!isA_CFDictionary(entity
)) {
641 // a "service" must have an "interface"
642 _SCErrorSet(kSCStatusNoKey
);
646 if (__SCNetworkInterfaceEntityIsPPTP(entity
)) {
647 SC_log(LOG_INFO
, "PPTP services are no longer supported");
648 _SCErrorSet(kSCStatusNoKey
);
652 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, prefs
, serviceID
, NULL
);
653 return (SCNetworkServiceRef
)servicePrivate
;
658 _SCNetworkServiceCopyActive(SCDynamicStoreRef store
, CFStringRef serviceID
)
660 SCNetworkServicePrivateRef servicePrivate
;
662 if (!isA_CFString(serviceID
)) {
663 _SCErrorSet(kSCStatusInvalidArgument
);
667 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, NULL
, serviceID
, NULL
);
668 assert(servicePrivate
!= NULL
);
670 servicePrivate
->store
= CFRetain(store
);
672 return (SCNetworkServiceRef
)servicePrivate
;
677 SCNetworkServiceCopyProtocol(SCNetworkServiceRef service
, CFStringRef protocolType
)
679 CFSetRef non_protocol_entities
;
681 CFDictionaryRef protocols
;
682 SCNetworkProtocolPrivateRef protocolPrivate
= NULL
;
683 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
685 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
686 _SCErrorSet(kSCStatusInvalidArgument
);
690 if (!isA_CFString(protocolType
)) {
691 _SCErrorSet(kSCStatusInvalidArgument
);
695 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
696 servicePrivate
->serviceID
, // service
698 protocols
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
701 if (!isA_CFDictionary(protocols
)) {
703 _SCErrorSet(kSCStatusFailed
);
707 non_protocol_entities
= _copyInterfaceEntityTypes(protocols
);
708 if (CFSetContainsValue(non_protocol_entities
, protocolType
)) {
709 // if the "protocolType" matches an interface entity type
710 _SCErrorSet(kSCStatusInvalidArgument
);
714 if (!CFDictionaryContainsKey(protocols
, protocolType
)) {
715 // if the "protocolType" entity does not exist
716 _SCErrorSet(kSCStatusNoKey
);
720 protocolPrivate
= __SCNetworkProtocolCreatePrivate(NULL
, protocolType
, service
);
724 CFRelease(non_protocol_entities
);
726 return (SCNetworkProtocolRef
)protocolPrivate
;
730 CFArrayRef
/* of SCNetworkProtocolRef's */
731 SCNetworkServiceCopyProtocols(SCNetworkServiceRef service
)
733 CFMutableArrayRef array
;
735 CFSetRef non_protocol_entities
;
737 CFDictionaryRef protocols
;
738 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
740 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
741 _SCErrorSet(kSCStatusInvalidArgument
);
745 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
746 servicePrivate
->serviceID
, // service
748 protocols
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
751 if (!isA_CFDictionary(protocols
)) {
753 _SCErrorSet(kSCStatusFailed
);
757 non_protocol_entities
= _copyInterfaceEntityTypes(protocols
);
759 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
761 n
= CFDictionaryGetCount(protocols
);
764 const void * keys_q
[N_QUICK
];
765 const void ** keys
= keys_q
;
766 const void * vals_q
[N_QUICK
];
767 const void ** vals
= vals_q
;
769 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
770 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
771 vals
= CFAllocatorAllocate(NULL
, n
* sizeof(CFPropertyListRef
), 0);
773 CFDictionaryGetKeysAndValues(protocols
, keys
, vals
);
774 for (i
= 0; i
< n
; i
++) {
775 SCNetworkProtocolPrivateRef protocolPrivate
;
777 if (!isA_CFDictionary(vals
[i
])) {
778 // if it's not a dictionary then it can't be a protocol entity
782 if (CFSetContainsValue(non_protocol_entities
, keys
[i
])) {
783 // skip any non-protocol (interface) entities
787 protocolPrivate
= __SCNetworkProtocolCreatePrivate(NULL
, keys
[i
], service
);
788 CFArrayAppendValue(array
, (SCNetworkProtocolRef
)protocolPrivate
);
790 CFRelease(protocolPrivate
);
792 if (keys
!= keys_q
) {
793 CFAllocatorDeallocate(NULL
, keys
);
794 CFAllocatorDeallocate(NULL
, vals
);
798 CFRelease(non_protocol_entities
);
805 __SCNetworkServiceSetInterfaceEntity(SCNetworkServiceRef service
,
806 SCNetworkInterfaceRef interface
)
808 CFDictionaryRef entity
;
811 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
813 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
814 servicePrivate
->serviceID
, // service
815 kSCEntNetInterface
); // entity
816 entity
= __SCNetworkInterfaceCopyInterfaceEntity(interface
);
817 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, entity
);
826 SCNetworkServiceCreate(SCPreferencesRef prefs
, SCNetworkInterfaceRef interface
)
828 CFArrayRef components
;
829 CFArrayRef interface_config
;
830 CFStringRef interface_name
;
831 SCNetworkInterfaceRef newInterface
;
834 CFStringRef serviceID
;
835 SCNetworkServicePrivateRef servicePrivate
;
836 CFArrayRef supported_protocols
;
838 if (!isA_SCNetworkInterface(interface
)) {
839 _SCErrorSet(kSCStatusInvalidArgument
);
843 // only allow network interfaces which support one or more protocols
844 // to be added to a service. The one exception is that we allow
845 // third-party interface types to be configured.
846 supported_protocols
= SCNetworkInterfaceGetSupportedProtocolTypes(interface
);
847 if (supported_protocols
== NULL
) {
848 CFStringRef interface_type
;
850 interface_type
= SCNetworkInterfaceGetInterfaceType(interface
);
851 if (CFStringFind(interface_type
, CFSTR("."), 0).location
== kCFNotFound
) {
852 _SCErrorSet(kSCStatusInvalidArgument
);
857 // do not allow creation of a network service if the interface is a
858 // member of a bond or bridge
859 if (__SCNetworkInterfaceIsMember(prefs
, interface
)) {
860 _SCErrorSet(kSCStatusKeyExists
);
864 // establish the service
865 prefix
= SCPreferencesPathKeyCreateNetworkServices(NULL
);
866 path
= __SCPreferencesPathCreateUniqueChild_WithMoreSCFCompatibility(prefs
, prefix
);
867 if (path
== NULL
) path
= SCPreferencesPathCreateUniqueChild(prefs
, prefix
);
873 components
= CFStringCreateArrayBySeparatingStrings(NULL
, path
, CFSTR("/"));
876 serviceID
= CFArrayGetValueAtIndex(components
, 2);
877 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, prefs
, serviceID
, NULL
);
878 CFRelease(components
);
880 // duplicate the interface and associate the copy with the new service
881 newInterface
= (SCNetworkInterfaceRef
)__SCNetworkInterfaceCreateCopy(NULL
,
885 servicePrivate
->interface
= newInterface
;
887 // establish "default" configuration(s) for the interface
888 for (interface
= newInterface
;
890 interface
= SCNetworkInterfaceGetInterface(interface
)) {
891 SCNetworkInterfaceRef childInterface
;
892 CFStringRef childInterfaceType
= NULL
;
893 CFDictionaryRef config
;
894 CFStringRef interfaceType
;
896 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
897 childInterface
= SCNetworkInterfaceGetInterface(interface
);
898 if (childInterface
!= NULL
) {
899 childInterfaceType
= SCNetworkInterfaceGetInterfaceType(childInterface
);
902 config
= __copyInterfaceTemplate(interfaceType
, childInterfaceType
);
903 if (config
!= NULL
) {
904 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeBluetooth
) ||
905 CFEqual(interfaceType
, kSCNetworkInterfaceTypeIrDA
) ||
906 CFEqual(interfaceType
, kSCNetworkInterfaceTypeModem
) ||
907 CFEqual(interfaceType
, kSCNetworkInterfaceTypeSerial
) ||
908 CFEqual(interfaceType
, kSCNetworkInterfaceTypeWWAN
)) {
909 CFDictionaryRef overrides
;
911 overrides
= __SCNetworkInterfaceGetTemplateOverrides(interface
, kSCNetworkInterfaceTypeModem
);
913 // a ConnectionScript (and related keys) from the interface
914 // should trump the settings from the configuration template.
915 if (isA_CFDictionary(overrides
)) {
916 CFMutableDictionaryRef newConfig
;
918 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
919 if (CFDictionaryContainsKey(overrides
, kSCPropNetModemConnectionScript
)) {
920 CFDictionaryRemoveValue(newConfig
, kSCPropNetModemConnectionPersonality
);
921 CFDictionaryRemoveValue(newConfig
, kSCPropNetModemConnectionScript
);
922 CFDictionaryRemoveValue(newConfig
, kSCPropNetModemDeviceVendor
);
923 CFDictionaryRemoveValue(newConfig
, kSCPropNetModemDeviceModel
);
925 CFDictionaryApplyFunction(overrides
, mergeDict
, newConfig
);
929 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
) ||
930 CFEqual(interfaceType
, kSCNetworkInterfaceTypeVPN
)) {
931 CFDictionaryRef overrides
;
933 overrides
= __SCNetworkInterfaceGetTemplateOverrides(interface
, kSCNetworkInterfaceTypePPP
);
934 if (isA_CFDictionary(overrides
)) {
935 CFMutableDictionaryRef newConfig
;
937 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
938 CFDictionaryApplyFunction(overrides
, mergeDict
, newConfig
);
944 if (!__SCNetworkInterfaceSetConfiguration(interface
, NULL
, config
, TRUE
)) {
945 SC_log(LOG_INFO
, "__SCNetworkInterfaceSetConfiguration failed(), interface=%@, type=NULL",
952 // add the interface [entity] to the service
953 (void) __SCNetworkServiceSetInterfaceEntity((SCNetworkServiceRef
)servicePrivate
,
954 servicePrivate
->interface
);
956 // push the [deep] interface configuration into the service.
957 interface_config
= __SCNetworkInterfaceCopyDeepConfiguration(NULL
, servicePrivate
->interface
);
958 __SCNetworkInterfaceSetDeepConfiguration(NULL
, servicePrivate
->interface
, interface_config
);
959 if (interface_config
!= NULL
) CFRelease(interface_config
);
961 // set the service name to match that of the associated interface
963 // Note: It might seem a bit odd to call SCNetworkServiceGetName
964 // followed by an immediate call to SCNetworkServiceSetName. The
965 // trick here is that if no name has previously been set, the
966 // "get" function will return the name of the associated interface.
968 // ... and we "set" a name to ensure that applications that do
969 // not use the APIs will still find a UserDefinedName property
970 // in the SCDynamicStore.
972 interface_name
= SCNetworkServiceGetName((SCNetworkServiceRef
)servicePrivate
);
973 if (interface_name
!= NULL
) {
974 (void) SCNetworkServiceSetName((SCNetworkServiceRef
)servicePrivate
,
978 SC_log(LOG_DEBUG
, "SCNetworkServiceCreate(): %@", servicePrivate
);
980 return (SCNetworkServiceRef
)servicePrivate
;
984 static CF_RETURNS_RETAINED CFStringRef
985 copyInterfaceUUID(CFStringRef bsdName
)
988 unsigned char sha256_bytes
[CC_SHA256_DIGEST_LENGTH
];
989 CFUUIDBytes uuid_bytes
;
992 char if_name
[IF_NAMESIZE
];
994 CFStringRef uuid_str
;
996 // start with interface name
997 memset(&if_name
, 0, sizeof(if_name
));
998 (void) _SC_cfstring_to_cstring(bsdName
,
1001 kCFStringEncodingASCII
);
1003 // create SHA256 hash
1004 memset(&bytes
, 0, sizeof(bytes
));
1005 CC_SHA256_Init(&ctx
);
1006 CC_SHA256_Update(&ctx
,
1009 CC_SHA256_Final(bytes
.sha256_bytes
, &ctx
);
1011 // create UUID string
1012 uuid
= CFUUIDCreateFromUUIDBytes(NULL
, bytes
.uuid_bytes
);
1013 uuid_str
= CFUUIDCreateString(NULL
, uuid
);
1021 _SCNetworkServiceCreatePreconfigured(SCPreferencesRef prefs
, SCNetworkInterfaceRef interface
)
1023 CFStringRef bsdName
;
1025 SCNetworkServiceRef service
;
1026 CFStringRef serviceID
;
1028 bsdName
= SCNetworkInterfaceGetBSDName(interface
);
1030 // create network service
1031 service
= SCNetworkServiceCreate(prefs
, interface
);
1032 if (service
== NULL
) {
1033 SC_log(LOG_ERR
, "could not create network service for \"%@\": %s",
1035 SCErrorString(SCError()));
1039 // update network service to use a consistent serviceID
1040 serviceID
= copyInterfaceUUID(bsdName
);
1041 if (serviceID
!= NULL
) {
1042 ok
= _SCNetworkServiceSetServiceID(service
, serviceID
);
1043 CFRelease(serviceID
);
1045 SC_log(LOG_ERR
, "_SCNetworkServiceSetServiceID() failed: %s",
1046 SCErrorString(SCError()));
1047 // ... and keep whatever random UUID was created for the service
1050 SC_log(LOG_ERR
, "could not create serviceID for \"%@\"", bsdName
);
1051 // ... and we'll use whatever random UUID was created for the service
1054 // establish [template] configuration
1055 ok
= SCNetworkServiceEstablishDefaultConfiguration(service
);
1057 SC_log(LOG_ERR
, "could not establish network service for \"%@\": %s",
1059 SCErrorString(SCError()));
1060 SCNetworkServiceRemove(service
);
1070 SCNetworkServiceEstablishDefaultConfiguration(SCNetworkServiceRef service
)
1073 SCNetworkInterfaceRef interface
;
1076 CFArrayRef protocolTypes
;
1077 CFStringRef rankStr
;
1078 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1080 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1081 _SCErrorSet(kSCStatusInvalidArgument
);
1085 interface
= SCNetworkServiceGetInterface(service
);
1086 if (interface
== NULL
) {
1090 protocolTypes
= SCNetworkInterfaceGetSupportedProtocolTypes(interface
);
1091 n
= (protocolTypes
!= NULL
) ? CFArrayGetCount(protocolTypes
) : 0;
1092 for (i
= 0; i
< n
; i
++) {
1093 CFStringRef protocolType
;
1095 protocolType
= CFArrayGetValueAtIndex(protocolTypes
, i
);
1096 ok
= SCNetworkServiceAddProtocolType(service
, protocolType
);
1099 "SCNetworkServiceEstablishDefaultConfiguration(): could not add protocol \"%@\"",
1104 rankStr
= __SCNetworkInterfaceGetTemplateOverrides(interface
, kSCPropNetServicePrimaryRank
);
1105 if (isA_CFString(rankStr
)) {
1106 SCNetworkServicePrimaryRank rank
;
1108 ok
= __str_to_rank(rankStr
, &rank
);
1111 "SCNetworkServiceEstablishDefaultConfiguration(): unknown rank \"%@\"",
1116 ok
= SCNetworkServiceSetPrimaryRank(service
, rank
);
1119 "SCNetworkServiceEstablishDefaultConfiguration(): could not set rank \"%@\"",
1132 SCNetworkServiceGetEnabled(SCNetworkServiceRef service
)
1136 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1138 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1139 _SCErrorSet(kSCStatusInvalidArgument
);
1143 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1144 servicePrivate
->serviceID
, // service
1146 enabled
= __getPrefsEnabled(servicePrivate
->prefs
, path
);
1153 SCNetworkInterfaceRef
1154 SCNetworkServiceGetInterface(SCNetworkServiceRef service
)
1156 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1158 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1159 _SCErrorSet(kSCStatusInvalidArgument
);
1163 if (servicePrivate
->interface
== NULL
) {
1164 CFDictionaryRef entity
;
1167 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1168 servicePrivate
->serviceID
, // service
1169 kSCEntNetInterface
); // entity
1170 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1173 if (isA_CFDictionary(entity
)) {
1174 servicePrivate
->interface
= _SCNetworkInterfaceCreateWithEntity(NULL
, entity
, service
);
1178 return servicePrivate
->interface
;
1183 SCNetworkServiceGetName(SCNetworkServiceRef service
)
1185 CFDictionaryRef entity
;
1186 SCNetworkInterfaceRef interface
;
1187 CFStringRef name
= NULL
;
1189 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1190 Boolean useSystemInterfaces
= TRUE
;
1192 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1193 _SCErrorSet(kSCStatusInvalidArgument
);
1197 if (servicePrivate
->name
!= NULL
) {
1198 return servicePrivate
->name
;
1201 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1202 servicePrivate
->serviceID
, // service
1204 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1207 useSystemInterfaces
= !_SCNetworkConfigurationBypassSystemInterfaces(servicePrivate
->prefs
);
1209 if (isA_CFDictionary(entity
)) {
1210 name
= CFDictionaryGetValue(entity
, kSCPropUserDefinedName
);
1211 if (isA_CFString(name
)) {
1212 servicePrivate
->name
= CFRetain(name
);
1213 if (!useSystemInterfaces
) {
1214 return servicePrivate
->name
;
1219 interface
= SCNetworkServiceGetInterface(service
);
1220 while (interface
!= NULL
) {
1221 SCNetworkInterfaceRef childInterface
;
1222 CFStringRef interfaceType
;
1224 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
1225 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeVPN
)) {
1229 childInterface
= SCNetworkInterfaceGetInterface(interface
);
1230 if ((childInterface
== NULL
) ||
1231 CFEqual(childInterface
, kSCNetworkInterfaceIPv4
)) {
1235 interface
= childInterface
;
1238 if (interface
!= NULL
) {
1240 CFStringRef interface_name
= NULL
;
1241 CFStringRef suffix
= NULL
;
1244 // check if the [stored] service name matches the non-localized interface
1245 // name. If so, return the localized name.
1247 // Also, the older "Built-in XXX" interface names are too long for the
1248 // current UI. If we find that the [stored] service name matches the older
1249 // name, return the newer (and shorter) localized name.
1251 // Note: the user/admin will no longer be able to set the service name
1252 // to "Built-in Ethernet".
1254 for (i
= 0; i
< 3; i
++) {
1255 if (servicePrivate
->name
== NULL
) {
1256 // if no [stored] service name to compare
1262 // compare the non-localized interface name
1263 interface_name
= __SCNetworkInterfaceGetNonLocalizedDisplayName(interface
);
1264 if (interface_name
!= NULL
) {
1265 CFRetain(interface_name
);
1268 #if !TARGET_OS_IPHONE
1270 // compare the older "Built-in XXX" localized name
1271 interface_name
= __SCNetworkInterfaceCopyXLocalizedDisplayName(interface
);
1274 // compare the older "Built-in XXX" non-localized name
1275 interface_name
= __SCNetworkInterfaceCopyXNonLocalizedDisplayName(interface
);
1277 #else // !TARGET_OS_IPHONE
1280 #endif // !TARGET_OS_IPHONE
1283 if (interface_name
!= NULL
) {
1284 Boolean match
= FALSE
;
1286 if (CFEqual(name
, interface_name
)) {
1287 // if service name matches the OLD localized
1290 } else if (CFStringHasPrefix(name
, interface_name
)) {
1291 CFIndex prefixLen
= CFStringGetLength(interface_name
);
1292 CFIndex suffixLen
= CFStringGetLength(name
);
1294 suffix
= CFStringCreateWithSubstring(NULL
,
1296 CFRangeMake(prefixLen
, suffixLen
- prefixLen
));
1299 CFRelease(interface_name
);
1302 CFRelease(servicePrivate
->name
);
1303 servicePrivate
->name
= NULL
;
1310 // if the service name has not been set, use the localized interface name
1312 if (servicePrivate
->name
== NULL
) {
1313 interface_name
= SCNetworkInterfaceGetLocalizedDisplayName(interface
);
1314 if (interface_name
!= NULL
) {
1315 if (suffix
!= NULL
) {
1316 servicePrivate
->name
= CFStringCreateWithFormat(NULL
,
1322 servicePrivate
->name
= CFRetain(interface_name
);
1326 if (suffix
!= NULL
) CFRelease(suffix
);
1329 return servicePrivate
->name
;
1334 SCNetworkServiceGetServiceID(SCNetworkServiceRef service
)
1336 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1338 if (!isA_SCNetworkService(service
)) {
1339 _SCErrorSet(kSCStatusInvalidArgument
);
1343 return servicePrivate
->serviceID
;
1348 SCNetworkServiceGetTypeID(void)
1350 pthread_once(&initialized
, __SCNetworkServiceInitialize
); /* initialize runtime */
1351 return __kSCNetworkServiceTypeID
;
1356 SCNetworkServiceRemove(SCNetworkServiceRef service
)
1360 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1363 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1364 _SCErrorSet(kSCStatusInvalidArgument
);
1368 if (!__SCNetworkServiceExists(service
)) {
1369 SC_log(LOG_ERR
, "SCNetworkServiceRemove() w/removed service\n service = %@", service
);
1370 _SC_crash_once("SCNetworkServiceRemove() w/removed service", NULL
, NULL
);
1371 _SCErrorSet(kSCStatusInvalidArgument
);
1375 // remove service from all sets
1377 sets
= SCNetworkSetCopyAll(servicePrivate
->prefs
);
1381 n
= CFArrayGetCount(sets
);
1382 for (CFIndex i
= 0; i
< n
; i
++) {
1383 SCNetworkSetRef set
;
1385 set
= CFArrayGetValueAtIndex(sets
, i
);
1386 ok
= SCNetworkSetRemoveService(set
, service
);
1387 if (!ok
&& (SCError() != kSCStatusNoKey
)) {
1397 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1398 servicePrivate
->serviceID
, // service
1400 ok
= SCPreferencesPathRemoveValue(servicePrivate
->prefs
, path
);
1404 SC_log(LOG_DEBUG
, "SCNetworkServiceRemove(): %@", service
);
1412 SCNetworkServiceRemoveProtocolType(SCNetworkServiceRef service
, CFStringRef protocolType
)
1414 CFDictionaryRef entity
;
1417 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1419 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1420 _SCErrorSet(kSCStatusInvalidArgument
);
1424 if (!__SCNetworkServiceExists(service
)) {
1425 SC_log(LOG_ERR
, "SCNetworkServiceRemoveProtocolType() w/removed service\n service = %@\n protocol = %@",
1428 _SC_crash_once("SCNetworkServiceRemoveProtocolType() w/removed service", NULL
, NULL
);
1429 _SCErrorSet(kSCStatusInvalidArgument
);
1433 if (!__SCNetworkProtocolIsValidType(protocolType
)) {
1434 _SCErrorSet(kSCStatusInvalidArgument
);
1438 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1439 servicePrivate
->serviceID
, // service
1440 protocolType
); // entity
1442 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1443 if (entity
== NULL
) {
1444 // if "protocol" does not exist
1445 _SCErrorSet(kSCStatusNoKey
);
1449 ok
= SCPreferencesPathRemoveValue(servicePrivate
->prefs
, path
);
1454 SC_log(LOG_DEBUG
, "SCNetworkServiceRemoveProtocolType(): %@, %@", service
, protocolType
);
1463 SCNetworkServiceSetEnabled(SCNetworkServiceRef service
, Boolean enabled
)
1467 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1469 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1470 _SCErrorSet(kSCStatusInvalidArgument
);
1474 if (!__SCNetworkServiceExists(service
)) {
1475 SC_log(LOG_ERR
, "SCNetworkServiceSetEnabled() w/removed service\n service = %@", service
);
1476 _SC_crash_once("SCNetworkProtocolSetEnabled() w/removed service", NULL
, NULL
);
1477 _SCErrorSet(kSCStatusInvalidArgument
);
1481 // make sure that we do not enable a network service if the
1482 // associated interface is a member of a bond or bridge.
1484 SCNetworkInterfaceRef interface
;
1486 interface
= SCNetworkServiceGetInterface(service
);
1487 if ((interface
!= NULL
) &&
1488 __SCNetworkInterfaceIsMember(servicePrivate
->prefs
, interface
)) {
1489 _SCErrorSet(kSCStatusKeyExists
);
1494 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1495 servicePrivate
->serviceID
, // service
1497 ok
= __setPrefsEnabled(servicePrivate
->prefs
, path
, enabled
);
1501 SC_log(LOG_DEBUG
, "SCNetworkServiceSetEnabled(): %@ -> %s",
1503 enabled
? "Enabled" : "Disabled");
1511 SCNetworkServiceSetName(SCNetworkServiceRef service
, CFStringRef name
)
1513 CFDictionaryRef entity
;
1516 CFStringRef saveName
= NULL
;
1517 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1519 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1520 _SCErrorSet(kSCStatusInvalidArgument
);
1524 if (!__SCNetworkServiceExists(service
)) {
1525 SC_log(LOG_ERR
, "SCNetworkServiceSetName() w/removed service\n service = %@\n name = %@",
1527 name
!= NULL
? name
: CFSTR("<NULL>"));
1528 _SC_crash_once("SCNetworkServiceSetName() w/removed service", NULL
, NULL
);
1529 _SCErrorSet(kSCStatusInvalidArgument
);
1534 if (!isA_CFString(name
)) {
1535 _SCErrorSet(kSCStatusInvalidArgument
);
1538 saveName
= CFRetain(name
);
1542 SCNetworkInterfaceRef interface
;
1544 interface
= SCNetworkServiceGetInterface(service
);
1545 while (interface
!= NULL
) {
1546 SCNetworkInterfaceRef childInterface
;
1548 childInterface
= SCNetworkInterfaceGetInterface(interface
);
1549 if (childInterface
== NULL
) {
1553 interface
= childInterface
;
1556 if (interface
!= NULL
) {
1557 CFStringRef interface_name
;
1559 interface_name
= SCNetworkInterfaceGetLocalizedDisplayName(interface
);
1560 if (interface_name
!= NULL
) {
1561 if (CFEqual(name
, interface_name
)) {
1562 // if service name matches the localized interface name
1563 // then store the non-localized name.
1564 interface_name
= __SCNetworkInterfaceGetNonLocalizedDisplayName(interface
);
1565 if (interface_name
!= NULL
) {
1566 CFRelease(saveName
);
1567 saveName
= CFRetain(interface_name
);
1569 } else if (CFStringHasPrefix(name
, interface_name
)) {
1570 CFIndex prefixLen
= CFStringGetLength(interface_name
);
1572 CFIndex suffixLen
= CFStringGetLength(name
);
1574 // if service name matches the localized interface name plus
1575 // a few extra characters) then store the non-localized name with
1577 suffix
= CFStringCreateWithSubstring(NULL
,
1579 CFRangeMake(prefixLen
, suffixLen
- prefixLen
));
1580 interface_name
= __SCNetworkInterfaceGetNonLocalizedDisplayName(interface
);
1581 if (interface_name
!= NULL
) {
1582 CFRelease(saveName
);
1583 saveName
= CFStringCreateWithFormat(NULL
,
1595 #define PREVENT_DUPLICATE_SERVICE_NAMES
1596 #ifdef PREVENT_DUPLICATE_SERVICE_NAMES
1600 // ensure that each service is uniquely named within its sets
1602 sets
= SCNetworkSetCopyAll(servicePrivate
->prefs
);
1607 set_count
= CFArrayGetCount(sets
);
1608 for (set_index
= 0; set_index
< set_count
; set_index
++) {
1609 CFIndex service_index
;
1610 Boolean isDup
= FALSE
;
1611 Boolean isMember
= FALSE
;
1612 CFIndex service_count
;
1613 CFArrayRef services
;
1614 SCNetworkSetRef set
= CFArrayGetValueAtIndex(sets
, set_index
);
1616 services
= SCNetworkSetCopyServices(set
);
1618 service_count
= CFArrayGetCount(services
);
1619 for (service_index
= 0; service_index
< service_count
; service_index
++) {
1620 CFStringRef otherID
;
1621 CFStringRef otherName
;
1622 SCNetworkServiceRef otherService
;
1624 otherService
= CFArrayGetValueAtIndex(services
, service_index
);
1626 otherID
= SCNetworkServiceGetServiceID(otherService
);
1627 if (CFEqual(servicePrivate
->serviceID
, otherID
)) {
1628 // if the service is a member of this set
1633 otherName
= SCNetworkServiceGetName(otherService
);
1634 if ((otherName
!= NULL
) && CFEqual(name
, otherName
)) {
1640 CFRelease(services
);
1642 if (isMember
&& isDup
) {
1644 * if this service is a member of the set and
1645 * the "name" is not unique.
1648 if (saveName
!= NULL
) CFRelease(saveName
);
1649 _SCErrorSet(kSCStatusKeyExists
);
1657 #endif /* PREVENT_DUPLICATE_SERVICE_NAMES */
1659 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1660 servicePrivate
->serviceID
, // service
1662 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1663 if (isA_CFDictionary(entity
) ||
1664 ((entity
== NULL
) && (name
!= NULL
))) {
1665 CFMutableDictionaryRef newEntity
;
1667 if (entity
!= NULL
) {
1668 newEntity
= CFDictionaryCreateMutableCopy(NULL
, 0, entity
);
1670 newEntity
= CFDictionaryCreateMutable(NULL
,
1672 &kCFTypeDictionaryKeyCallBacks
,
1673 &kCFTypeDictionaryValueCallBacks
);
1675 if (saveName
!= NULL
) {
1676 CFDictionarySetValue(newEntity
, kSCPropUserDefinedName
, saveName
);
1678 CFDictionaryRemoveValue(newEntity
, kSCPropUserDefinedName
);
1680 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, newEntity
);
1681 CFRelease(newEntity
);
1684 if (saveName
!= NULL
) CFRelease(saveName
);
1686 if (servicePrivate
->name
!= NULL
) CFRelease(servicePrivate
->name
);
1687 if (name
!= NULL
) CFRetain(name
);
1688 servicePrivate
->name
= name
;
1691 SC_log(LOG_DEBUG
, "SCNetworkServiceSetName(): %@", service
);
1699 #pragma mark SCNetworkService SPIs
1704 __SCNetworkServiceExists(SCNetworkServiceRef service
)
1706 CFDictionaryRef entity
;
1708 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1710 if (servicePrivate
->prefs
== NULL
) {
1715 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1716 servicePrivate
->serviceID
, // service
1717 kSCEntNetInterface
); // entity
1718 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1721 if (!isA_CFDictionary(entity
)) {
1722 // a "service" must have an "interface"
1730 SCNetworkServicePrimaryRank
1731 SCNetworkServiceGetPrimaryRank(SCNetworkServiceRef service
)
1733 CFDictionaryRef entity
;
1736 SCNetworkServicePrimaryRank rank
= kSCNetworkServicePrimaryRankDefault
;
1737 CFStringRef rankStr
= NULL
;
1738 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1740 if (!isA_SCNetworkService(service
)) {
1741 _SCErrorSet(kSCStatusInvalidArgument
);
1745 if (servicePrivate
->prefs
!= NULL
) {
1746 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
,
1747 servicePrivate
->serviceID
,
1749 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1751 if (isA_CFDictionary(entity
)) {
1752 rankStr
= CFDictionaryGetValue(entity
, kSCPropNetServicePrimaryRank
);
1753 ok
= __str_to_rank(rankStr
, &rank
);
1755 } else if (servicePrivate
->store
!= NULL
) {
1756 path
= SCDynamicStoreKeyCreateNetworkServiceEntity(NULL
,
1757 kSCDynamicStoreDomainState
,
1758 servicePrivate
->serviceID
,
1760 entity
= SCDynamicStoreCopyValue(servicePrivate
->store
, path
);
1762 if (entity
!= NULL
) {
1763 if (isA_CFDictionary(entity
)) {
1764 rankStr
= CFDictionaryGetValue(entity
, kSCPropNetServicePrimaryRank
);
1765 ok
= __str_to_rank(rankStr
, &rank
);
1770 _SCErrorSet(kSCStatusInvalidArgument
);
1775 rank
= kSCNetworkServicePrimaryRankDefault
;
1776 _SCErrorSet(kSCStatusInvalidArgument
);
1777 } else if (rank
== kSCNetworkServicePrimaryRankDefault
) {
1778 _SCErrorSet(kSCStatusOK
);
1786 SCNetworkServiceSetPrimaryRank(SCNetworkServiceRef service
,
1787 SCNetworkServicePrimaryRank newRank
)
1790 CFDictionaryRef entity
;
1791 CFMutableDictionaryRef newEntity
;
1792 CFStringRef path
= NULL
;
1793 CFStringRef rankStr
= NULL
;
1794 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1796 if (!isA_SCNetworkService(service
)) {
1797 _SCErrorSet(kSCStatusInvalidArgument
);
1801 if ((servicePrivate
->prefs
!= NULL
) && !__SCNetworkServiceExists(service
)) {
1802 SC_log(LOG_ERR
, "SCNetworkServiceSetPrimaryRank() w/removed\n service = %@", service
);
1803 _SC_crash_once("SCNetworkServiceSetPrimaryRank() w/removed service", NULL
, NULL
);
1804 _SCErrorSet(kSCStatusInvalidArgument
);
1808 ok
= __rank_to_str(newRank
, &rankStr
);
1810 _SCErrorSet(kSCStatusInvalidArgument
);
1814 if (servicePrivate
->prefs
!= NULL
) {
1816 case kSCNetworkServicePrimaryRankDefault
:
1817 case kSCNetworkServicePrimaryRankNever
:
1818 case kSCNetworkServicePrimaryRankScoped
:
1819 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
,
1820 servicePrivate
->serviceID
,
1822 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1823 if (entity
!= NULL
) {
1824 if (!isA_CFDictionary(entity
)) {
1826 _SCErrorSet(kSCStatusFailed
);
1829 newEntity
= CFDictionaryCreateMutableCopy(NULL
, 0, entity
);
1831 newEntity
= CFDictionaryCreateMutable(NULL
,
1833 &kCFTypeDictionaryKeyCallBacks
,
1834 &kCFTypeDictionaryValueCallBacks
);
1836 if (rankStr
!= NULL
) {
1837 CFDictionarySetValue(newEntity
, kSCPropNetServicePrimaryRank
, rankStr
);
1839 CFDictionaryRemoveValue(newEntity
, kSCPropNetServicePrimaryRank
);
1841 if (CFDictionaryGetCount(newEntity
) > 0) {
1842 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, newEntity
);
1844 ok
= SCPreferencesPathRemoveValue(servicePrivate
->prefs
, path
);
1846 CFRelease(newEntity
);
1852 _SCErrorSet(kSCStatusInvalidArgument
);
1855 } else if (servicePrivate
->store
!= NULL
) {
1856 path
= SCDynamicStoreKeyCreateNetworkServiceEntity(NULL
,
1857 kSCDynamicStoreDomainState
,
1858 servicePrivate
->serviceID
,
1860 entity
= SCDynamicStoreCopyValue(servicePrivate
->store
, path
);
1861 if (entity
!= NULL
) {
1862 if (!isA_CFDictionary(entity
)) {
1865 _SCErrorSet(kSCStatusFailed
);
1868 newEntity
= CFDictionaryCreateMutableCopy(NULL
, 0, entity
);
1871 newEntity
= CFDictionaryCreateMutable(NULL
,
1873 &kCFTypeDictionaryKeyCallBacks
,
1874 &kCFTypeDictionaryValueCallBacks
);
1876 if (rankStr
!= NULL
) {
1877 CFDictionarySetValue(newEntity
, kSCPropNetServicePrimaryRank
, rankStr
);
1879 CFDictionaryRemoveValue(newEntity
, kSCPropNetServicePrimaryRank
);
1881 if (CFDictionaryGetCount(newEntity
) > 0) {
1882 ok
= SCDynamicStoreSetValue(servicePrivate
->store
, path
, newEntity
);
1884 ok
= SCDynamicStoreRemoveValue(servicePrivate
->store
, path
);
1886 CFRelease(newEntity
);
1891 _SCErrorSet(kSCStatusInvalidArgument
);
1897 if (path
!= NULL
) CFRelease(path
);
1903 _SCNetworkServiceIsVPN(SCNetworkServiceRef service
)
1905 SCNetworkInterfaceRef interface
;
1906 CFStringRef interfaceType
;
1908 interface
= SCNetworkServiceGetInterface(service
);
1909 if (interface
== NULL
) {
1913 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
1914 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
)) {
1915 interface
= SCNetworkInterfaceGetInterface(interface
);
1916 if (interface
== NULL
) {
1920 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
1921 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeL2TP
)) {
1924 #pragma GCC diagnostic push
1925 #pragma GCC diagnostic ignored "-Wdeprecated"
1926 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPTP
)) {
1929 #pragma GCC diagnostic pop
1930 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeVPN
)) {
1932 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeIPSec
)) {
1941 SCNetworkServiceSetExternalID(SCNetworkServiceRef service
, CFStringRef identifierDomain
, CFStringRef identifier
)
1943 CFStringRef prefs_path
;
1944 CFDictionaryRef service_dictionary
;
1945 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1946 Boolean success
= FALSE
;
1947 CFStringRef prefixed_domain
;
1949 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
) || !isA_CFString(identifierDomain
)) {
1950 _SCErrorSet(kSCStatusInvalidArgument
);
1954 if (!__SCNetworkServiceExists(service
)) {
1955 SC_log(LOG_ERR
, "SCNetworkServiceSetExternalID() w/removed\n service = %@\n id = %@",
1958 _SC_crash_once("SCNetworkServiceSetExternalID() w/removed service", NULL
, NULL
);
1959 _SCErrorSet(kSCStatusInvalidArgument
);
1963 if (identifier
!= NULL
&& !isA_CFString(identifier
)) {
1964 _SCErrorSet(kSCStatusInvalidArgument
);
1968 prefixed_domain
= CFStringCreateWithFormat(NULL
, 0, CFSTR("%s%@"), EXTERNAL_ID_DOMAIN_PREFIX
, identifierDomain
);
1970 prefs_path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
,
1971 servicePrivate
->serviceID
,
1974 service_dictionary
= SCPreferencesPathGetValue(servicePrivate
->prefs
, prefs_path
);
1975 if (isA_CFDictionary(service_dictionary
) || ((service_dictionary
== NULL
) && (identifier
!= NULL
))) {
1976 CFMutableDictionaryRef new_service_dictionary
;
1978 if (service_dictionary
!= NULL
) {
1979 new_service_dictionary
= CFDictionaryCreateMutableCopy(NULL
, 0, service_dictionary
);
1981 new_service_dictionary
= CFDictionaryCreateMutable(NULL
,
1983 &kCFTypeDictionaryKeyCallBacks
,
1984 &kCFTypeDictionaryValueCallBacks
);
1987 if (identifier
!= NULL
) {
1988 CFDictionarySetValue(new_service_dictionary
, prefixed_domain
, identifier
);
1990 CFDictionaryRemoveValue(new_service_dictionary
, prefixed_domain
);
1992 success
= SCPreferencesPathSetValue(servicePrivate
->prefs
, prefs_path
, new_service_dictionary
);
1993 CFRelease(new_service_dictionary
);
1995 CFRelease(prefs_path
);
1997 if (identifier
!= NULL
) {
1998 if (servicePrivate
->externalIDs
== NULL
) {
1999 servicePrivate
->externalIDs
= CFDictionaryCreateMutable(NULL
,
2001 &kCFTypeDictionaryKeyCallBacks
,
2002 &kCFTypeDictionaryValueCallBacks
);
2004 CFDictionarySetValue(servicePrivate
->externalIDs
, prefixed_domain
, identifier
);
2006 if (servicePrivate
->externalIDs
!= NULL
) {
2007 CFDictionaryRemoveValue(servicePrivate
->externalIDs
, prefixed_domain
);
2011 CFRelease(prefixed_domain
);
2014 _SCErrorSet(kSCStatusFailed
);
2022 SCNetworkServiceCopyExternalID(SCNetworkServiceRef service
, CFStringRef identifierDomain
)
2024 CFStringRef identifier
= NULL
;
2025 CFStringRef prefixed_domain
;
2026 SCNetworkServicePrivateRef service_private
= (SCNetworkServicePrivateRef
)service
;
2028 if (!isA_SCNetworkService(service
) || (service_private
->prefs
== NULL
) || !isA_CFString(identifierDomain
)) {
2029 _SCErrorSet(kSCStatusInvalidArgument
);
2033 prefixed_domain
= CFStringCreateWithFormat(NULL
, 0, CFSTR("%s%@"), EXTERNAL_ID_DOMAIN_PREFIX
, identifierDomain
);
2035 if (service_private
->externalIDs
!= NULL
) {
2036 identifier
= CFDictionaryGetValue(service_private
->externalIDs
, prefixed_domain
);
2037 if (identifier
!= NULL
) {
2038 CFRetain(identifier
);
2042 if (identifier
== NULL
) {
2043 CFStringRef prefs_path
;
2044 CFDictionaryRef service_dictionary
;
2046 prefs_path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
,
2047 service_private
->serviceID
,
2050 service_dictionary
= SCPreferencesPathGetValue(service_private
->prefs
, prefs_path
);
2051 if (isA_CFDictionary(service_dictionary
)) {
2052 identifier
= CFDictionaryGetValue(service_dictionary
, prefixed_domain
);
2053 if (identifier
!= NULL
) {
2054 CFRetain(identifier
);
2055 if (service_private
->externalIDs
== NULL
) {
2056 service_private
->externalIDs
= CFDictionaryCreateMutable(NULL
,
2058 &kCFTypeDictionaryKeyCallBacks
,
2059 &kCFTypeDictionaryValueCallBacks
);
2061 CFDictionarySetValue(service_private
->externalIDs
, prefixed_domain
, identifier
);
2064 CFRelease(prefs_path
);
2067 CFRelease(prefixed_domain
);
2069 if (identifier
== NULL
) {
2070 _SCErrorSet(kSCStatusNoKey
);
2078 CFStringRef oldServiceID
;
2079 CFStringRef newServiceID
;
2080 } serviceContext
, *serviceContextRef
;
2084 replaceServiceID(const void *value
, void *context
)
2086 CFStringRef link
= NULL
;
2087 CFStringRef oldLink
;
2088 CFMutableArrayRef newServiceOrder
;
2090 serviceContextRef service_context
= (serviceContextRef
)context
;
2091 CFArrayRef serviceOrder
= NULL
;
2092 SCNetworkSetRef set
= (SCNetworkSetRef
)value
;
2093 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
2095 // update service order
2096 serviceOrder
= SCNetworkSetGetServiceOrder(set
);
2097 if ((isA_CFArray(serviceOrder
) != NULL
) &&
2098 CFArrayContainsValue(serviceOrder
,
2099 CFRangeMake(0, CFArrayGetCount(serviceOrder
)),
2100 service_context
->oldServiceID
)) {
2102 CFIndex serviceOrderIndex
;
2104 // replacing all instances of old service ID with new one
2105 newServiceOrder
= CFArrayCreateMutableCopy(NULL
, 0, serviceOrder
);
2106 count
= CFArrayGetCount(newServiceOrder
);
2107 for (serviceOrderIndex
= 0; serviceOrderIndex
< count
; serviceOrderIndex
++) {
2108 CFStringRef serviceID
;
2110 serviceID
= CFArrayGetValueAtIndex(newServiceOrder
, serviceOrderIndex
);
2111 if (CFEqual(serviceID
, service_context
->oldServiceID
)) {
2112 CFArraySetValueAtIndex(newServiceOrder
, serviceOrderIndex
, service_context
->newServiceID
);
2115 SCNetworkSetSetServiceOrder(set
, newServiceOrder
);
2116 CFRelease(newServiceOrder
);
2119 // check if service with old serviceID is part of the set
2120 path
= SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL
, // allocator
2121 setPrivate
->setID
, // set
2122 service_context
->oldServiceID
, // service
2124 oldLink
= SCPreferencesPathGetLink(setPrivate
->prefs
, path
);
2125 if (oldLink
== NULL
) {
2126 // don't make any changes if service with old serviceID is not found
2130 // remove link between "set" and old "service"
2131 (void) SCPreferencesPathRemoveValue(setPrivate
->prefs
, path
);
2134 // create the link between "set" and the "service"
2135 path
= SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL
, // allocator
2136 setPrivate
->setID
, // set
2137 service_context
->newServiceID
, // service
2139 link
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
2140 service_context
->newServiceID
, // service
2142 (void) SCPreferencesPathSetLink(setPrivate
->prefs
, path
, link
);
2158 _SCNetworkServiceSetServiceID(SCNetworkServiceRef service
, CFStringRef newServiceID
)
2160 CFArrayRef allSets
= NULL
;
2161 CFDictionaryRef entity
;
2162 CFStringRef newPath
;
2164 CFStringRef oldPath
= NULL
;
2165 serviceContext service_context
;
2166 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
2168 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
2169 _SCErrorSet(kSCStatusInvalidArgument
);
2173 if (!isA_CFString(newServiceID
)) {
2174 _SCErrorSet(kSCStatusInvalidArgument
);
2178 if (CFEqual(newServiceID
, servicePrivate
->serviceID
)) {
2179 // no work needs to be done if new service ID is equal to current service ID
2183 if (!__SCNetworkServiceExists(service
)) {
2184 SC_log(LOG_ERR
, "_SCNetworkServiceSetServiceID() w/removed service\n service = %@\n serviceID = %@",
2187 _SC_crash_once("_SCNetworkServiceSetServiceID() w/removed service", NULL
, NULL
);
2188 _SCErrorSet(kSCStatusInvalidArgument
);
2192 newPath
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
2193 newServiceID
, // service
2195 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, newPath
);
2196 if (isA_CFDictionary(entity
)) {
2197 // if the new service already exists
2198 _SCErrorSet(kSCStatusKeyExists
);
2202 oldPath
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
2203 servicePrivate
->serviceID
, // service
2205 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, oldPath
);
2206 if (!isA_CFDictionary(entity
)) {
2207 // if the service has already been removed
2208 _SCErrorSet(kSCStatusNoKey
);
2212 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, newPath
, entity
);
2215 ok
= SCPreferencesPathRemoveValue(servicePrivate
->prefs
, oldPath
);
2218 allSets
= SCNetworkSetCopyAll(servicePrivate
->prefs
);
2220 service_context
.newServiceID
= newServiceID
;
2221 service_context
.oldServiceID
= servicePrivate
->serviceID
;
2223 // find all sets w/oldServiceID and update
2224 // ... and update the serviceOrder
2225 CFArrayApplyFunction(allSets
,
2226 CFRangeMake(0, CFArrayGetCount(allSets
)),
2230 if (servicePrivate
->interface
!= NULL
) {
2231 SCNetworkInterfaceRef newInterface
;
2233 // duplicate the interface and associate the copy with the new service ID
2234 newInterface
= (SCNetworkInterfaceRef
)__SCNetworkInterfaceCreateCopy(NULL
,
2235 servicePrivate
->interface
,
2236 servicePrivate
->prefs
,
2238 CFRelease(servicePrivate
->interface
);
2239 servicePrivate
->interface
= newInterface
;
2242 SC_log(LOG_DEBUG
, "_SCNetworkServiceSetServiceID(): %@ --> %@", service
, newServiceID
);
2244 // replace serviceID with new one
2245 CFRetain(newServiceID
);
2246 CFRelease(servicePrivate
->serviceID
);
2247 servicePrivate
->serviceID
= newServiceID
;
2251 if (oldPath
!= NULL
) {
2254 if (newPath
!= NULL
) {
2257 if (allSets
!= NULL
) {
2264 #define kVPNProtocolPayloadInfo CFSTR("com.apple.payload")
2265 #define kSCEntNetLoginWindowEAPOL CFSTR("EAPOL.LoginWindow")
2268 copyInterfaceConfiguration(SCNetworkServiceRef oldService
, SCNetworkServiceRef newService
)
2270 SCNetworkInterfaceRef oldInterface
;
2271 SCNetworkInterfaceRef newInterface
;
2273 oldInterface
= SCNetworkServiceGetInterface(oldService
);
2274 newInterface
= SCNetworkServiceGetInterface(newService
);
2276 while (oldInterface
!= NULL
) {
2277 CFDictionaryRef configuration
;
2278 CFStringRef interfaceType
;
2280 if (newInterface
== NULL
) {
2281 // oops ... interface layering does not match
2285 // copy interface configuration
2286 configuration
= SCNetworkInterfaceGetConfiguration(oldInterface
);
2288 if ((configuration
!= NULL
) ||
2289 (SCError() == kSCStatusOK
)) {
2290 if (!SCNetworkInterfaceSetConfiguration(newInterface
, configuration
)) {
2291 SC_log(LOG_INFO
, "problem setting interface configuration");
2296 // special case: PPP/L2TP + IPSec
2297 interfaceType
= SCNetworkInterfaceGetInterfaceType(oldInterface
);
2298 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
)) {
2299 SCNetworkInterfaceRef childInterface
;
2301 childInterface
= SCNetworkInterfaceGetInterface(oldInterface
);
2302 if (childInterface
!= NULL
) {
2303 CFStringRef childInterfaceType
;
2305 childInterfaceType
= SCNetworkInterfaceGetInterfaceType(childInterface
);
2307 if (CFEqual(childInterfaceType
, kSCNetworkInterfaceTypeL2TP
)) {
2308 configuration
= SCNetworkInterfaceGetExtendedConfiguration(oldInterface
, kSCEntNetIPSec
);
2309 if ((configuration
!= NULL
) ||
2310 (SCError() == kSCStatusOK
)) {
2311 if (!SCNetworkInterfaceSetExtendedConfiguration(newInterface
, kSCEntNetIPSec
, configuration
)) {
2312 SC_log(LOG_INFO
, "problem setting child interface configuration");
2319 // special case: 802.1x
2320 configuration
= SCNetworkInterfaceGetExtendedConfiguration(oldInterface
, kSCEntNetEAPOL
);
2321 if ((configuration
!= NULL
) ||
2322 (SCError() == kSCStatusOK
)) {
2323 (void) SCNetworkInterfaceSetExtendedConfiguration(newInterface
, kSCEntNetEAPOL
, configuration
);
2326 // special case: Managed Client
2327 configuration
= SCNetworkInterfaceGetExtendedConfiguration(oldInterface
, kVPNProtocolPayloadInfo
);
2328 if ((configuration
!= NULL
) ||
2329 (SCError() == kSCStatusOK
)) {
2330 (void) SCNetworkInterfaceSetExtendedConfiguration(newInterface
, kVPNProtocolPayloadInfo
, configuration
);
2333 // special case: Network Pref
2334 configuration
= SCNetworkInterfaceGetExtendedConfiguration(oldInterface
, kSCValNetPPPAuthProtocolEAP
);
2335 if ((configuration
!= NULL
) ||
2336 (SCError() == kSCStatusOK
)) {
2337 (void) SCNetworkInterfaceSetExtendedConfiguration(newInterface
, kSCValNetPPPAuthProtocolEAP
, configuration
);
2340 // special case: Remote Pref
2341 configuration
= SCNetworkInterfaceGetExtendedConfiguration(oldInterface
, kSCEntNetLoginWindowEAPOL
);
2342 if ((configuration
!= NULL
) ||
2343 (SCError() == kSCStatusOK
)) {
2344 (void) SCNetworkInterfaceSetExtendedConfiguration(newInterface
, kSCEntNetLoginWindowEAPOL
, configuration
);
2347 // special case: Network Extension
2348 configuration
= SCNetworkInterfaceGetExtendedConfiguration(oldInterface
, kSCNetworkInterfaceTypeIPSec
);
2349 if ((configuration
!= NULL
) ||
2350 (SCError() == kSCStatusOK
)) {
2351 (void) SCNetworkInterfaceSetExtendedConfiguration(newInterface
, kSCNetworkInterfaceTypeIPSec
, configuration
);
2354 oldInterface
= SCNetworkInterfaceGetInterface(oldInterface
);
2355 newInterface
= SCNetworkInterfaceGetInterface(newInterface
);
2363 __SCNetworkServiceAddProtocolToService(SCNetworkServiceRef service
, CFStringRef protocolType
, CFDictionaryRef configuration
, Boolean enabled
)
2366 SCNetworkProtocolRef protocol
;
2368 protocol
= SCNetworkServiceCopyProtocol(service
, protocolType
);
2370 if ((protocol
== NULL
) &&
2371 (SCError() == kSCStatusNoKey
)) {
2372 ok
= SCNetworkServiceAddProtocolType(service
, protocolType
);
2374 protocol
= SCNetworkServiceCopyProtocol(service
, protocolType
);
2377 if (protocol
!= NULL
) {
2378 SCNetworkProtocolSetConfiguration(protocol
, configuration
);
2379 SCNetworkProtocolSetEnabled(protocol
, enabled
);
2380 CFRelease(protocol
);
2389 __SCNetworkServiceMigrateNew(SCPreferencesRef prefs
,
2390 SCNetworkServiceRef service
,
2391 CFDictionaryRef bsdNameMapping
,
2392 CFDictionaryRef setMapping
,
2393 CFDictionaryRef serviceSetMapping
)
2395 CFStringRef deviceName
= NULL
;
2397 SCNetworkInterfaceRef interface
= NULL
;
2398 CFDictionaryRef interfaceEntity
= NULL
;
2399 SCNetworkSetRef newSet
= NULL
;
2400 SCNetworkInterfaceRef newInterface
= NULL
;
2401 SCNetworkServiceRef newService
= NULL
;
2402 SCNetworkSetRef oldSet
= NULL
;
2403 Boolean serviceAdded
= FALSE
;
2404 CFStringRef serviceID
= NULL
;
2405 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
2406 CFArrayRef setList
= NULL
;
2407 Boolean success
= FALSE
;
2408 CFStringRef targetDeviceName
= NULL
;
2409 CFArrayRef protocols
= NULL
;
2411 if (!isA_SCNetworkService(service
) ||
2412 !isA_SCNetworkInterface(servicePrivate
->interface
) ||
2413 (servicePrivate
->prefs
== NULL
)) {
2416 serviceID
= servicePrivate
->serviceID
;
2418 newService
= SCNetworkServiceCopy(prefs
, serviceID
);
2419 if (newService
!= NULL
) {
2420 // Cannot add service if it already exists
2421 SC_log(LOG_INFO
, "Service already exists");
2425 interface
= SCNetworkServiceGetInterface(service
);
2426 if (interface
== NULL
) {
2427 SC_log(LOG_INFO
, "No interface");
2431 interfaceEntity
= __SCNetworkInterfaceCopyInterfaceEntity(interface
);
2432 if (interfaceEntity
== NULL
) {
2433 SC_log(LOG_INFO
, "No interface entity");
2437 if (bsdNameMapping
!= NULL
) {
2438 deviceName
= CFDictionaryGetValue(interfaceEntity
, kSCPropNetInterfaceDeviceName
);
2439 if (deviceName
!= NULL
) {
2440 targetDeviceName
= CFDictionaryGetValue(bsdNameMapping
, deviceName
);
2441 if (targetDeviceName
!= NULL
) {
2443 CFMutableDictionaryRef newInterfaceEntity
;
2445 SC_log(LOG_INFO
, " mapping \"%@\" --> \"%@\"", deviceName
, targetDeviceName
);
2447 newInterfaceEntity
= CFDictionaryCreateMutableCopy(NULL
, 0, interfaceEntity
);
2450 CFDictionarySetValue(newInterfaceEntity
, kSCPropNetInterfaceDeviceName
, targetDeviceName
);
2452 // update interface name
2453 name
= CFDictionaryGetValue(newInterfaceEntity
, kSCPropUserDefinedName
);
2455 CFMutableStringRef newName
;
2458 * the interface "entity" can include the a UserDefinedName
2459 * like "Ethernet Adapter (en4)". If this interface name is
2460 * mapped to another then we want to ensure that corresponding
2461 * UserDefinedName is also updated to match.
2463 newName
= CFStringCreateMutableCopy(NULL
, 0, name
);
2464 CFStringFindAndReplace(newName
,
2467 CFRangeMake(0, CFStringGetLength(newName
)),
2469 CFDictionarySetValue(newInterfaceEntity
, kSCPropUserDefinedName
, newName
);
2473 CFRelease(interfaceEntity
);
2474 interfaceEntity
= newInterfaceEntity
;
2479 newInterface
= _SCNetworkInterfaceCreateWithEntity(NULL
,
2481 __kSCNetworkInterfaceSearchExternal
);
2483 if ((setMapping
== NULL
) ||
2484 (serviceSetMapping
== NULL
) ||
2485 !CFDictionaryGetValueIfPresent(serviceSetMapping
, service
, (const void **)&setList
)) {
2487 SC_log(LOG_INFO
, "No mapping");
2491 newService
= SCNetworkServiceCreate(prefs
, newInterface
);
2492 if (newService
== NULL
) {
2493 SC_log(LOG_INFO
, "SCNetworkServiceCreate() failed");
2497 enabled
= SCNetworkServiceGetEnabled(service
);
2498 if (!SCNetworkServiceSetEnabled(newService
, enabled
)) {
2499 SCNetworkServiceRemove(newService
);
2500 SC_log(LOG_INFO
, "SCNetworkServiceSetEnabled() failed");
2504 if (!SCNetworkServiceEstablishDefaultConfiguration(newService
)) {
2505 SCNetworkServiceRemove(newService
);
2506 SC_log(LOG_INFO
, "SCNetworkServiceEstablishDefaultConfiguration() failed");
2511 _SCNetworkServiceSetServiceID(newService
, serviceID
);
2513 // Determine which sets to add service
2514 for (CFIndex idx
= 0; idx
< CFArrayGetCount(setList
); idx
++) {
2515 oldSet
= CFArrayGetValueAtIndex(setList
, idx
);
2516 newSet
= CFDictionaryGetValue(setMapping
, oldSet
);
2517 if (newSet
== NULL
) {
2521 SC_log(LOG_INFO
, " adding service to set: %@", SCNetworkSetGetSetID(newSet
));
2522 if (SCNetworkSetAddService(newSet
, newService
)) {
2523 serviceAdded
= TRUE
;
2525 SC_log(LOG_INFO
, "SCNetworkSetAddService() failed");
2529 if (!serviceAdded
) {
2530 SCNetworkServiceRemove(newService
);
2531 SC_log(LOG_INFO
, " service not added to any sets");
2535 protocols
= SCNetworkServiceCopyProtocols(service
);
2536 if (protocols
!= NULL
) {
2538 for (CFIndex idx
= 0; idx
< CFArrayGetCount(protocols
); idx
++) {
2539 SCNetworkProtocolRef protocol
= CFArrayGetValueAtIndex(protocols
, idx
);
2540 CFDictionaryRef configuration
= SCNetworkProtocolGetConfiguration(protocol
);
2541 CFStringRef protocolType
= SCNetworkProtocolGetProtocolType(protocol
);
2542 enabled
= SCNetworkProtocolGetEnabled(protocol
);
2543 __SCNetworkServiceAddProtocolToService(newService
, protocolType
, configuration
, enabled
);
2545 CFRelease(protocols
);
2548 copyInterfaceConfiguration(service
, newService
);
2554 if (interfaceEntity
!= NULL
) {
2555 CFRelease(interfaceEntity
);
2557 if (newInterface
!= NULL
) {
2558 CFRelease(newInterface
);
2560 if (newService
!= NULL
) {
2561 CFRelease(newService
);
2569 __SCNetworkServiceCreate(SCPreferencesRef prefs
,
2570 SCNetworkInterfaceRef interface
,
2571 CFStringRef userDefinedName
)
2573 SCNetworkSetRef currentSet
= NULL
;
2575 SCNetworkServiceRef service
= NULL
;
2577 if (interface
== NULL
) {
2581 if (userDefinedName
== NULL
) {
2582 userDefinedName
= __SCNetworkInterfaceGetUserDefinedName(interface
);
2583 if (userDefinedName
== NULL
) {
2584 SC_log(LOG_INFO
, "No userDefinedName");
2588 service
= SCNetworkServiceCreate(prefs
, interface
);
2589 if (service
== NULL
) {
2590 SC_log(LOG_INFO
, "SCNetworkServiceCreate() failed: %s", SCErrorString(SCError()));
2592 ok
= SCNetworkServiceSetName(service
, userDefinedName
);
2594 SC_log(LOG_INFO
, "SCNetworkServiceSetName() failed: %s", SCErrorString(SCError()));
2595 SCNetworkServiceRemove(service
);
2599 ok
= SCNetworkServiceEstablishDefaultConfiguration(service
);
2601 SC_log(LOG_INFO
, "SCNetworkServiceEstablishDefaultConfiguration() failed: %s", SCErrorString(SCError()));
2602 SCNetworkServiceRemove(service
);
2606 currentSet
= SCNetworkSetCopyCurrent(prefs
);
2607 if (currentSet
== NULL
) {
2608 SC_log(LOG_INFO
, "No current set");
2609 if (service
!= NULL
) {
2610 SCNetworkServiceRemove(service
);
2614 if (service
!= NULL
) {
2615 ok
= SCNetworkSetAddService(currentSet
, service
);
2617 SC_log(LOG_INFO
, "Could not add service to the current set");
2618 SCNetworkServiceRemove(service
);
2624 if (service
!= NULL
) {
2627 if (currentSet
!= NULL
) {
2628 CFRelease(currentSet
);
2633 __private_extern__ Boolean
2634 __SCNetworkServiceIsPPTP(SCNetworkServiceRef service
)
2636 CFStringRef intfSubtype
;
2637 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
2639 if (servicePrivate
== NULL
|| servicePrivate
->interface
== NULL
) {
2643 intfSubtype
= __SCNetworkInterfaceGetEntitySubType(servicePrivate
->interface
);
2644 if (intfSubtype
== NULL
) {
2648 #pragma GCC diagnostic push
2649 #pragma GCC diagnostic ignored "-Wdeprecated"
2650 if (CFEqual(intfSubtype
, kSCValNetInterfaceSubTypePPTP
)) {
2653 #pragma GCC diagnostic pop