2 * Copyright (c) 2004-2017 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 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)cf
;
73 result
= CFStringCreateMutable(allocator
, 0);
74 CFStringAppendFormat(result
, NULL
, CFSTR("<SCNetworkService %p [%p]> {"), cf
, allocator
);
75 CFStringAppendFormat(result
, NULL
, CFSTR("id = %@"), servicePrivate
->serviceID
);
76 if (servicePrivate
->prefs
!= NULL
) {
77 CFStringAppendFormat(result
, NULL
, CFSTR(", prefs = %p"), servicePrivate
->prefs
);
78 } else if (servicePrivate
->store
!= NULL
) {
79 CFStringAppendFormat(result
, NULL
, CFSTR(", store = %p"), servicePrivate
->store
);
81 if (servicePrivate
->name
!= NULL
) {
82 CFStringAppendFormat(result
, NULL
, CFSTR(", name = %@"), servicePrivate
->name
);
84 CFStringAppendFormat(result
, NULL
, CFSTR("}"));
91 __SCNetworkServiceDeallocate(CFTypeRef cf
)
93 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)cf
;
95 /* release resources */
97 CFRelease(servicePrivate
->serviceID
);
98 if (servicePrivate
->interface
!= NULL
) CFRelease(servicePrivate
->interface
);
99 if (servicePrivate
->prefs
!= NULL
) CFRelease(servicePrivate
->prefs
);
100 if (servicePrivate
->store
!= NULL
) CFRelease(servicePrivate
->store
);
101 if (servicePrivate
->name
!= NULL
) CFRelease(servicePrivate
->name
);
102 if (servicePrivate
->externalIDs
!= NULL
) CFRelease(servicePrivate
->externalIDs
);
109 __SCNetworkServiceEqual(CFTypeRef cf1
, CFTypeRef cf2
)
111 SCNetworkServicePrivateRef s1
= (SCNetworkServicePrivateRef
)cf1
;
112 SCNetworkServicePrivateRef s2
= (SCNetworkServicePrivateRef
)cf2
;
117 if (s1
->prefs
!= s2
->prefs
)
118 return FALSE
; // if not the same prefs
120 if (!CFEqual(s1
->serviceID
, s2
->serviceID
))
121 return FALSE
; // if not the same service identifier
128 __SCNetworkServiceHash(CFTypeRef cf
)
130 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)cf
;
132 return CFHash(servicePrivate
->serviceID
);
137 __SCNetworkServiceInitialize(void)
139 __kSCNetworkServiceTypeID
= _CFRuntimeRegisterClass(&__SCNetworkServiceClass
);
144 __private_extern__ SCNetworkServicePrivateRef
145 __SCNetworkServiceCreatePrivate(CFAllocatorRef allocator
,
146 SCPreferencesRef prefs
,
147 CFStringRef serviceID
,
148 SCNetworkInterfaceRef interface
)
150 SCNetworkServicePrivateRef servicePrivate
;
153 /* initialize runtime */
154 pthread_once(&initialized
, __SCNetworkServiceInitialize
);
156 /* allocate target */
157 size
= sizeof(SCNetworkServicePrivate
) - sizeof(CFRuntimeBase
);
158 servicePrivate
= (SCNetworkServicePrivateRef
)_CFRuntimeCreateInstance(allocator
,
159 __kSCNetworkServiceTypeID
,
162 if (servicePrivate
== NULL
) {
166 /* initialize non-zero/NULL members */
167 servicePrivate
->prefs
= (prefs
!= NULL
) ? CFRetain(prefs
): NULL
;
168 servicePrivate
->serviceID
= CFStringCreateCopy(NULL
, serviceID
);
169 servicePrivate
->interface
= (interface
!= NULL
) ? CFRetain(interface
) : NULL
;
171 return servicePrivate
;
176 #pragma mark Service ordering
180 _SCNetworkServiceCompare(const void *val1
, const void *val2
, void *context
)
184 CFArrayRef order
= (CFArrayRef
)context
;
185 SCNetworkServiceRef s1
= (SCNetworkServiceRef
)val1
;
186 SCNetworkServiceRef s2
= (SCNetworkServiceRef
)val2
;
188 id1
= SCNetworkServiceGetServiceID(s1
);
189 id2
= SCNetworkServiceGetServiceID(s2
);
196 range
= CFRangeMake(0, CFArrayGetCount(order
));
197 o1
= CFArrayGetFirstIndexOfValue(order
, range
, id1
);
198 o2
= CFArrayGetFirstIndexOfValue(order
, range
, id2
);
201 return (o2
!= kCFNotFound
) ? kCFCompareGreaterThan
: kCFCompareLessThan
;
202 } else if (o1
< o2
) {
203 return (o1
!= kCFNotFound
) ? kCFCompareLessThan
: kCFCompareGreaterThan
;
207 return CFStringCompare(id1
, id2
, 0);
212 #pragma mark SCNetworkService APIs
218 __private_extern__ CFArrayRef
/* of SCNetworkServiceRef's */
219 __SCNetworkServiceCopyAllEnabled(SCPreferencesRef prefs
)
221 CFMutableArrayRef array
= NULL
;
226 sets
= SCNetworkSetCopyAll(prefs
);
231 n_sets
= CFArrayGetCount(sets
);
232 for (i_sets
= 0; i_sets
< n_sets
; i_sets
++) {
238 set
= CFArrayGetValueAtIndex(sets
, i_sets
);
239 services
= SCNetworkSetCopyServices(set
);
240 if (services
== NULL
) {
244 n_services
= CFArrayGetCount(services
);
245 for (i_services
= 0; i_services
< n_services
; i_services
++) {
246 SCNetworkServiceRef service
;
248 service
= CFArrayGetValueAtIndex(services
, i_services
);
249 if (!SCNetworkServiceGetEnabled(service
)) {
254 if ((array
== NULL
) ||
255 !CFArrayContainsValue(array
,
256 CFRangeMake(0, CFArrayGetCount(array
)),
259 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
261 CFArrayAppendValue(array
, service
);
272 __private_extern__ Boolean
273 __SCNetworkServiceExistsForInterface(CFArrayRef services
, SCNetworkInterfaceRef interface
)
278 n
= isA_CFArray(services
) ? CFArrayGetCount(services
) : 0;
279 for (i
= 0; i
< n
; i
++) {
280 SCNetworkServiceRef service
;
281 SCNetworkInterfaceRef service_interface
;
283 service
= CFArrayGetValueAtIndex(services
, i
);
285 service_interface
= SCNetworkServiceGetInterface(service
);
286 while (service_interface
!= NULL
) {
287 if (CFEqual(interface
, service_interface
)) {
291 service_interface
= SCNetworkInterfaceGetInterface(service_interface
);
300 mergeDict(const void *key
, const void *value
, void *context
)
302 CFMutableDictionaryRef newDict
= (CFMutableDictionaryRef
)context
;
304 CFDictionarySetValue(newDict
, key
, value
);
309 static CF_RETURNS_RETAINED CFDictionaryRef
310 _protocolTemplate(SCNetworkServiceRef service
, CFStringRef protocolType
)
312 SCNetworkInterfaceRef interface
;
313 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
314 CFDictionaryRef
template = NULL
;
316 interface
= servicePrivate
->interface
;
317 if (interface
!= NULL
) {
318 SCNetworkInterfaceRef childInterface
;
319 CFStringRef childInterfaceType
= NULL
;
320 CFStringRef interfaceType
;
323 interfaceType
= SCNetworkInterfaceGetInterfaceType(servicePrivate
->interface
);
324 childInterface
= SCNetworkInterfaceGetInterface(servicePrivate
->interface
);
325 if (childInterface
!= NULL
) {
326 childInterfaceType
= SCNetworkInterfaceGetInterfaceType(childInterface
);
329 template = __copyProtocolTemplate(interfaceType
, childInterfaceType
, protocolType
);
330 if (template != NULL
) {
331 CFDictionaryRef overrides
;
333 // move to the interface at the lowest layer
334 while (childInterface
!= NULL
) {
335 interface
= childInterface
;
336 childInterface
= SCNetworkInterfaceGetInterface(interface
);
339 overrides
= __SCNetworkInterfaceGetTemplateOverrides(interface
, protocolType
);
340 if (overrides
!= NULL
) {
341 CFMutableDictionaryRef newTemplate
;
343 newTemplate
= CFDictionaryCreateMutableCopy(NULL
, 0, template);
344 CFDictionaryApplyFunction(overrides
, mergeDict
, newTemplate
);
346 template = newTemplate
;
351 if (template == NULL
) {
352 template = CFDictionaryCreate(NULL
,
356 &kCFTypeDictionaryKeyCallBacks
,
357 &kCFTypeDictionaryValueCallBacks
);
365 SCNetworkServiceAddProtocolType(SCNetworkServiceRef service
, CFStringRef protocolType
)
367 CFDictionaryRef entity
;
368 CFDictionaryRef newEntity
= NULL
;
371 SCNetworkProtocolRef protocol
;
372 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
374 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
375 _SCErrorSet(kSCStatusInvalidArgument
);
379 if (!__SCNetworkProtocolIsValidType(protocolType
)) {
380 _SCErrorSet(kSCStatusInvalidArgument
);
384 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
385 servicePrivate
->serviceID
, // service
386 protocolType
); // entity
388 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
389 if (entity
!= NULL
) {
390 // if "protocol" already exists
391 _SCErrorSet(kSCStatusKeyExists
);
395 newEntity
= CFDictionaryCreate(NULL
,
399 &kCFTypeDictionaryKeyCallBacks
,
400 &kCFTypeDictionaryValueCallBacks
);
401 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, newEntity
);
402 CFRelease(newEntity
);
407 protocol
= SCNetworkServiceCopyProtocol(service
, protocolType
);
408 assert(protocol
!= NULL
);
410 newEntity
= _protocolTemplate(service
, protocolType
);
411 ok
= SCNetworkProtocolSetConfiguration(protocol
, newEntity
);
412 CFRelease(newEntity
);
418 SC_log(LOG_DEBUG
, "SCNetworkServiceAddProtocolType(): %@, %@", service
, protocolType
);
426 CFArrayRef
/* of SCNetworkServiceRef's */
427 SCNetworkServiceCopyAll(SCPreferencesRef prefs
)
429 CFMutableArrayRef array
;
432 CFDictionaryRef services
;
434 path
= SCPreferencesPathKeyCreateNetworkServices(NULL
);
435 services
= SCPreferencesPathGetValue(prefs
, path
);
438 if ((services
!= NULL
) && !isA_CFDictionary(services
)) {
442 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
444 n
= (services
!= NULL
) ? CFDictionaryGetCount(services
) : 0;
447 const void * keys_q
[N_QUICK
];
448 const void ** keys
= keys_q
;
449 const void * vals_q
[N_QUICK
];
450 const void ** vals
= vals_q
;
452 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
453 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
454 vals
= CFAllocatorAllocate(NULL
, n
* sizeof(CFPropertyListRef
), 0);
456 CFDictionaryGetKeysAndValues(services
, keys
, vals
);
457 for (i
= 0; i
< n
; i
++) {
458 CFDictionaryRef entity
;
459 SCNetworkServicePrivateRef servicePrivate
;
461 if (!isA_CFDictionary(vals
[i
])) {
462 SC_log(LOG_INFO
, "error w/service \"%@\"", keys
[i
]);
466 entity
= CFDictionaryGetValue(vals
[i
], kSCEntNetInterface
);
467 if (!isA_CFDictionary(entity
)) {
469 SC_log(LOG_INFO
, "no \"%@\" entity for service \"%@\"",
475 if (__SCNetworkInterfaceEntityIsPPTP(entity
)) {
476 SC_log(LOG_INFO
, "PPTP services are no longer supported");
480 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, prefs
, keys
[i
], NULL
);
481 assert(servicePrivate
!= NULL
);
482 CFArrayAppendValue(array
, (SCNetworkServiceRef
)servicePrivate
);
483 CFRelease(servicePrivate
);
485 if (keys
!= keys_q
) {
486 CFAllocatorDeallocate(NULL
, keys
);
487 CFAllocatorDeallocate(NULL
, vals
);
496 CFArrayRef
/* of SCNetworkInterfaceRef's */
497 __SCNetworkServiceCopyAllInterfaces(SCPreferencesRef prefs
)
499 CFMutableArrayRef interfaces
= NULL
;
500 CFArrayRef services
= NULL
;
501 CFIndex servicesCount
= 0;
502 SCNetworkServiceRef service
= NULL
;
503 SCNetworkInterfaceRef interface
= NULL
;
505 services
= SCNetworkServiceCopyAll(prefs
);
506 if (services
== NULL
) {
510 servicesCount
= CFArrayGetCount(services
);
511 if (servicesCount
== 0) {
515 interfaces
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
517 for (CFIndex idx
= 0; idx
< servicesCount
; idx
++) {
518 service
= CFArrayGetValueAtIndex(services
, idx
);
519 interface
= SCNetworkServiceGetInterface(service
);
521 if (isA_SCNetworkInterface(interface
) == NULL
) {
524 CFArrayAppendValue(interfaces
, interface
);
527 if (CFArrayGetCount(interfaces
) == 0) {
528 // Do not return an empty array
529 CFRelease(interfaces
);
535 if (services
!= NULL
) {
543 * build a list of all of a services entity types that are associated
544 * with the services interface. The list will include :
546 * - entity types associated with the interface type (Ethernet, FireWire, PPP, ...)
547 * - entity types associated with the interface sub-type (PPPSerial, PPPoE, L2TP, PPTP, ...)
548 * - entity types associated with the hardware device (Ethernet, AirPort, FireWire, Modem, ...)
551 _copyInterfaceEntityTypes(CFDictionaryRef protocols
)
553 CFDictionaryRef interface
;
554 CFMutableSetRef interface_entity_types
;
556 interface_entity_types
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
558 interface
= CFDictionaryGetValue(protocols
, kSCEntNetInterface
);
559 if (isA_CFDictionary(interface
)) {
560 CFStringRef entities
[] = { kSCPropNetInterfaceType
,
561 kSCPropNetInterfaceSubType
,
562 kSCPropNetInterfaceHardware
};
564 // include the "Interface" entity itself
565 CFSetAddValue(interface_entity_types
, kSCEntNetInterface
);
567 // include the entities associated with the interface
568 for (size_t i
= 0; i
< sizeof(entities
)/sizeof(entities
[0]); i
++) {
571 entity
= CFDictionaryGetValue(interface
, entities
[i
]);
572 if (isA_CFString(entity
)) {
573 CFSetAddValue(interface_entity_types
, entity
);
578 * and, because we've found some misguided network preference code
579 * developers leaving [PPP] entity dictionaries around even though
580 * they are unused and/or unneeded...
582 CFSetAddValue(interface_entity_types
, kSCEntNetPPP
);
585 return interface_entity_types
;
590 SCNetworkServiceCopy(SCPreferencesRef prefs
, CFStringRef serviceID
)
592 CFDictionaryRef entity
;
594 SCNetworkServicePrivateRef servicePrivate
;
596 if (!isA_CFString(serviceID
)) {
597 _SCErrorSet(kSCStatusInvalidArgument
);
601 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
602 serviceID
, // service
603 kSCEntNetInterface
); // entity
604 entity
= SCPreferencesPathGetValue(prefs
, path
);
607 if (!isA_CFDictionary(entity
)) {
608 // a "service" must have an "interface"
609 _SCErrorSet(kSCStatusNoKey
);
613 if (__SCNetworkInterfaceEntityIsPPTP(entity
)) {
614 SC_log(LOG_INFO
, "PPTP services are no longer supported");
615 _SCErrorSet(kSCStatusNoKey
);
619 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, prefs
, serviceID
, NULL
);
620 return (SCNetworkServiceRef
)servicePrivate
;
625 _SCNetworkServiceCopyActive(SCDynamicStoreRef store
, CFStringRef serviceID
)
627 SCNetworkServicePrivateRef servicePrivate
;
629 if (!isA_CFString(serviceID
)) {
630 _SCErrorSet(kSCStatusInvalidArgument
);
634 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, NULL
, serviceID
, NULL
);
635 assert(servicePrivate
!= NULL
);
637 servicePrivate
->store
= CFRetain(store
);
639 return (SCNetworkServiceRef
)servicePrivate
;
644 SCNetworkServiceCopyProtocol(SCNetworkServiceRef service
, CFStringRef protocolType
)
646 CFSetRef non_protocol_entities
;
648 CFDictionaryRef protocols
;
649 SCNetworkProtocolPrivateRef protocolPrivate
= NULL
;
650 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
652 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
653 _SCErrorSet(kSCStatusInvalidArgument
);
657 if (!isA_CFString(protocolType
)) {
658 _SCErrorSet(kSCStatusInvalidArgument
);
662 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
663 servicePrivate
->serviceID
, // service
665 protocols
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
668 if (!isA_CFDictionary(protocols
)) {
670 _SCErrorSet(kSCStatusFailed
);
674 non_protocol_entities
= _copyInterfaceEntityTypes(protocols
);
675 if (CFSetContainsValue(non_protocol_entities
, protocolType
)) {
676 // if the "protocolType" matches an interface entity type
677 _SCErrorSet(kSCStatusInvalidArgument
);
681 if (!CFDictionaryContainsKey(protocols
, protocolType
)) {
682 // if the "protocolType" entity does not exist
683 _SCErrorSet(kSCStatusNoKey
);
687 protocolPrivate
= __SCNetworkProtocolCreatePrivate(NULL
, protocolType
, service
);
691 CFRelease(non_protocol_entities
);
693 return (SCNetworkProtocolRef
)protocolPrivate
;
697 CFArrayRef
/* of SCNetworkProtocolRef's */
698 SCNetworkServiceCopyProtocols(SCNetworkServiceRef service
)
700 CFMutableArrayRef array
;
702 CFSetRef non_protocol_entities
;
704 CFDictionaryRef protocols
;
705 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
707 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
708 _SCErrorSet(kSCStatusInvalidArgument
);
712 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
713 servicePrivate
->serviceID
, // service
715 protocols
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
718 if (!isA_CFDictionary(protocols
)) {
720 _SCErrorSet(kSCStatusFailed
);
724 non_protocol_entities
= _copyInterfaceEntityTypes(protocols
);
726 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
728 n
= CFDictionaryGetCount(protocols
);
731 const void * keys_q
[N_QUICK
];
732 const void ** keys
= keys_q
;
733 const void * vals_q
[N_QUICK
];
734 const void ** vals
= vals_q
;
736 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
737 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
738 vals
= CFAllocatorAllocate(NULL
, n
* sizeof(CFPropertyListRef
), 0);
740 CFDictionaryGetKeysAndValues(protocols
, keys
, vals
);
741 for (i
= 0; i
< n
; i
++) {
742 SCNetworkProtocolPrivateRef protocolPrivate
;
744 if (!isA_CFDictionary(vals
[i
])) {
745 // if it's not a dictionary then it can't be a protocol entity
749 if (CFSetContainsValue(non_protocol_entities
, keys
[i
])) {
750 // skip any non-protocol (interface) entities
754 protocolPrivate
= __SCNetworkProtocolCreatePrivate(NULL
, keys
[i
], service
);
755 CFArrayAppendValue(array
, (SCNetworkProtocolRef
)protocolPrivate
);
757 CFRelease(protocolPrivate
);
759 if (keys
!= keys_q
) {
760 CFAllocatorDeallocate(NULL
, keys
);
761 CFAllocatorDeallocate(NULL
, vals
);
765 CFRelease(non_protocol_entities
);
772 __SCNetworkServiceSetInterfaceEntity(SCNetworkServiceRef service
,
773 SCNetworkInterfaceRef interface
)
775 CFDictionaryRef entity
;
778 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
780 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
781 servicePrivate
->serviceID
, // service
782 kSCEntNetInterface
); // entity
783 entity
= __SCNetworkInterfaceCopyInterfaceEntity(interface
);
784 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, entity
);
793 SCNetworkServiceCreate(SCPreferencesRef prefs
, SCNetworkInterfaceRef interface
)
795 CFArrayRef components
;
796 CFArrayRef interface_config
;
797 CFStringRef interface_name
;
798 SCNetworkInterfaceRef newInterface
;
801 CFStringRef serviceID
;
802 SCNetworkServicePrivateRef servicePrivate
;
803 CFArrayRef supported_protocols
;
805 if (!isA_SCNetworkInterface(interface
)) {
806 _SCErrorSet(kSCStatusInvalidArgument
);
810 // only allow network interfaces which support one or more protocols
811 // to be added to a service. The one exception is that we allow
812 // third-party interface types to be configured.
813 supported_protocols
= SCNetworkInterfaceGetSupportedProtocolTypes(interface
);
814 if (supported_protocols
== NULL
) {
815 CFStringRef interface_type
;
817 interface_type
= SCNetworkInterfaceGetInterfaceType(interface
);
818 if (CFStringFind(interface_type
, CFSTR("."), 0).location
== kCFNotFound
) {
819 _SCErrorSet(kSCStatusInvalidArgument
);
824 // do not allow creation of a network service if the interface is a
825 // member of a bond or bridge
826 if (__SCNetworkInterfaceIsMember(prefs
, interface
)) {
827 _SCErrorSet(kSCStatusKeyExists
);
831 // establish the service
832 prefix
= SCPreferencesPathKeyCreateNetworkServices(NULL
);
833 path
= __SCPreferencesPathCreateUniqueChild_WithMoreSCFCompatibility(prefs
, prefix
);
834 if (path
== NULL
) path
= SCPreferencesPathCreateUniqueChild(prefs
, prefix
);
840 components
= CFStringCreateArrayBySeparatingStrings(NULL
, path
, CFSTR("/"));
843 serviceID
= CFArrayGetValueAtIndex(components
, 2);
844 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, prefs
, serviceID
, NULL
);
845 CFRelease(components
);
847 // duplicate the interface and associate the copy with the new service
848 newInterface
= (SCNetworkInterfaceRef
)__SCNetworkInterfaceCreateCopy(NULL
,
852 servicePrivate
->interface
= newInterface
;
854 // establish "default" configuration(s) for the interface
855 for (interface
= newInterface
;
857 interface
= SCNetworkInterfaceGetInterface(interface
)) {
858 SCNetworkInterfaceRef childInterface
;
859 CFStringRef childInterfaceType
= NULL
;
860 CFDictionaryRef config
;
861 CFStringRef interfaceType
;
863 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
864 childInterface
= SCNetworkInterfaceGetInterface(interface
);
865 if (childInterface
!= NULL
) {
866 childInterfaceType
= SCNetworkInterfaceGetInterfaceType(childInterface
);
869 config
= __copyInterfaceTemplate(interfaceType
, childInterfaceType
);
870 if (config
!= NULL
) {
871 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeBluetooth
) ||
872 CFEqual(interfaceType
, kSCNetworkInterfaceTypeIrDA
) ||
873 CFEqual(interfaceType
, kSCNetworkInterfaceTypeModem
) ||
874 CFEqual(interfaceType
, kSCNetworkInterfaceTypeSerial
) ||
875 CFEqual(interfaceType
, kSCNetworkInterfaceTypeWWAN
)) {
876 CFDictionaryRef overrides
;
878 overrides
= __SCNetworkInterfaceGetTemplateOverrides(interface
, kSCNetworkInterfaceTypeModem
);
880 // a ConnectionScript (and related keys) from the interface
881 // should trump the settings from the configuration template.
882 if (overrides
!= NULL
) {
883 CFMutableDictionaryRef newConfig
;
885 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
886 if (CFDictionaryContainsKey(overrides
, kSCPropNetModemConnectionScript
)) {
887 CFDictionaryRemoveValue(newConfig
, kSCPropNetModemConnectionPersonality
);
888 CFDictionaryRemoveValue(newConfig
, kSCPropNetModemConnectionScript
);
889 CFDictionaryRemoveValue(newConfig
, kSCPropNetModemDeviceVendor
);
890 CFDictionaryRemoveValue(newConfig
, kSCPropNetModemDeviceModel
);
892 CFDictionaryApplyFunction(overrides
, mergeDict
, newConfig
);
896 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
) ||
897 CFEqual(interfaceType
, kSCNetworkInterfaceTypeVPN
)) {
898 CFDictionaryRef overrides
;
900 overrides
= __SCNetworkInterfaceGetTemplateOverrides(interface
, kSCNetworkInterfaceTypePPP
);
901 if (overrides
!= NULL
) {
902 CFMutableDictionaryRef newConfig
;
904 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
905 CFDictionaryApplyFunction(overrides
, mergeDict
, newConfig
);
911 if (!__SCNetworkInterfaceSetConfiguration(interface
, NULL
, config
, TRUE
)) {
912 SC_log(LOG_INFO
, "__SCNetworkInterfaceSetConfiguration failed(), interface=%@, type=NULL",
919 // add the interface [entity] to the service
920 (void) __SCNetworkServiceSetInterfaceEntity((SCNetworkServiceRef
)servicePrivate
,
921 servicePrivate
->interface
);
923 // push the [deep] interface configuration into the service.
924 interface_config
= __SCNetworkInterfaceCopyDeepConfiguration(NULL
, servicePrivate
->interface
);
925 __SCNetworkInterfaceSetDeepConfiguration(NULL
, servicePrivate
->interface
, interface_config
);
926 if (interface_config
!= NULL
) CFRelease(interface_config
);
928 // set the service name to match that of the associated interface
930 // Note: It might seem a bit odd to call SCNetworkServiceGetName
931 // followed by an immediate call to SCNetworkServiceSetName. The
932 // trick here is that if no name has previously been set, the
933 // "get" function will return the name of the associated interface.
935 // ... and we "set" a name to ensure that applications that do
936 // not use the APIs will still find a UserDefinedName property
937 // in the SCDynamicStore.
939 interface_name
= SCNetworkServiceGetName((SCNetworkServiceRef
)servicePrivate
);
940 if (interface_name
!= NULL
) {
941 (void) SCNetworkServiceSetName((SCNetworkServiceRef
)servicePrivate
,
945 SC_log(LOG_DEBUG
, "SCNetworkServiceCreate(): %@", servicePrivate
);
947 return (SCNetworkServiceRef
)servicePrivate
;
952 SCNetworkServiceEstablishDefaultConfiguration(SCNetworkServiceRef service
)
955 SCNetworkInterfaceRef interface
;
957 CFArrayRef protocolTypes
;
958 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
960 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
961 _SCErrorSet(kSCStatusInvalidArgument
);
965 interface
= SCNetworkServiceGetInterface(service
);
966 if (interface
== NULL
) {
970 protocolTypes
= SCNetworkInterfaceGetSupportedProtocolTypes(interface
);
971 n
= (protocolTypes
!= NULL
) ? CFArrayGetCount(protocolTypes
) : 0;
972 for (i
= 0; i
< n
; i
++) {
974 CFDictionaryRef newEntity
= NULL
;
976 SCNetworkProtocolRef protocol
= NULL
;
977 CFStringRef protocolType
;
979 protocolType
= CFArrayGetValueAtIndex(protocolTypes
, i
);
980 ok
= SCNetworkServiceAddProtocolType(service
, protocolType
);
981 if (!ok
&& (SCError() != kSCStatusKeyExists
)) {
982 // could not add protocol
986 protocol
= SCNetworkServiceCopyProtocol(service
, protocolType
);
987 if (protocol
== NULL
) {
988 // oops, somethings wrong (should never happen)
992 newEntity
= _protocolTemplate(service
, protocolType
);
993 ok
= SCNetworkProtocolSetConfiguration(protocol
, newEntity
);
995 // could not set default configuration
999 enabled
= !CFDictionaryContainsKey(newEntity
, kSCResvInactive
);
1000 ok
= SCNetworkProtocolSetEnabled(protocol
, enabled
);
1002 // could not enable/disable protocol
1008 if (newEntity
!= NULL
) CFRelease(newEntity
);
1009 if (protocol
!= NULL
) CFRelease(protocol
);
1017 SCNetworkServiceGetEnabled(SCNetworkServiceRef service
)
1021 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1023 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1024 _SCErrorSet(kSCStatusInvalidArgument
);
1028 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1029 servicePrivate
->serviceID
, // service
1031 enabled
= __getPrefsEnabled(servicePrivate
->prefs
, path
);
1038 SCNetworkInterfaceRef
1039 SCNetworkServiceGetInterface(SCNetworkServiceRef service
)
1041 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1043 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1044 _SCErrorSet(kSCStatusInvalidArgument
);
1048 if (servicePrivate
->interface
== NULL
) {
1049 CFDictionaryRef entity
;
1052 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1053 servicePrivate
->serviceID
, // service
1054 kSCEntNetInterface
); // entity
1055 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1058 if (isA_CFDictionary(entity
)) {
1059 servicePrivate
->interface
= _SCNetworkInterfaceCreateWithEntity(NULL
, entity
, service
);
1063 return servicePrivate
->interface
;
1068 SCNetworkServiceGetName(SCNetworkServiceRef service
)
1070 CFDictionaryRef entity
;
1071 SCNetworkInterfaceRef interface
;
1072 CFStringRef name
= NULL
;
1074 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1075 Boolean useSystemInterfaces
= TRUE
;
1077 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1078 _SCErrorSet(kSCStatusInvalidArgument
);
1082 if (servicePrivate
->name
!= NULL
) {
1083 return servicePrivate
->name
;
1086 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1087 servicePrivate
->serviceID
, // service
1089 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1092 useSystemInterfaces
= ((__SCPreferencesUsingDefaultPrefs(servicePrivate
->prefs
)) &&
1093 !__SCPreferencesGetLimitSCNetworkConfiguration(servicePrivate
->prefs
));
1095 if (isA_CFDictionary(entity
)) {
1096 name
= CFDictionaryGetValue(entity
, kSCPropUserDefinedName
);
1097 if (isA_CFString(name
)) {
1098 servicePrivate
->name
= CFRetain(name
);
1099 if (!useSystemInterfaces
) {
1100 return servicePrivate
->name
;
1105 interface
= SCNetworkServiceGetInterface(service
);
1106 while (interface
!= NULL
) {
1107 SCNetworkInterfaceRef childInterface
;
1108 CFStringRef interfaceType
;
1110 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
1111 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeVPN
)) {
1115 childInterface
= SCNetworkInterfaceGetInterface(interface
);
1116 if ((childInterface
== NULL
) ||
1117 CFEqual(childInterface
, kSCNetworkInterfaceIPv4
)) {
1121 interface
= childInterface
;
1124 if (interface
!= NULL
) {
1126 CFStringRef interface_name
= NULL
;
1127 CFStringRef suffix
= NULL
;
1130 // check if the [stored] service name matches the non-localized interface
1131 // name. If so, return the localized name.
1133 // Also, the older "Built-in XXX" interface names are too long for the
1134 // current UI. If we find that the [stored] service name matches the older
1135 // name, return the newer (and shorter) localized name.
1137 // Note: the user/admin will no longer be able to set the service name
1138 // to "Built-in Ethernet".
1140 for (i
= 0; i
< 3; i
++) {
1141 if (servicePrivate
->name
== NULL
) {
1142 // if no [stored] service name to compare
1148 // compare the non-localized interface name
1149 interface_name
= __SCNetworkInterfaceGetNonLocalizedDisplayName(interface
);
1150 if (interface_name
!= NULL
) {
1151 CFRetain(interface_name
);
1154 #if !TARGET_OS_IPHONE
1156 // compare the older "Built-in XXX" localized name
1157 interface_name
= __SCNetworkInterfaceCopyXLocalizedDisplayName(interface
);
1160 // compare the older "Built-in XXX" non-localized name
1161 interface_name
= __SCNetworkInterfaceCopyXNonLocalizedDisplayName(interface
);
1163 #else // !TARGET_OS_IPHONE
1166 #endif // !TARGET_OS_IPHONE
1169 if (interface_name
!= NULL
) {
1170 Boolean match
= FALSE
;
1172 if (CFEqual(name
, interface_name
)) {
1173 // if service name matches the OLD localized
1176 } else if (CFStringHasPrefix(name
, interface_name
)) {
1177 CFIndex prefixLen
= CFStringGetLength(interface_name
);
1178 CFIndex suffixLen
= CFStringGetLength(name
);
1180 suffix
= CFStringCreateWithSubstring(NULL
,
1182 CFRangeMake(prefixLen
, suffixLen
- prefixLen
));
1185 CFRelease(interface_name
);
1188 CFRelease(servicePrivate
->name
);
1189 servicePrivate
->name
= NULL
;
1196 // if the service name has not been set, use the localized interface name
1198 if (servicePrivate
->name
== NULL
) {
1199 interface_name
= SCNetworkInterfaceGetLocalizedDisplayName(interface
);
1200 if (interface_name
!= NULL
) {
1201 if (suffix
!= NULL
) {
1202 servicePrivate
->name
= CFStringCreateWithFormat(NULL
,
1208 servicePrivate
->name
= CFRetain(interface_name
);
1212 if (suffix
!= NULL
) CFRelease(suffix
);
1215 return servicePrivate
->name
;
1220 SCNetworkServiceGetServiceID(SCNetworkServiceRef service
)
1222 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1224 if (!isA_SCNetworkService(service
)) {
1225 _SCErrorSet(kSCStatusInvalidArgument
);
1229 return servicePrivate
->serviceID
;
1234 SCNetworkServiceGetTypeID(void)
1236 pthread_once(&initialized
, __SCNetworkServiceInitialize
); /* initialize runtime */
1237 return __kSCNetworkServiceTypeID
;
1242 SCNetworkServiceRemove(SCNetworkServiceRef service
)
1246 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1249 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1250 _SCErrorSet(kSCStatusInvalidArgument
);
1254 // remove service from all sets
1256 sets
= SCNetworkSetCopyAll(servicePrivate
->prefs
);
1260 n
= CFArrayGetCount(sets
);
1261 for (CFIndex i
= 0; i
< n
; i
++) {
1262 SCNetworkSetRef set
;
1264 set
= CFArrayGetValueAtIndex(sets
, i
);
1265 ok
= SCNetworkSetRemoveService(set
, service
);
1266 if (!ok
&& (SCError() != kSCStatusNoKey
)) {
1276 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1277 servicePrivate
->serviceID
, // service
1279 ok
= SCPreferencesPathRemoveValue(servicePrivate
->prefs
, path
);
1283 SC_log(LOG_DEBUG
, "SCNetworkServiceRemove(): %@", service
);
1291 SCNetworkServiceRemoveProtocolType(SCNetworkServiceRef service
, CFStringRef protocolType
)
1293 CFDictionaryRef entity
;
1296 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1298 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1299 _SCErrorSet(kSCStatusInvalidArgument
);
1303 if (!__SCNetworkProtocolIsValidType(protocolType
)) {
1304 _SCErrorSet(kSCStatusInvalidArgument
);
1308 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1309 servicePrivate
->serviceID
, // service
1310 protocolType
); // entity
1312 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1313 if (entity
== NULL
) {
1314 // if "protocol" does not exist
1315 _SCErrorSet(kSCStatusNoKey
);
1319 ok
= SCPreferencesPathRemoveValue(servicePrivate
->prefs
, path
);
1324 SC_log(LOG_DEBUG
, "SCNetworkServiceRemoveProtocolType(): %@, %@", service
, protocolType
);
1333 SCNetworkServiceSetEnabled(SCNetworkServiceRef service
, Boolean enabled
)
1337 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1339 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1340 _SCErrorSet(kSCStatusInvalidArgument
);
1344 // make sure that we do not enable a network service if the
1345 // associated interface is a member of a bond or bridge.
1347 SCNetworkInterfaceRef interface
;
1349 interface
= SCNetworkServiceGetInterface(service
);
1350 if ((interface
!= NULL
) &&
1351 __SCNetworkInterfaceIsMember(servicePrivate
->prefs
, interface
)) {
1352 _SCErrorSet(kSCStatusKeyExists
);
1357 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1358 servicePrivate
->serviceID
, // service
1360 ok
= __setPrefsEnabled(servicePrivate
->prefs
, path
, enabled
);
1364 SC_log(LOG_DEBUG
, "SCNetworkServiceSetEnabled(): %@ -> %s",
1366 enabled
? "Enabled" : "Disabled");
1374 SCNetworkServiceSetName(SCNetworkServiceRef service
, CFStringRef name
)
1376 CFDictionaryRef entity
;
1379 CFStringRef saveName
= NULL
;
1380 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1382 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1383 _SCErrorSet(kSCStatusInvalidArgument
);
1388 if (!isA_CFString(name
)) {
1389 _SCErrorSet(kSCStatusInvalidArgument
);
1392 saveName
= CFRetain(name
);
1396 SCNetworkInterfaceRef interface
;
1398 interface
= SCNetworkServiceGetInterface(service
);
1399 while (interface
!= NULL
) {
1400 SCNetworkInterfaceRef childInterface
;
1402 childInterface
= SCNetworkInterfaceGetInterface(interface
);
1403 if (childInterface
== NULL
) {
1407 interface
= childInterface
;
1410 if (interface
!= NULL
) {
1411 CFStringRef interface_name
;
1413 interface_name
= SCNetworkInterfaceGetLocalizedDisplayName(interface
);
1414 if (interface_name
!= NULL
) {
1415 if (CFEqual(name
, interface_name
)) {
1416 // if service name matches the localized interface name
1417 // then store the non-localized name.
1418 interface_name
= __SCNetworkInterfaceGetNonLocalizedDisplayName(interface
);
1419 if (interface_name
!= NULL
) {
1420 CFRelease(saveName
);
1421 saveName
= CFRetain(interface_name
);
1423 } else if (CFStringHasPrefix(name
, interface_name
)) {
1424 CFIndex prefixLen
= CFStringGetLength(interface_name
);
1426 CFIndex suffixLen
= CFStringGetLength(name
);
1428 // if service name matches the localized interface name plus
1429 // a few extra characters) then store the non-localized name with
1431 suffix
= CFStringCreateWithSubstring(NULL
,
1433 CFRangeMake(prefixLen
, suffixLen
- prefixLen
));
1434 interface_name
= __SCNetworkInterfaceGetNonLocalizedDisplayName(interface
);
1435 if (interface_name
!= NULL
) {
1436 CFRelease(saveName
);
1437 saveName
= CFStringCreateWithFormat(NULL
,
1449 #define PREVENT_DUPLICATE_SERVICE_NAMES
1450 #ifdef PREVENT_DUPLICATE_SERVICE_NAMES
1454 // ensure that each service is uniquely named within its sets
1456 sets
= SCNetworkSetCopyAll(servicePrivate
->prefs
);
1461 set_count
= CFArrayGetCount(sets
);
1462 for (set_index
= 0; set_index
< set_count
; set_index
++) {
1463 CFIndex service_index
;
1464 Boolean isDup
= FALSE
;
1465 Boolean isMember
= FALSE
;
1466 CFIndex service_count
;
1467 CFArrayRef services
;
1468 SCNetworkSetRef set
= CFArrayGetValueAtIndex(sets
, set_index
);
1470 services
= SCNetworkSetCopyServices(set
);
1472 service_count
= CFArrayGetCount(services
);
1473 for (service_index
= 0; service_index
< service_count
; service_index
++) {
1474 CFStringRef otherID
;
1475 CFStringRef otherName
;
1476 SCNetworkServiceRef otherService
;
1478 otherService
= CFArrayGetValueAtIndex(services
, service_index
);
1480 otherID
= SCNetworkServiceGetServiceID(otherService
);
1481 if (CFEqual(servicePrivate
->serviceID
, otherID
)) {
1482 // if the service is a member of this set
1487 otherName
= SCNetworkServiceGetName(otherService
);
1488 if ((otherName
!= NULL
) && CFEqual(name
, otherName
)) {
1494 CFRelease(services
);
1496 if (isMember
&& isDup
) {
1498 * if this service is a member of the set and
1499 * the "name" is not unique.
1502 if (saveName
!= NULL
) CFRelease(saveName
);
1503 _SCErrorSet(kSCStatusKeyExists
);
1511 #endif /* PREVENT_DUPLICATE_SERVICE_NAMES */
1513 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1514 servicePrivate
->serviceID
, // service
1516 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1517 if (isA_CFDictionary(entity
) ||
1518 ((entity
== NULL
) && (name
!= NULL
))) {
1519 CFMutableDictionaryRef newEntity
;
1521 if (entity
!= NULL
) {
1522 newEntity
= CFDictionaryCreateMutableCopy(NULL
, 0, entity
);
1524 newEntity
= CFDictionaryCreateMutable(NULL
,
1526 &kCFTypeDictionaryKeyCallBacks
,
1527 &kCFTypeDictionaryValueCallBacks
);
1529 if (saveName
!= NULL
) {
1530 CFDictionarySetValue(newEntity
, kSCPropUserDefinedName
, saveName
);
1532 CFDictionaryRemoveValue(newEntity
, kSCPropUserDefinedName
);
1534 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, newEntity
);
1535 CFRelease(newEntity
);
1538 if (saveName
!= NULL
) CFRelease(saveName
);
1540 if (servicePrivate
->name
!= NULL
) CFRelease(servicePrivate
->name
);
1541 if (name
!= NULL
) CFRetain(name
);
1542 servicePrivate
->name
= name
;
1545 SC_log(LOG_DEBUG
, "SCNetworkServiceSetName(): %@", service
);
1553 #pragma mark SCNetworkService SPIs
1556 SCNetworkServicePrimaryRank
1557 SCNetworkServiceGetPrimaryRank(SCNetworkServiceRef service
)
1559 CFDictionaryRef entity
;
1562 SCNetworkServicePrimaryRank rank
= kSCNetworkServicePrimaryRankDefault
;
1563 CFStringRef rankStr
= NULL
;
1564 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1566 if (!isA_SCNetworkService(service
)) {
1567 _SCErrorSet(kSCStatusInvalidArgument
);
1571 if (servicePrivate
->prefs
!= NULL
) {
1572 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
,
1573 servicePrivate
->serviceID
,
1575 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1577 if (isA_CFDictionary(entity
)) {
1578 rankStr
= CFDictionaryGetValue(entity
, kSCPropNetServicePrimaryRank
);
1579 ok
= __str_to_rank(rankStr
, &rank
);
1581 } else if (servicePrivate
->store
!= NULL
) {
1582 path
= SCDynamicStoreKeyCreateNetworkServiceEntity(NULL
,
1583 kSCDynamicStoreDomainState
,
1584 servicePrivate
->serviceID
,
1586 entity
= SCDynamicStoreCopyValue(servicePrivate
->store
, path
);
1588 if (entity
!= NULL
) {
1589 if (isA_CFDictionary(entity
)) {
1590 rankStr
= CFDictionaryGetValue(entity
, kSCPropNetServicePrimaryRank
);
1591 ok
= __str_to_rank(rankStr
, &rank
);
1596 _SCErrorSet(kSCStatusInvalidArgument
);
1601 rank
= kSCNetworkServicePrimaryRankDefault
;
1602 _SCErrorSet(kSCStatusInvalidArgument
);
1603 } else if (rank
== kSCNetworkServicePrimaryRankDefault
) {
1604 _SCErrorSet(kSCStatusOK
);
1612 SCNetworkServiceSetPrimaryRank(SCNetworkServiceRef service
,
1613 SCNetworkServicePrimaryRank newRank
)
1616 CFDictionaryRef entity
;
1617 CFMutableDictionaryRef newEntity
;
1618 CFStringRef path
= NULL
;
1619 CFStringRef rankStr
= NULL
;
1620 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1622 if (!isA_SCNetworkService(service
)) {
1623 _SCErrorSet(kSCStatusInvalidArgument
);
1627 ok
= __rank_to_str(newRank
, &rankStr
);
1629 _SCErrorSet(kSCStatusInvalidArgument
);
1633 if (servicePrivate
->prefs
!= NULL
) {
1635 case kSCNetworkServicePrimaryRankDefault
:
1636 case kSCNetworkServicePrimaryRankNever
:
1637 case kSCNetworkServicePrimaryRankScoped
:
1638 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
,
1639 servicePrivate
->serviceID
,
1641 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1642 if (entity
!= NULL
) {
1643 if (!isA_CFDictionary(entity
)) {
1645 _SCErrorSet(kSCStatusFailed
);
1648 newEntity
= CFDictionaryCreateMutableCopy(NULL
, 0, entity
);
1650 newEntity
= CFDictionaryCreateMutable(NULL
,
1652 &kCFTypeDictionaryKeyCallBacks
,
1653 &kCFTypeDictionaryValueCallBacks
);
1655 if (rankStr
!= NULL
) {
1656 CFDictionarySetValue(newEntity
, kSCPropNetServicePrimaryRank
, rankStr
);
1658 CFDictionaryRemoveValue(newEntity
, kSCPropNetServicePrimaryRank
);
1660 if (CFDictionaryGetCount(newEntity
) > 0) {
1661 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, newEntity
);
1663 ok
= SCPreferencesPathRemoveValue(servicePrivate
->prefs
, path
);
1665 CFRelease(newEntity
);
1671 _SCErrorSet(kSCStatusInvalidArgument
);
1674 } else if (servicePrivate
->store
!= NULL
) {
1675 path
= SCDynamicStoreKeyCreateNetworkServiceEntity(NULL
,
1676 kSCDynamicStoreDomainState
,
1677 servicePrivate
->serviceID
,
1679 entity
= SCDynamicStoreCopyValue(servicePrivate
->store
, path
);
1680 if (entity
!= NULL
) {
1681 if (!isA_CFDictionary(entity
)) {
1684 _SCErrorSet(kSCStatusFailed
);
1687 newEntity
= CFDictionaryCreateMutableCopy(NULL
, 0, entity
);
1690 newEntity
= CFDictionaryCreateMutable(NULL
,
1692 &kCFTypeDictionaryKeyCallBacks
,
1693 &kCFTypeDictionaryValueCallBacks
);
1695 if (rankStr
!= NULL
) {
1696 CFDictionarySetValue(newEntity
, kSCPropNetServicePrimaryRank
, rankStr
);
1698 CFDictionaryRemoveValue(newEntity
, kSCPropNetServicePrimaryRank
);
1700 if (CFDictionaryGetCount(newEntity
) > 0) {
1701 ok
= SCDynamicStoreSetValue(servicePrivate
->store
, path
, newEntity
);
1703 ok
= SCDynamicStoreRemoveValue(servicePrivate
->store
, path
);
1705 CFRelease(newEntity
);
1710 _SCErrorSet(kSCStatusInvalidArgument
);
1716 if (path
!= NULL
) CFRelease(path
);
1722 _SCNetworkServiceIsVPN(SCNetworkServiceRef service
)
1724 SCNetworkInterfaceRef interface
;
1725 CFStringRef interfaceType
;
1727 interface
= SCNetworkServiceGetInterface(service
);
1728 if (interface
== NULL
) {
1732 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
1733 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
)) {
1734 interface
= SCNetworkInterfaceGetInterface(interface
);
1735 if (interface
== NULL
) {
1739 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
1740 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeL2TP
)) {
1743 #pragma GCC diagnostic push
1744 #pragma GCC diagnostic ignored "-Wdeprecated"
1745 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPTP
)) {
1748 #pragma GCC diagnostic pop
1749 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeVPN
)) {
1751 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeIPSec
)) {
1760 SCNetworkServiceSetExternalID(SCNetworkServiceRef service
, CFStringRef identifierDomain
, CFStringRef identifier
)
1762 CFStringRef prefs_path
;
1763 CFDictionaryRef service_dictionary
;
1764 SCNetworkServicePrivateRef service_private
= (SCNetworkServicePrivateRef
)service
;
1765 Boolean success
= FALSE
;
1766 CFStringRef prefixed_domain
;
1768 if (!isA_SCNetworkService(service
) || (service_private
->prefs
== NULL
) || !isA_CFString(identifierDomain
)) {
1769 _SCErrorSet(kSCStatusInvalidArgument
);
1773 if (identifier
!= NULL
&& !isA_CFString(identifier
)) {
1774 _SCErrorSet(kSCStatusInvalidArgument
);
1778 prefixed_domain
= CFStringCreateWithFormat(NULL
, 0, CFSTR("%s%@"), EXTERNAL_ID_DOMAIN_PREFIX
, identifierDomain
);
1780 prefs_path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
,
1781 service_private
->serviceID
,
1784 service_dictionary
= SCPreferencesPathGetValue(service_private
->prefs
, prefs_path
);
1785 if (isA_CFDictionary(service_dictionary
) || ((service_dictionary
== NULL
) && (identifier
!= NULL
))) {
1786 CFMutableDictionaryRef new_service_dictionary
;
1788 if (service_dictionary
!= NULL
) {
1789 new_service_dictionary
= CFDictionaryCreateMutableCopy(NULL
, 0, service_dictionary
);
1791 new_service_dictionary
= CFDictionaryCreateMutable(NULL
,
1793 &kCFTypeDictionaryKeyCallBacks
,
1794 &kCFTypeDictionaryValueCallBacks
);
1797 if (identifier
!= NULL
) {
1798 CFDictionarySetValue(new_service_dictionary
, prefixed_domain
, identifier
);
1800 CFDictionaryRemoveValue(new_service_dictionary
, prefixed_domain
);
1802 success
= SCPreferencesPathSetValue(service_private
->prefs
, prefs_path
, new_service_dictionary
);
1803 CFRelease(new_service_dictionary
);
1805 CFRelease(prefs_path
);
1807 if (identifier
!= NULL
) {
1808 if (service_private
->externalIDs
== NULL
) {
1809 service_private
->externalIDs
= CFDictionaryCreateMutable(NULL
,
1811 &kCFTypeDictionaryKeyCallBacks
,
1812 &kCFTypeDictionaryValueCallBacks
);
1814 CFDictionarySetValue(service_private
->externalIDs
, prefixed_domain
, identifier
);
1816 if (service_private
->externalIDs
!= NULL
) {
1817 CFDictionaryRemoveValue(service_private
->externalIDs
, prefixed_domain
);
1821 CFRelease(prefixed_domain
);
1824 _SCErrorSet(kSCStatusFailed
);
1832 SCNetworkServiceCopyExternalID(SCNetworkServiceRef service
, CFStringRef identifierDomain
)
1834 CFStringRef identifier
= NULL
;
1835 CFStringRef prefixed_domain
;
1836 SCNetworkServicePrivateRef service_private
= (SCNetworkServicePrivateRef
)service
;
1838 if (!isA_SCNetworkService(service
) || (service_private
->prefs
== NULL
) || !isA_CFString(identifierDomain
)) {
1839 _SCErrorSet(kSCStatusInvalidArgument
);
1843 prefixed_domain
= CFStringCreateWithFormat(NULL
, 0, CFSTR("%s%@"), EXTERNAL_ID_DOMAIN_PREFIX
, identifierDomain
);
1845 if (service_private
->externalIDs
!= NULL
) {
1846 identifier
= CFDictionaryGetValue(service_private
->externalIDs
, prefixed_domain
);
1847 if (identifier
!= NULL
) {
1848 CFRetain(identifier
);
1852 if (identifier
== NULL
) {
1853 CFStringRef prefs_path
;
1854 CFDictionaryRef service_dictionary
;
1856 prefs_path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
,
1857 service_private
->serviceID
,
1860 service_dictionary
= SCPreferencesPathGetValue(service_private
->prefs
, prefs_path
);
1861 if (isA_CFDictionary(service_dictionary
)) {
1862 identifier
= CFDictionaryGetValue(service_dictionary
, prefixed_domain
);
1863 if (identifier
!= NULL
) {
1864 CFRetain(identifier
);
1865 if (service_private
->externalIDs
== NULL
) {
1866 service_private
->externalIDs
= CFDictionaryCreateMutable(NULL
,
1868 &kCFTypeDictionaryKeyCallBacks
,
1869 &kCFTypeDictionaryValueCallBacks
);
1871 CFDictionarySetValue(service_private
->externalIDs
, prefixed_domain
, identifier
);
1874 CFRelease(prefs_path
);
1877 CFRelease(prefixed_domain
);
1879 if (identifier
== NULL
) {
1880 _SCErrorSet(kSCStatusNoKey
);
1888 CFStringRef oldServiceID
;
1889 CFStringRef newServiceID
;
1890 } serviceContext
, *serviceContextRef
;
1894 replaceServiceID(const void *value
, void *context
)
1896 CFStringRef link
= NULL
;
1897 CFStringRef oldLink
;
1898 CFMutableArrayRef newServiceOrder
;
1900 serviceContextRef service_context
= (serviceContextRef
)context
;
1901 CFArrayRef serviceOrder
= NULL
;
1902 SCNetworkSetRef set
= (SCNetworkSetRef
)value
;
1903 SCNetworkSetPrivateRef setPrivate
= (SCNetworkSetPrivateRef
)set
;
1905 // update service order
1906 serviceOrder
= SCNetworkSetGetServiceOrder(set
);
1907 if ((isA_CFArray(serviceOrder
) != NULL
) &&
1908 CFArrayContainsValue(serviceOrder
,
1909 CFRangeMake(0, CFArrayGetCount(serviceOrder
)),
1910 service_context
->oldServiceID
)) {
1912 CFIndex serviceOrderIndex
;
1914 // replacing all instances of old service ID with new one
1915 newServiceOrder
= CFArrayCreateMutableCopy(NULL
, 0, serviceOrder
);
1916 count
= CFArrayGetCount(newServiceOrder
);
1917 for (serviceOrderIndex
= 0; serviceOrderIndex
< count
; serviceOrderIndex
++) {
1918 CFStringRef serviceID
;
1920 serviceID
= CFArrayGetValueAtIndex(newServiceOrder
, serviceOrderIndex
);
1921 if (CFEqual(serviceID
, service_context
->oldServiceID
)) {
1922 CFArraySetValueAtIndex(newServiceOrder
, serviceOrderIndex
, service_context
->newServiceID
);
1925 SCNetworkSetSetServiceOrder(set
, newServiceOrder
);
1926 CFRelease(newServiceOrder
);
1929 // check if service with old serviceID is part of the set
1930 path
= SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL
, // allocator
1931 setPrivate
->setID
, // set
1932 service_context
->oldServiceID
, // service
1934 oldLink
= SCPreferencesPathGetLink(setPrivate
->prefs
, path
);
1935 if (oldLink
== NULL
) {
1936 // don't make any changes if service with old serviceID is not found
1940 // remove link between "set" and old "service"
1941 (void) SCPreferencesPathRemoveValue(setPrivate
->prefs
, path
);
1944 // create the link between "set" and the "service"
1945 path
= SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL
, // allocator
1946 setPrivate
->setID
, // set
1947 service_context
->newServiceID
, // service
1949 link
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1950 service_context
->newServiceID
, // service
1952 (void) SCPreferencesPathSetLink(setPrivate
->prefs
, path
, link
);
1968 _SCNetworkServiceSetServiceID(SCNetworkServiceRef service
, CFStringRef newServiceID
)
1970 CFArrayRef allSets
= NULL
;
1971 CFDictionaryRef entity
;
1972 CFStringRef newPath
;
1974 CFStringRef oldPath
= NULL
;
1975 serviceContext service_context
;
1976 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1978 if (!isA_SCNetworkService(service
) || (servicePrivate
->prefs
== NULL
)) {
1979 _SCErrorSet(kSCStatusInvalidArgument
);
1983 if (!isA_CFString(newServiceID
)) {
1984 _SCErrorSet(kSCStatusInvalidArgument
);
1988 if (CFEqual(newServiceID
, servicePrivate
->serviceID
)) {
1989 // no work needs to be done if new service ID is equal to current service ID
1993 newPath
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1994 newServiceID
, // service
1996 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, newPath
);
1997 if (isA_CFDictionary(entity
)) {
1998 // if the new service already exists
1999 _SCErrorSet(kSCStatusKeyExists
);
2003 oldPath
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
2004 servicePrivate
->serviceID
, // service
2006 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, oldPath
);
2007 if (!isA_CFDictionary(entity
)) {
2008 // if the service has already been removed
2009 _SCErrorSet(kSCStatusNoKey
);
2013 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, newPath
, entity
);
2016 ok
= SCPreferencesPathRemoveValue(servicePrivate
->prefs
, oldPath
);
2019 allSets
= SCNetworkSetCopyAll(servicePrivate
->prefs
);
2021 service_context
.newServiceID
= newServiceID
;
2022 service_context
.oldServiceID
= servicePrivate
->serviceID
;
2024 // find all sets w/oldServiceID and update
2025 // ... and update the serviceOrder
2026 CFArrayApplyFunction(allSets
,
2027 CFRangeMake(0, CFArrayGetCount(allSets
)),
2031 if (servicePrivate
->interface
!= NULL
) {
2032 SCNetworkInterfaceRef newInterface
;
2034 // duplicate the interface and associate the copy with the new service ID
2035 newInterface
= (SCNetworkInterfaceRef
)__SCNetworkInterfaceCreateCopy(NULL
,
2036 servicePrivate
->interface
,
2037 servicePrivate
->prefs
,
2039 CFRelease(servicePrivate
->interface
);
2040 servicePrivate
->interface
= newInterface
;
2043 SC_log(LOG_DEBUG
, "_SCNetworkServiceSetServiceID(): %@ --> %@", service
, newServiceID
);
2045 // replace serviceID with new one
2046 CFRetain(newServiceID
);
2047 CFRelease(servicePrivate
->serviceID
);
2048 servicePrivate
->serviceID
= newServiceID
;
2052 if (oldPath
!= NULL
) {
2055 if (newPath
!= NULL
) {
2058 if (allSets
!= NULL
) {
2065 #define kVPNProtocolPayloadInfo CFSTR("com.apple.payload")
2066 #define kSCEntNetLoginWindowEAPOL CFSTR("EAPOL.LoginWindow")
2069 copyInterfaceConfiguration(SCNetworkServiceRef oldService
, SCNetworkServiceRef newService
)
2071 SCNetworkInterfaceRef oldInterface
;
2072 SCNetworkInterfaceRef newInterface
;
2074 oldInterface
= SCNetworkServiceGetInterface(oldService
);
2075 newInterface
= SCNetworkServiceGetInterface(newService
);
2077 while (oldInterface
!= NULL
) {
2078 CFDictionaryRef configuration
;
2079 CFStringRef interfaceType
;
2081 if (newInterface
== NULL
) {
2082 // oops ... interface layering does not match
2086 // copy interface configuration
2087 configuration
= SCNetworkInterfaceGetConfiguration(oldInterface
);
2089 if ((configuration
!= NULL
) ||
2090 (SCError() == kSCStatusOK
)) {
2091 if (!SCNetworkInterfaceSetConfiguration(newInterface
, configuration
)) {
2092 SC_log(LOG_INFO
, "problem setting interface configuration");
2097 // special case: PPP/L2TP + IPSec
2098 interfaceType
= SCNetworkInterfaceGetInterfaceType(oldInterface
);
2099 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
)) {
2100 SCNetworkInterfaceRef childInterface
;
2102 childInterface
= SCNetworkInterfaceGetInterface(oldInterface
);
2103 if (childInterface
!= NULL
) {
2104 CFStringRef childInterfaceType
;
2106 childInterfaceType
= SCNetworkInterfaceGetInterfaceType(childInterface
);
2108 if (CFEqual(childInterfaceType
, kSCNetworkInterfaceTypeL2TP
)) {
2109 configuration
= SCNetworkInterfaceGetExtendedConfiguration(oldInterface
, kSCEntNetIPSec
);
2110 if ((configuration
!= NULL
) ||
2111 (SCError() == kSCStatusOK
)) {
2112 if (!SCNetworkInterfaceSetExtendedConfiguration(newInterface
, kSCEntNetIPSec
, configuration
)) {
2113 SC_log(LOG_INFO
, "problem setting child interface configuration");
2120 // special case: 802.1x
2121 configuration
= SCNetworkInterfaceGetExtendedConfiguration(oldInterface
, kSCEntNetEAPOL
);
2122 if ((configuration
!= NULL
) ||
2123 (SCError() == kSCStatusOK
)) {
2124 (void) SCNetworkInterfaceSetExtendedConfiguration(newInterface
, kSCEntNetEAPOL
, configuration
);
2127 // special case: Managed Client
2128 configuration
= SCNetworkInterfaceGetExtendedConfiguration(oldInterface
, kVPNProtocolPayloadInfo
);
2129 if ((configuration
!= NULL
) ||
2130 (SCError() == kSCStatusOK
)) {
2131 (void) SCNetworkInterfaceSetExtendedConfiguration(newInterface
, kVPNProtocolPayloadInfo
, configuration
);
2134 // special case: Network Pref
2135 configuration
= SCNetworkInterfaceGetExtendedConfiguration(oldInterface
, kSCValNetPPPAuthProtocolEAP
);
2136 if ((configuration
!= NULL
) ||
2137 (SCError() == kSCStatusOK
)) {
2138 (void) SCNetworkInterfaceSetExtendedConfiguration(newInterface
, kSCValNetPPPAuthProtocolEAP
, configuration
);
2141 // special case: Remote Pref
2142 configuration
= SCNetworkInterfaceGetExtendedConfiguration(oldInterface
, kSCEntNetLoginWindowEAPOL
);
2143 if ((configuration
!= NULL
) ||
2144 (SCError() == kSCStatusOK
)) {
2145 (void) SCNetworkInterfaceSetExtendedConfiguration(newInterface
, kSCEntNetLoginWindowEAPOL
, configuration
);
2148 // special case: Network Extension
2149 configuration
= SCNetworkInterfaceGetExtendedConfiguration(oldInterface
, kSCNetworkInterfaceTypeIPSec
);
2150 if ((configuration
!= NULL
) ||
2151 (SCError() == kSCStatusOK
)) {
2152 (void) SCNetworkInterfaceSetExtendedConfiguration(newInterface
, kSCNetworkInterfaceTypeIPSec
, configuration
);
2155 oldInterface
= SCNetworkInterfaceGetInterface(oldInterface
);
2156 newInterface
= SCNetworkInterfaceGetInterface(newInterface
);
2164 __SCNetworkServiceAddProtocolToService(SCNetworkServiceRef service
, CFStringRef protocolType
, CFDictionaryRef configuration
, Boolean enabled
)
2167 SCNetworkProtocolRef protocol
;
2169 protocol
= SCNetworkServiceCopyProtocol(service
, protocolType
);
2171 if ((protocol
== NULL
) &&
2172 (SCError() == kSCStatusNoKey
)) {
2173 ok
= SCNetworkServiceAddProtocolType(service
, protocolType
);
2175 protocol
= SCNetworkServiceCopyProtocol(service
, protocolType
);
2178 if (protocol
!= NULL
) {
2179 SCNetworkProtocolSetConfiguration(protocol
, configuration
);
2180 SCNetworkProtocolSetEnabled(protocol
, enabled
);
2181 CFRelease(protocol
);
2190 __SCNetworkServiceMigrateNew(SCPreferencesRef prefs
,
2191 SCNetworkServiceRef service
,
2192 CFDictionaryRef bsdMapping
,
2193 CFDictionaryRef setMapping
,
2194 CFDictionaryRef serviceSetMapping
)
2196 CFStringRef deviceName
= NULL
;
2198 SCNetworkInterfaceRef interface
= NULL
;
2199 CFDictionaryRef interfaceEntity
= NULL
;
2200 CFMutableDictionaryRef interfaceEntityMutable
= NULL
;
2201 SCNetworkSetRef newSet
= NULL
;
2202 SCPreferencesRef ni_prefs
= NULL
;
2203 SCNetworkInterfaceRef ni_interface
= NULL
;
2204 SCNetworkInterfaceRef oldInterface
= NULL
;
2205 SCNetworkSetRef oldSet
= NULL
;
2206 SCNetworkServiceRef newService
= NULL
;
2207 CFStringRef serviceID
= NULL
;
2208 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
) service
;
2209 CFArrayRef setList
= NULL
;
2210 Boolean success
= FALSE
;
2211 CFStringRef targetDeviceName
= NULL
;
2212 CFStringRef userDefinedName
= NULL
;
2213 CFStringRef userDefinedNameInterface
= NULL
;
2214 CFArrayRef protocols
= NULL
;
2215 CFStringRef subType
;
2217 if ((isA_SCNetworkService(service
) == NULL
) ||
2218 (isA_SCNetworkInterface(servicePrivate
->interface
) == NULL
) ||
2219 (servicePrivate
->prefs
== NULL
)) {
2222 serviceID
= servicePrivate
->serviceID
;
2224 newService
= SCNetworkServiceCopy(prefs
, serviceID
);
2225 if (newService
!= NULL
) {
2226 // Cannot add service if it already exists
2227 SC_log(LOG_INFO
, "Service already exists");
2231 oldInterface
= SCNetworkServiceGetInterface(service
);
2232 interfaceEntity
= __SCNetworkInterfaceCopyInterfaceEntity(oldInterface
);
2233 if (interfaceEntity
== NULL
) {
2234 SC_log(LOG_INFO
, "No interface entity");
2237 interfaceEntityMutable
= CFDictionaryCreateMutableCopy(NULL
, 0, interfaceEntity
);
2239 if (isA_CFDictionary(bsdMapping
) != NULL
) {
2240 deviceName
= CFDictionaryGetValue(interfaceEntityMutable
, kSCPropNetInterfaceDeviceName
);
2241 if (isA_CFString(deviceName
) != NULL
) {
2242 targetDeviceName
= CFDictionaryGetValue(bsdMapping
, deviceName
);
2243 if (targetDeviceName
!= NULL
) {
2245 CFDictionarySetValue(interfaceEntityMutable
, kSCPropNetInterfaceDeviceName
, targetDeviceName
);
2246 ni_prefs
= __SCPreferencesCreateNIPrefsFromPrefs(prefs
);
2247 ni_interface
= __SCNetworkInterfaceCreateWithNIPreferencesUsingBSDName(NULL
, ni_prefs
, targetDeviceName
);
2248 if (ni_interface
!= NULL
) {
2249 userDefinedNameInterface
= __SCNetworkInterfaceGetUserDefinedName(ni_interface
);
2253 if (userDefinedNameInterface
== NULL
) {
2254 userDefinedNameInterface
= CFDictionaryGetValue(interfaceEntityMutable
, kSCPropUserDefinedName
);
2257 subType
= CFDictionaryGetValue(interfaceEntityMutable
, kSCPropNetInterfaceSubType
);
2258 interface
= _SCNetworkInterfaceCreateWithEntity(NULL
, interfaceEntityMutable
, NULL
);
2259 if (userDefinedNameInterface
!= NULL
) {
2260 __SCNetworkInterfaceSetUserDefinedName(interface
, userDefinedNameInterface
);
2262 // Supporting PPPoE subtype
2263 if (subType
!= NULL
&&
2264 CFEqual(subType
, kSCValNetInterfaceSubTypePPPoE
)) {
2265 SCNetworkInterfaceRef childInterface
= SCNetworkInterfaceGetInterface(interface
);
2266 if (childInterface
!= NULL
) {
2267 __SCNetworkInterfaceSetUserDefinedName(childInterface
, userDefinedNameInterface
);
2270 newService
= SCNetworkServiceCreate(prefs
, interface
);
2271 if (newService
== NULL
) {
2272 SC_log(LOG_INFO
, "SCNetworkServiceCreate() failed");
2276 enabled
= SCNetworkServiceGetEnabled(service
);
2277 if (!SCNetworkServiceSetEnabled(newService
, enabled
)) {
2278 SCNetworkServiceRemove(newService
);
2279 SC_log(LOG_INFO
, "SCNetworkServiceSetEnabled() failed");
2283 if (!SCNetworkServiceEstablishDefaultConfiguration(newService
)) {
2284 SCNetworkServiceRemove(newService
);
2285 SC_log(LOG_INFO
, "SCNetworkServiceEstablishDefaultConfiguration() failed");
2290 _SCNetworkServiceSetServiceID(newService
, serviceID
);
2292 userDefinedName
= SCNetworkServiceGetName(service
);
2293 if ((userDefinedName
!= NULL
) &&
2294 !SCNetworkServiceSetName(newService
, userDefinedName
)) {
2295 SC_log(LOG_INFO
, "SCNetworkServiceSetName(, %@) failed", userDefinedName
);
2298 // Determine which sets to add service
2299 if (setMapping
!= NULL
&&
2300 serviceSetMapping
!= NULL
) {
2301 setList
= CFDictionaryGetValue(serviceSetMapping
, service
);
2302 if (setList
!= NULL
) {
2303 for (CFIndex idx
= 0; idx
< CFArrayGetCount(setList
); idx
++) {
2304 oldSet
= CFArrayGetValueAtIndex(setList
, idx
);
2305 newSet
= CFDictionaryGetValue(setMapping
, oldSet
);
2306 if (newSet
== NULL
) {
2310 if (!SCNetworkSetAddService(newSet
, newService
)) {
2311 SC_log(LOG_INFO
, "SCNetworkSetAddService() failed");
2317 protocols
= SCNetworkServiceCopyProtocols(service
);
2318 if (protocols
!= NULL
) {
2320 for (CFIndex idx
= 0; idx
< CFArrayGetCount(protocols
); idx
++) {
2321 SCNetworkProtocolRef protocol
= CFArrayGetValueAtIndex(protocols
, idx
);
2322 CFDictionaryRef configuration
= SCNetworkProtocolGetConfiguration(protocol
);
2323 CFStringRef protocolType
= SCNetworkProtocolGetProtocolType(protocol
);
2324 enabled
= SCNetworkProtocolGetEnabled(protocol
);
2325 __SCNetworkServiceAddProtocolToService(newService
, protocolType
, configuration
, enabled
);
2327 CFRelease(protocols
);
2330 copyInterfaceConfiguration(service
, newService
);
2334 if (interface
!= NULL
) {
2335 CFRelease(interface
);
2337 if (interfaceEntity
!= NULL
) {
2338 CFRelease(interfaceEntity
);
2340 if (interfaceEntityMutable
!= NULL
) {
2341 CFRelease(interfaceEntityMutable
);
2343 if (newService
!= NULL
) {
2344 CFRelease(newService
);
2346 if (ni_prefs
!= NULL
) {
2347 CFRelease(ni_prefs
);
2349 if (ni_interface
!= NULL
) {
2350 CFRelease(ni_interface
);
2358 __SCNetworkServiceCreate(SCPreferencesRef prefs
,
2359 SCNetworkInterfaceRef interface
,
2360 CFStringRef userDefinedName
)
2362 SCNetworkSetRef currentSet
= NULL
;
2364 SCNetworkServiceRef service
= NULL
;
2366 if (interface
== NULL
) {
2370 if (userDefinedName
== NULL
) {
2371 userDefinedName
= __SCNetworkInterfaceGetUserDefinedName(interface
);
2372 if (userDefinedName
== NULL
) {
2373 SC_log(LOG_INFO
, "No userDefinedName");
2377 service
= SCNetworkServiceCreate(prefs
, interface
);
2378 if (service
== NULL
) {
2379 SC_log(LOG_INFO
, "SCNetworkServiceCreate() failed: %s", SCErrorString(SCError()));
2381 ok
= SCNetworkServiceSetName(service
, userDefinedName
);
2383 SC_log(LOG_INFO
, "SCNetworkServiceSetName() failed: %s", SCErrorString(SCError()));
2384 SCNetworkServiceRemove(service
);
2388 ok
= SCNetworkServiceEstablishDefaultConfiguration(service
);
2390 SC_log(LOG_INFO
, "SCNetworkServiceEstablishDefaultConfiguration() failed: %s", SCErrorString(SCError()));
2391 SCNetworkServiceRemove(service
);
2395 currentSet
= SCNetworkSetCopyCurrent(prefs
);
2396 if (currentSet
== NULL
) {
2397 SC_log(LOG_INFO
, "No current set");
2398 if (service
!= NULL
) {
2399 SCNetworkServiceRemove(service
);
2403 if (service
!= NULL
) {
2404 ok
= SCNetworkSetAddService(currentSet
, service
);
2406 SC_log(LOG_INFO
, "Could not add service to the current set");
2407 SCNetworkServiceRemove(service
);
2413 if (service
!= NULL
) {
2416 if (currentSet
!= NULL
) {
2417 CFRelease(currentSet
);
2422 __private_extern__ Boolean
2423 __SCNetworkServiceIsPPTP(SCNetworkServiceRef service
)
2425 CFStringRef intfSubtype
;
2426 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
2428 if (servicePrivate
== NULL
|| servicePrivate
->interface
== NULL
) {
2432 intfSubtype
= __SCNetworkInterfaceGetEntitySubType(servicePrivate
->interface
);
2433 if (intfSubtype
== NULL
) {
2437 #pragma GCC diagnostic push
2438 #pragma GCC diagnostic ignored "-Wdeprecated"
2439 if (CFEqual(intfSubtype
, kSCValNetInterfaceSubTypePPTP
)) {
2442 #pragma GCC diagnostic pop