2 * Copyright (c) 2004-2007 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 * Modification History
27 * May 13, 2004 Allan Nathanson <ajn@apple.com>
32 #include <CoreFoundation/CoreFoundation.h>
33 #include <CoreFoundation/CFRuntime.h>
34 #include <SystemConfiguration/SystemConfiguration.h>
35 #include "SCNetworkConfigurationInternal.h"
36 #include <SystemConfiguration/SCValidation.h>
37 #include <SystemConfiguration/SCPrivate.h>
42 static CFStringRef
__SCNetworkServiceCopyDescription (CFTypeRef cf
);
43 static void __SCNetworkServiceDeallocate (CFTypeRef cf
);
44 static Boolean
__SCNetworkServiceEqual (CFTypeRef cf1
, CFTypeRef cf2
);
45 static CFHashCode
__SCNetworkServiceHash (CFTypeRef cf
);
48 static CFTypeID __kSCNetworkServiceTypeID
= _kCFRuntimeNotATypeID
;
51 static const CFRuntimeClass __SCNetworkServiceClass
= {
53 "SCNetworkService", // className
56 __SCNetworkServiceDeallocate
, // dealloc
57 __SCNetworkServiceEqual
, // equal
58 __SCNetworkServiceHash
, // hash
59 NULL
, // copyFormattingDesc
60 __SCNetworkServiceCopyDescription
// copyDebugDesc
64 static pthread_once_t initialized
= PTHREAD_ONCE_INIT
;
68 __SCNetworkServiceCopyDescription(CFTypeRef cf
)
70 CFAllocatorRef allocator
= CFGetAllocator(cf
);
71 CFMutableStringRef result
;
72 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)cf
;
74 result
= CFStringCreateMutable(allocator
, 0);
75 CFStringAppendFormat(result
, NULL
, CFSTR("<SCNetworkService %p [%p]> {"), cf
, allocator
);
76 CFStringAppendFormat(result
, NULL
, CFSTR("id = %@"), servicePrivate
->serviceID
);
77 CFStringAppendFormat(result
, NULL
, CFSTR(", prefs = %p"), servicePrivate
->prefs
);
78 CFStringAppendFormat(result
, NULL
, CFSTR("}"));
85 __SCNetworkServiceDeallocate(CFTypeRef cf
)
87 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)cf
;
89 /* release resources */
91 CFRelease(servicePrivate
->serviceID
);
92 if (servicePrivate
->interface
!= NULL
) CFRelease(servicePrivate
->interface
);
93 CFRelease(servicePrivate
->prefs
);
100 __SCNetworkServiceEqual(CFTypeRef cf1
, CFTypeRef cf2
)
102 SCNetworkServicePrivateRef s1
= (SCNetworkServicePrivateRef
)cf1
;
103 SCNetworkServicePrivateRef s2
= (SCNetworkServicePrivateRef
)cf2
;
108 if (s1
->prefs
!= s2
->prefs
)
109 return FALSE
; // if not the same prefs
111 if (!CFEqual(s1
->serviceID
, s2
->serviceID
))
112 return FALSE
; // if not the same service identifier
119 __SCNetworkServiceHash(CFTypeRef cf
)
121 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)cf
;
123 return CFHash(servicePrivate
->serviceID
);
128 __SCNetworkServiceInitialize(void)
130 __kSCNetworkServiceTypeID
= _CFRuntimeRegisterClass(&__SCNetworkServiceClass
);
135 __private_extern__ SCNetworkServicePrivateRef
136 __SCNetworkServiceCreatePrivate(CFAllocatorRef allocator
,
137 SCPreferencesRef prefs
,
138 CFStringRef serviceID
,
139 SCNetworkInterfaceRef interface
)
141 SCNetworkServicePrivateRef servicePrivate
;
144 /* initialize runtime */
145 pthread_once(&initialized
, __SCNetworkServiceInitialize
);
147 /* allocate target */
148 size
= sizeof(SCNetworkServicePrivate
) - sizeof(CFRuntimeBase
);
149 servicePrivate
= (SCNetworkServicePrivateRef
)_CFRuntimeCreateInstance(allocator
,
150 __kSCNetworkServiceTypeID
,
153 if (servicePrivate
== NULL
) {
157 servicePrivate
->prefs
= CFRetain(prefs
);
158 servicePrivate
->serviceID
= CFStringCreateCopy(NULL
, serviceID
);
159 servicePrivate
->interface
= (interface
!= NULL
) ? CFRetain(interface
) : NULL
;
161 return servicePrivate
;
166 #pragma mark SCNetworkService APIs
172 static CFDictionaryRef
173 _protocolTemplate(SCNetworkServiceRef service
, CFStringRef protocolType
)
175 CFDictionaryRef newEntity
= NULL
;
176 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
178 if (servicePrivate
->interface
!= NULL
) {
179 SCNetworkInterfaceRef childInterface
;
180 CFStringRef childInterfaceType
= NULL
;
181 CFStringRef interfaceType
;
183 interfaceType
= SCNetworkInterfaceGetInterfaceType(servicePrivate
->interface
);
184 childInterface
= SCNetworkInterfaceGetInterface(servicePrivate
->interface
);
185 if (childInterface
!= NULL
) {
186 childInterfaceType
= SCNetworkInterfaceGetInterfaceType(childInterface
);
189 newEntity
= __copyProtocolTemplate(interfaceType
, childInterfaceType
, protocolType
);
192 if (newEntity
== NULL
) {
193 newEntity
= CFDictionaryCreate(NULL
,
197 &kCFTypeDictionaryKeyCallBacks
,
198 &kCFTypeDictionaryValueCallBacks
);
206 SCNetworkServiceAddProtocolType(SCNetworkServiceRef service
, CFStringRef protocolType
)
208 CFDictionaryRef entity
;
209 CFDictionaryRef newEntity
= NULL
;
212 SCNetworkProtocolRef protocol
;
213 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
215 if (!isA_SCNetworkService(service
)) {
216 _SCErrorSet(kSCStatusInvalidArgument
);
220 if (!__SCNetworkProtocolIsValidType(protocolType
)) {
221 _SCErrorSet(kSCStatusInvalidArgument
);
225 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
226 servicePrivate
->serviceID
, // service
227 protocolType
); // entity
229 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
230 if (entity
!= NULL
) {
231 // if "protocol" already exists
232 _SCErrorSet(kSCStatusKeyExists
);
236 newEntity
= CFDictionaryCreate(NULL
,
240 &kCFTypeDictionaryKeyCallBacks
,
241 &kCFTypeDictionaryValueCallBacks
);
242 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, newEntity
);
243 CFRelease(newEntity
);
248 protocol
= SCNetworkServiceCopyProtocol(service
, protocolType
);
249 newEntity
= _protocolTemplate(service
, protocolType
);
250 ok
= SCNetworkProtocolSetConfiguration(protocol
, newEntity
);
251 CFRelease(newEntity
);
261 CFArrayRef
/* of SCNetworkServiceRef's */
262 SCNetworkServiceCopyAll(SCPreferencesRef prefs
)
264 CFMutableArrayRef array
;
267 CFDictionaryRef services
;
269 path
= SCPreferencesPathKeyCreateNetworkServices(NULL
);
270 services
= SCPreferencesPathGetValue(prefs
, path
);
273 if ((services
!= NULL
) && !isA_CFDictionary(services
)) {
277 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
279 n
= (services
!= NULL
) ? CFDictionaryGetCount(services
) : 0;
282 const void * keys_q
[N_QUICK
];
283 const void ** keys
= keys_q
;
284 const void * vals_q
[N_QUICK
];
285 const void ** vals
= vals_q
;
287 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
288 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
289 vals
= CFAllocatorAllocate(NULL
, n
* sizeof(CFPropertyListRef
), 0);
291 CFDictionaryGetKeysAndValues(services
, keys
, vals
);
292 for (i
= 0; i
< n
; i
++) {
293 CFDictionaryRef entity
;
294 SCNetworkServicePrivateRef servicePrivate
;
296 if (!isA_CFDictionary(vals
[i
])) {
299 CFSTR("SCNetworkServiceCopyAll(): error w/service \"%@\"\n"),
304 entity
= CFDictionaryGetValue(vals
[i
], kSCEntNetInterface
);
305 if (!isA_CFDictionary(entity
)) {
309 CFSTR("SCNetworkServiceCopyAll(): no \"%@\" entity for service \"%@\"\n"),
315 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, prefs
, keys
[i
], NULL
);
316 CFArrayAppendValue(array
, (SCNetworkServiceRef
)servicePrivate
);
317 CFRelease(servicePrivate
);
319 if (keys
!= keys_q
) {
320 CFAllocatorDeallocate(NULL
, keys
);
321 CFAllocatorDeallocate(NULL
, vals
);
330 * build a list of all of a servives entity types that are associated
331 * with the services interface. The list will include :
333 * - entity types associated with the interface type (Ethernet, FireWire, PPP, ...)
334 * - entity types associated with the interface sub-type (PPPSerial, PPPoE, L2TP, PPTP, ...)
335 * - entity types associated with the hardware device (Ethernet, AirPort, FireWire, Modem, ...)
338 _copyInterfaceEntityTypes(CFDictionaryRef protocols
)
340 CFDictionaryRef interface
;
341 CFMutableSetRef interface_entity_types
;
343 interface_entity_types
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
345 interface
= CFDictionaryGetValue(protocols
, kSCEntNetInterface
);
346 if (isA_CFDictionary(interface
)) {
347 CFStringRef entities
[] = { kSCPropNetInterfaceType
,
348 kSCPropNetInterfaceSubType
,
349 kSCPropNetInterfaceHardware
};
352 // include the "Interface" entity itself
353 CFSetAddValue(interface_entity_types
, kSCEntNetInterface
);
355 // include the entities associated with the interface
356 for (i
= 0; i
< sizeof(entities
)/sizeof(entities
[0]); i
++) {
359 entity
= CFDictionaryGetValue(interface
, entities
[i
]);
360 if (isA_CFString(entity
)) {
361 CFSetAddValue(interface_entity_types
, entity
);
366 * and, because we've found some misguided network preference code
367 * developers leaving [PPP] entity dictionaries around even though
368 * they are unused and/or unneeded...
370 CFSetAddValue(interface_entity_types
, kSCEntNetPPP
);
373 return interface_entity_types
;
378 SCNetworkServiceCopy(SCPreferencesRef prefs
, CFStringRef serviceID
)
380 CFDictionaryRef entity
;
382 SCNetworkServicePrivateRef servicePrivate
;
384 if (!isA_CFString(serviceID
)) {
385 _SCErrorSet(kSCStatusInvalidArgument
);
389 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
390 serviceID
, // service
391 kSCEntNetInterface
); // entity
392 entity
= SCPreferencesPathGetValue(prefs
, path
);
395 if (!isA_CFDictionary(entity
)) {
396 // a "service" must have an "interface"
397 _SCErrorSet(kSCStatusNoKey
);
401 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, prefs
, serviceID
, NULL
);
402 return (SCNetworkServiceRef
)servicePrivate
;
407 SCNetworkServiceCopyProtocol(SCNetworkServiceRef service
, CFStringRef protocolType
)
409 CFSetRef non_protocol_entities
;
411 CFDictionaryRef protocols
;
412 SCNetworkProtocolPrivateRef protocolPrivate
= NULL
;
413 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
415 if (!isA_SCNetworkService(service
)) {
416 _SCErrorSet(kSCStatusInvalidArgument
);
420 if (!isA_CFString(protocolType
)) {
421 _SCErrorSet(kSCStatusInvalidArgument
);
425 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
426 servicePrivate
->serviceID
, // service
428 protocols
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
431 if ((protocols
!= NULL
) && !isA_CFDictionary(protocols
)) {
433 _SCErrorSet(kSCStatusFailed
);
437 non_protocol_entities
= _copyInterfaceEntityTypes(protocols
);
438 if (CFSetContainsValue(non_protocol_entities
, protocolType
)) {
439 // if the "protocolType" matches an interface entity type
440 _SCErrorSet(kSCStatusInvalidArgument
);
444 if (!CFDictionaryContainsKey(protocols
, protocolType
)) {
445 // if the "protocolType" entity does not exist
446 _SCErrorSet(kSCStatusNoKey
);
450 protocolPrivate
= __SCNetworkProtocolCreatePrivate(NULL
, protocolType
, service
);
454 CFRelease(non_protocol_entities
);
456 return (SCNetworkProtocolRef
)protocolPrivate
;
460 CFArrayRef
/* of SCNetworkProtocolRef's */
461 SCNetworkServiceCopyProtocols(SCNetworkServiceRef service
)
463 CFMutableArrayRef array
;
465 CFSetRef non_protocol_entities
;
467 CFDictionaryRef protocols
;
468 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
470 if (!isA_SCNetworkService(service
)) {
471 _SCErrorSet(kSCStatusInvalidArgument
);
475 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
476 servicePrivate
->serviceID
, // service
478 protocols
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
481 if (!isA_CFDictionary(protocols
)) {
485 non_protocol_entities
= _copyInterfaceEntityTypes(protocols
);
487 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
489 n
= CFDictionaryGetCount(protocols
);
492 const void * keys_q
[N_QUICK
];
493 const void ** keys
= keys_q
;
494 const void * vals_q
[N_QUICK
];
495 const void ** vals
= vals_q
;
497 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
498 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
499 vals
= CFAllocatorAllocate(NULL
, n
* sizeof(CFPropertyListRef
), 0);
501 CFDictionaryGetKeysAndValues(protocols
, keys
, vals
);
502 for (i
= 0; i
< n
; i
++) {
503 SCNetworkProtocolPrivateRef protocolPrivate
;
505 if (!isA_CFDictionary(vals
[i
])) {
506 // if it's not a dictionary then it can't be a protocol entity
510 if (CFSetContainsValue(non_protocol_entities
, keys
[i
])) {
511 // skip any non-protocol (interface) entities
515 protocolPrivate
= __SCNetworkProtocolCreatePrivate(NULL
, keys
[i
], service
);
516 CFArrayAppendValue(array
, (SCNetworkProtocolRef
)protocolPrivate
);
518 CFRelease(protocolPrivate
);
520 if (keys
!= keys_q
) {
521 CFAllocatorDeallocate(NULL
, keys
);
522 CFAllocatorDeallocate(NULL
, vals
);
526 CFRelease(non_protocol_entities
);
533 __SCNetworkServiceSetInterfaceEntity(SCNetworkServiceRef service
,
534 SCNetworkInterfaceRef interface
)
536 CFDictionaryRef entity
;
539 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
541 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
542 servicePrivate
->serviceID
, // service
543 kSCEntNetInterface
); // entity
544 entity
= __SCNetworkInterfaceCopyInterfaceEntity(interface
);
545 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, entity
);
554 mergeDict(const void *key
, const void *value
, void *context
)
556 CFMutableDictionaryRef newDict
= (CFMutableDictionaryRef
)context
;
558 CFDictionarySetValue(newDict
, key
, value
);
564 SCNetworkServiceCreate(SCPreferencesRef prefs
, SCNetworkInterfaceRef interface
)
566 CFArrayRef components
;
567 CFArrayRef interface_config
;
568 CFStringRef interface_name
;
569 SCNetworkInterfaceRef newInterface
;
572 CFStringRef serviceID
;
573 SCNetworkServicePrivateRef servicePrivate
;
574 CFArrayRef supported_protocols
;
576 if (!isA_SCNetworkInterface(interface
)) {
577 _SCErrorSet(kSCStatusInvalidArgument
);
581 // only allow network interfaces which support one or more protocols
582 // to be added to a service. The one exception is that we allow
583 // third-party interface types to be configured.
584 supported_protocols
= SCNetworkInterfaceGetSupportedProtocolTypes(interface
);
585 if (supported_protocols
== NULL
) {
586 CFStringRef interface_type
;
588 interface_type
= SCNetworkInterfaceGetInterfaceType(interface
);
589 if (CFStringFind(interface_type
, CFSTR("."), 0).location
== kCFNotFound
) {
594 // establish the service
595 prefix
= SCPreferencesPathKeyCreateNetworkServices(NULL
);
596 path
= __SCPreferencesPathCreateUniqueChild_WithMoreSCFCompatibility(prefs
, prefix
);
597 if (path
== NULL
) path
= SCPreferencesPathCreateUniqueChild(prefs
, prefix
);
603 components
= CFStringCreateArrayBySeparatingStrings(NULL
, path
, CFSTR("/"));
606 serviceID
= CFArrayGetValueAtIndex(components
, 2);
607 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, prefs
, serviceID
, NULL
);
608 CFRelease(components
);
610 // duplicate the interface and associate the copy with the new service
611 newInterface
= (SCNetworkInterfaceRef
)__SCNetworkInterfaceCreateCopy(NULL
,
615 servicePrivate
->interface
= newInterface
;
617 // establish "default" configuration(s) for the interface
618 for (interface
= newInterface
;
620 interface
= SCNetworkInterfaceGetInterface(interface
)) {
621 SCNetworkInterfaceRef childInterface
;
622 CFStringRef childInterfaceType
= NULL
;
623 CFDictionaryRef config
;
624 CFStringRef interfaceType
;
626 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
627 childInterface
= SCNetworkInterfaceGetInterface(interface
);
628 if (childInterface
!= NULL
) {
629 childInterfaceType
= SCNetworkInterfaceGetInterfaceType(childInterface
);
632 config
= __copyInterfaceTemplate(interfaceType
, childInterfaceType
);
633 if (config
!= NULL
) {
634 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeBluetooth
) ||
635 CFEqual(interfaceType
, kSCNetworkInterfaceTypeIrDA
) ||
636 CFEqual(interfaceType
, kSCNetworkInterfaceTypeModem
) ||
637 CFEqual(interfaceType
, kSCNetworkInterfaceTypeSerial
) ||
638 CFEqual(interfaceType
, kSCNetworkInterfaceTypeWWAN
)) {
639 CFDictionaryRef overrides
;
642 overrides
= __SCNetworkInterfaceGetTemplateOverrides(interface
, kSCNetworkInterfaceTypeModem
);
644 // a ConnectionScript (and related keys) from the interface
645 // should trump the settings from the configuration template.
646 if ((overrides
!= NULL
) &&
647 CFDictionaryContainsKey(overrides
, kSCPropNetModemConnectionScript
)) {
648 CFMutableDictionaryRef newConfig
;
650 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
651 CFDictionaryRemoveValue(newConfig
, kSCPropNetModemConnectionPersonality
);
652 CFDictionaryRemoveValue(newConfig
, kSCPropNetModemConnectionScript
);
653 CFDictionaryRemoveValue(newConfig
, kSCPropNetModemDeviceVendor
);
654 CFDictionaryRemoveValue(newConfig
, kSCPropNetModemDeviceModel
);
659 // update template for v.92 modems
660 if ((overrides
== NULL
) &&
661 CFDictionaryGetValueIfPresent(config
,
662 kSCPropNetModemConnectionScript
,
663 (const void **)&script
) &&
664 CFEqual(script
, CFSTR("v.34 Personality")) &&
665 _SCNetworkInterfaceIsModemV92(interface
)) {
666 CFMutableDictionaryRef newConfig
;
668 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
669 CFDictionarySetValue(newConfig
,
670 kSCPropNetModemConnectionPersonality
,
671 CFSTR("v.92 Personality"));
672 CFDictionarySetValue(newConfig
,
673 kSCPropNetModemDeviceModel
,
674 CFSTR("Apple Modem (v.92)"));
679 if (overrides
!= NULL
) {
680 CFMutableDictionaryRef newConfig
;
682 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
683 CFDictionaryApplyFunction(overrides
, mergeDict
, newConfig
);
687 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
)) {
688 CFDictionaryRef overrides
;
690 overrides
= __SCNetworkInterfaceGetTemplateOverrides(interface
, kSCNetworkInterfaceTypePPP
);
691 if (overrides
!= NULL
) {
692 CFMutableDictionaryRef newConfig
;
694 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
695 CFDictionaryApplyFunction(overrides
, mergeDict
, newConfig
);
701 if (!__SCNetworkInterfaceSetConfiguration(interface
, NULL
, config
, TRUE
)) {
702 SCLog(TRUE
, LOG_DEBUG
,
703 CFSTR("SCNetworkService __SCNetworkInterfaceSetConfiguration failed(), interface=%@, type=NULL"),
710 // add the interface [entity] to the service
711 (void) __SCNetworkServiceSetInterfaceEntity((SCNetworkServiceRef
)servicePrivate
,
712 servicePrivate
->interface
);
714 // push the [deep] interface configuration into the service.
715 interface_config
= __SCNetworkInterfaceCopyDeepConfiguration(servicePrivate
->interface
);
716 __SCNetworkInterfaceSetDeepConfiguration(servicePrivate
->interface
, interface_config
);
717 if (interface_config
!= NULL
) CFRelease(interface_config
);
719 // set the service name to match that of the associated interface
721 // Note: It might seem a bit odd to call SCNetworkServiceGetName
722 // followed by an immediate call to SCNetworkServiceSetName. The
723 // trick here is that if no name has previously been set, the
724 // "get" function will return the name of the associated interface.
726 // ... and we "set" a name to ensure that applications that do
727 // not use the APIs will still find a UserDefinedName property
728 // in the SCDynamicStore.
730 interface_name
= SCNetworkServiceGetName((SCNetworkServiceRef
)servicePrivate
);
731 if (interface_name
!= NULL
) {
732 (void) SCNetworkServiceSetName((SCNetworkServiceRef
)servicePrivate
,
736 return (SCNetworkServiceRef
)servicePrivate
;
741 SCNetworkServiceEstablishDefaultConfiguration(SCNetworkServiceRef service
)
744 SCNetworkInterfaceRef interface
;
746 CFArrayRef protocolTypes
;
748 interface
= SCNetworkServiceGetInterface(service
);
749 if (interface
== NULL
) {
753 protocolTypes
= SCNetworkInterfaceGetSupportedProtocolTypes(interface
);
754 n
= (protocolTypes
!= NULL
) ? CFArrayGetCount(protocolTypes
) : 0;
755 for (i
= 0; i
< n
; i
++) {
757 CFDictionaryRef newEntity
= NULL
;
759 SCNetworkProtocolRef protocol
= NULL
;
760 CFStringRef protocolType
;
762 protocolType
= CFArrayGetValueAtIndex(protocolTypes
, i
);
763 ok
= SCNetworkServiceAddProtocolType(service
, protocolType
);
764 if (!ok
&& (SCError() != kSCStatusKeyExists
)) {
765 // could not add protocol
769 protocol
= SCNetworkServiceCopyProtocol(service
, protocolType
);
770 if (protocol
== NULL
) {
771 // oops, somethings wrong (should never happen)
775 newEntity
= _protocolTemplate(service
, protocolType
);
776 ok
= SCNetworkProtocolSetConfiguration(protocol
, newEntity
);
778 // could not set default configuration
782 enabled
= !CFDictionaryContainsKey(newEntity
, kSCResvInactive
);
783 ok
= SCNetworkProtocolSetEnabled(protocol
, enabled
);
785 // could not enable/disable protocol
791 if (newEntity
!= NULL
) CFRelease(newEntity
);
792 if (protocol
!= NULL
) CFRelease(protocol
);
800 SCNetworkServiceGetEnabled(SCNetworkServiceRef service
)
804 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
806 if (!isA_SCNetworkService(service
)) {
807 _SCErrorSet(kSCStatusInvalidArgument
);
811 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
812 servicePrivate
->serviceID
, // service
814 enabled
= __getPrefsEnabled(servicePrivate
->prefs
, path
);
821 SCNetworkInterfaceRef
822 SCNetworkServiceGetInterface(SCNetworkServiceRef service
)
824 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
826 if (!isA_SCNetworkService(service
)) {
827 _SCErrorSet(kSCStatusInvalidArgument
);
831 if (servicePrivate
->interface
== NULL
) {
832 CFDictionaryRef entity
;
835 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
836 servicePrivate
->serviceID
, // service
837 kSCEntNetInterface
); // entity
838 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
841 if (isA_CFDictionary(entity
)) {
842 servicePrivate
->interface
= _SCNetworkInterfaceCreateWithEntity(NULL
, entity
, service
);
846 return servicePrivate
->interface
;
851 SCNetworkServiceGetName(SCNetworkServiceRef service
)
853 CFDictionaryRef entity
;
854 SCNetworkInterfaceRef interface
;
855 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
856 CFStringRef name
= NULL
;
859 if (!isA_SCNetworkService(service
)) {
860 _SCErrorSet(kSCStatusInvalidArgument
);
864 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
865 servicePrivate
->serviceID
, // service
867 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
870 if (isA_CFDictionary(entity
)) {
871 name
= CFDictionaryGetValue(entity
, kSCPropUserDefinedName
);
872 name
= isA_CFString(name
);
875 interface
= SCNetworkServiceGetInterface(service
);
876 while (interface
!= NULL
) {
877 SCNetworkInterfaceRef childInterface
;
879 childInterface
= SCNetworkInterfaceGetInterface(interface
);
880 if (childInterface
== NULL
) {
884 interface
= childInterface
;
887 if (interface
!= NULL
) {
889 CFStringRef interface_name
;
891 interface_name
= __SCNetworkInterfaceGetNonLocalizedDisplayName(interface
);
892 if ((interface_name
!= NULL
) && CFEqual(name
, interface_name
)) {
893 // if service name matches the [non-]localized
900 name
= SCNetworkInterfaceGetLocalizedDisplayName(interface
);
909 SCNetworkServiceGetServiceID(SCNetworkServiceRef service
)
911 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
913 if (!isA_SCNetworkService(service
)) {
914 _SCErrorSet(kSCStatusInvalidArgument
);
918 return servicePrivate
->serviceID
;
923 SCNetworkServiceGetTypeID(void)
925 pthread_once(&initialized
, __SCNetworkServiceInitialize
); /* initialize runtime */
926 return __kSCNetworkServiceTypeID
;
931 SCNetworkServiceRemove(SCNetworkServiceRef service
)
934 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
938 if (!isA_SCNetworkService(service
)) {
939 _SCErrorSet(kSCStatusInvalidArgument
);
943 // remove service from all sets
945 sets
= SCNetworkSetCopyAll(servicePrivate
->prefs
);
950 n
= CFArrayGetCount(sets
);
951 for (i
= 0; i
< n
; i
++) {
954 set
= CFArrayGetValueAtIndex(sets
, i
);
955 ok
= SCNetworkSetRemoveService(set
, service
);
956 if (!ok
&& (SCError() != kSCStatusNoKey
)) {
966 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
967 servicePrivate
->serviceID
, // service
969 ok
= SCPreferencesPathRemoveValue(servicePrivate
->prefs
, path
);
977 SCNetworkServiceRemoveProtocolType(SCNetworkServiceRef service
, CFStringRef protocolType
)
979 CFDictionaryRef entity
;
982 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
984 if (!isA_SCNetworkService(service
)) {
985 _SCErrorSet(kSCStatusInvalidArgument
);
989 if (!__SCNetworkProtocolIsValidType(protocolType
)) {
990 _SCErrorSet(kSCStatusInvalidArgument
);
994 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
995 servicePrivate
->serviceID
, // service
996 protocolType
); // entity
998 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
999 if (entity
== NULL
) {
1000 // if "protocol" does not exist
1001 _SCErrorSet(kSCStatusNoKey
);
1005 ok
= SCPreferencesPathRemoveValue(servicePrivate
->prefs
, path
);
1015 SCNetworkServiceSetEnabled(SCNetworkServiceRef service
, Boolean enabled
)
1019 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1021 if (!isA_SCNetworkService(service
)) {
1022 _SCErrorSet(kSCStatusInvalidArgument
);
1026 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1027 servicePrivate
->serviceID
, // service
1029 ok
= __setPrefsEnabled(servicePrivate
->prefs
, path
, enabled
);
1037 SCNetworkServiceSetName(SCNetworkServiceRef service
, CFStringRef name
)
1039 CFDictionaryRef entity
;
1042 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1044 if (!isA_SCNetworkService(service
)) {
1045 _SCErrorSet(kSCStatusInvalidArgument
);
1049 if ((name
!= NULL
) && !isA_CFString(name
)) {
1050 _SCErrorSet(kSCStatusInvalidArgument
);
1055 SCNetworkInterfaceRef interface
;
1057 interface
= SCNetworkServiceGetInterface(service
);
1058 while (interface
!= NULL
) {
1059 SCNetworkInterfaceRef childInterface
;
1061 childInterface
= SCNetworkInterfaceGetInterface(interface
);
1062 if (childInterface
== NULL
) {
1066 interface
= childInterface
;
1069 if (interface
!= NULL
) {
1070 CFStringRef interface_name
;
1072 interface_name
= SCNetworkInterfaceGetLocalizedDisplayName(interface
);
1073 if ((interface_name
!= NULL
) && CFEqual(name
, interface_name
)) {
1074 // if service name matches the localized interface name
1075 // then store the non-localized name.
1076 interface_name
= __SCNetworkInterfaceGetNonLocalizedDisplayName(interface
);
1077 if (interface_name
!= NULL
) {
1078 name
= interface_name
;
1084 #define PREVENT_DUPLICATE_SERVICE_NAMES
1085 #ifdef PREVENT_DUPLICATE_SERVICE_NAMES
1089 // ensure that each service is uniquely named within its sets
1091 sets
= SCNetworkSetCopyAll(servicePrivate
->prefs
);
1096 set_count
= CFArrayGetCount(sets
);
1097 for (set_index
= 0; set_index
< set_count
; set_index
++) {
1098 CFIndex service_index
;
1099 Boolean isDup
= FALSE
;
1100 Boolean isMember
= FALSE
;
1101 CFIndex service_count
;
1102 CFArrayRef services
;
1103 SCNetworkSetRef set
= CFArrayGetValueAtIndex(sets
, set_index
);
1105 services
= SCNetworkSetCopyServices(set
);
1107 service_count
= CFArrayGetCount(services
);
1108 for (service_index
= 0; service_index
< service_count
; service_index
++) {
1109 CFStringRef otherID
;
1110 CFStringRef otherName
;
1111 SCNetworkServiceRef otherService
;
1113 otherService
= CFArrayGetValueAtIndex(services
, service_index
);
1115 otherID
= SCNetworkServiceGetServiceID(otherService
);
1116 if (CFEqual(servicePrivate
->serviceID
, otherID
)) {
1117 // if the service is a member of this set
1122 otherName
= SCNetworkServiceGetName(otherService
);
1123 if ((otherName
!= NULL
) && CFEqual(name
, otherName
)) {
1129 CFRelease(services
);
1131 if (isMember
&& isDup
) {
1133 * if this service is a member of the set and
1134 * the "name" is not unique.
1137 _SCErrorSet(kSCStatusKeyExists
);
1145 #endif /* PREVENT_DUPLICATE_SERVICE_NAMES */
1147 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1148 servicePrivate
->serviceID
, // service
1150 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1151 if ((entity
== NULL
) && (name
!= NULL
)) {
1152 entity
= CFDictionaryCreate(NULL
,
1156 &kCFTypeDictionaryKeyCallBacks
,
1157 &kCFTypeDictionaryValueCallBacks
);
1159 if (isA_CFDictionary(entity
)) {
1160 CFMutableDictionaryRef newEntity
;
1162 newEntity
= CFDictionaryCreateMutableCopy(NULL
, 0, entity
);
1164 CFDictionarySetValue(newEntity
, kSCPropUserDefinedName
, name
);
1166 CFDictionaryRemoveValue(newEntity
, kSCPropUserDefinedName
);
1168 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, newEntity
);
1169 CFRelease(newEntity
);