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 if (servicePrivate
->name
!= NULL
) {
79 CFStringAppendFormat(result
, NULL
, CFSTR(", name = %@"), servicePrivate
->name
);
81 CFStringAppendFormat(result
, NULL
, CFSTR("}"));
88 __SCNetworkServiceDeallocate(CFTypeRef cf
)
90 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)cf
;
92 /* release resources */
94 CFRelease(servicePrivate
->serviceID
);
95 if (servicePrivate
->interface
!= NULL
) CFRelease(servicePrivate
->interface
);
96 CFRelease(servicePrivate
->prefs
);
97 if (servicePrivate
->name
!= NULL
) CFRelease(servicePrivate
->name
);
104 __SCNetworkServiceEqual(CFTypeRef cf1
, CFTypeRef cf2
)
106 SCNetworkServicePrivateRef s1
= (SCNetworkServicePrivateRef
)cf1
;
107 SCNetworkServicePrivateRef s2
= (SCNetworkServicePrivateRef
)cf2
;
112 if (s1
->prefs
!= s2
->prefs
)
113 return FALSE
; // if not the same prefs
115 if (!CFEqual(s1
->serviceID
, s2
->serviceID
))
116 return FALSE
; // if not the same service identifier
123 __SCNetworkServiceHash(CFTypeRef cf
)
125 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)cf
;
127 return CFHash(servicePrivate
->serviceID
);
132 __SCNetworkServiceInitialize(void)
134 __kSCNetworkServiceTypeID
= _CFRuntimeRegisterClass(&__SCNetworkServiceClass
);
139 __private_extern__ SCNetworkServicePrivateRef
140 __SCNetworkServiceCreatePrivate(CFAllocatorRef allocator
,
141 SCPreferencesRef prefs
,
142 CFStringRef serviceID
,
143 SCNetworkInterfaceRef interface
)
145 SCNetworkServicePrivateRef servicePrivate
;
148 /* initialize runtime */
149 pthread_once(&initialized
, __SCNetworkServiceInitialize
);
151 /* allocate target */
152 size
= sizeof(SCNetworkServicePrivate
) - sizeof(CFRuntimeBase
);
153 servicePrivate
= (SCNetworkServicePrivateRef
)_CFRuntimeCreateInstance(allocator
,
154 __kSCNetworkServiceTypeID
,
157 if (servicePrivate
== NULL
) {
161 servicePrivate
->prefs
= CFRetain(prefs
);
162 servicePrivate
->serviceID
= CFStringCreateCopy(NULL
, serviceID
);
163 servicePrivate
->interface
= (interface
!= NULL
) ? CFRetain(interface
) : NULL
;
164 servicePrivate
->name
= NULL
;
166 return servicePrivate
;
171 #pragma mark SCNetworkService APIs
177 static CFDictionaryRef
178 _protocolTemplate(SCNetworkServiceRef service
, CFStringRef protocolType
)
180 CFDictionaryRef newEntity
= NULL
;
181 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
183 if (servicePrivate
->interface
!= NULL
) {
184 SCNetworkInterfaceRef childInterface
;
185 CFStringRef childInterfaceType
= NULL
;
186 CFStringRef interfaceType
;
188 interfaceType
= SCNetworkInterfaceGetInterfaceType(servicePrivate
->interface
);
189 childInterface
= SCNetworkInterfaceGetInterface(servicePrivate
->interface
);
190 if (childInterface
!= NULL
) {
191 childInterfaceType
= SCNetworkInterfaceGetInterfaceType(childInterface
);
194 newEntity
= __copyProtocolTemplate(interfaceType
, childInterfaceType
, protocolType
);
197 if (newEntity
== NULL
) {
198 newEntity
= CFDictionaryCreate(NULL
,
202 &kCFTypeDictionaryKeyCallBacks
,
203 &kCFTypeDictionaryValueCallBacks
);
211 SCNetworkServiceAddProtocolType(SCNetworkServiceRef service
, CFStringRef protocolType
)
213 CFDictionaryRef entity
;
214 CFDictionaryRef newEntity
= NULL
;
217 SCNetworkProtocolRef protocol
;
218 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
220 if (!isA_SCNetworkService(service
)) {
221 _SCErrorSet(kSCStatusInvalidArgument
);
225 if (!__SCNetworkProtocolIsValidType(protocolType
)) {
226 _SCErrorSet(kSCStatusInvalidArgument
);
230 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
231 servicePrivate
->serviceID
, // service
232 protocolType
); // entity
234 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
235 if (entity
!= NULL
) {
236 // if "protocol" already exists
237 _SCErrorSet(kSCStatusKeyExists
);
241 newEntity
= CFDictionaryCreate(NULL
,
245 &kCFTypeDictionaryKeyCallBacks
,
246 &kCFTypeDictionaryValueCallBacks
);
247 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, newEntity
);
248 CFRelease(newEntity
);
253 protocol
= SCNetworkServiceCopyProtocol(service
, protocolType
);
254 newEntity
= _protocolTemplate(service
, protocolType
);
255 ok
= SCNetworkProtocolSetConfiguration(protocol
, newEntity
);
256 CFRelease(newEntity
);
266 CFArrayRef
/* of SCNetworkServiceRef's */
267 SCNetworkServiceCopyAll(SCPreferencesRef prefs
)
269 CFMutableArrayRef array
;
272 CFDictionaryRef services
;
274 path
= SCPreferencesPathKeyCreateNetworkServices(NULL
);
275 services
= SCPreferencesPathGetValue(prefs
, path
);
278 if ((services
!= NULL
) && !isA_CFDictionary(services
)) {
282 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
284 n
= (services
!= NULL
) ? CFDictionaryGetCount(services
) : 0;
287 const void * keys_q
[N_QUICK
];
288 const void ** keys
= keys_q
;
289 const void * vals_q
[N_QUICK
];
290 const void ** vals
= vals_q
;
292 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
293 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
294 vals
= CFAllocatorAllocate(NULL
, n
* sizeof(CFPropertyListRef
), 0);
296 CFDictionaryGetKeysAndValues(services
, keys
, vals
);
297 for (i
= 0; i
< n
; i
++) {
298 CFDictionaryRef entity
;
299 SCNetworkServicePrivateRef servicePrivate
;
301 if (!isA_CFDictionary(vals
[i
])) {
304 CFSTR("SCNetworkServiceCopyAll(): error w/service \"%@\"\n"),
309 entity
= CFDictionaryGetValue(vals
[i
], kSCEntNetInterface
);
310 if (!isA_CFDictionary(entity
)) {
314 CFSTR("SCNetworkServiceCopyAll(): no \"%@\" entity for service \"%@\"\n"),
320 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, prefs
, keys
[i
], NULL
);
321 CFArrayAppendValue(array
, (SCNetworkServiceRef
)servicePrivate
);
322 CFRelease(servicePrivate
);
324 if (keys
!= keys_q
) {
325 CFAllocatorDeallocate(NULL
, keys
);
326 CFAllocatorDeallocate(NULL
, vals
);
335 * build a list of all of a servives entity types that are associated
336 * with the services interface. The list will include :
338 * - entity types associated with the interface type (Ethernet, FireWire, PPP, ...)
339 * - entity types associated with the interface sub-type (PPPSerial, PPPoE, L2TP, PPTP, ...)
340 * - entity types associated with the hardware device (Ethernet, AirPort, FireWire, Modem, ...)
343 _copyInterfaceEntityTypes(CFDictionaryRef protocols
)
345 CFDictionaryRef interface
;
346 CFMutableSetRef interface_entity_types
;
348 interface_entity_types
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
350 interface
= CFDictionaryGetValue(protocols
, kSCEntNetInterface
);
351 if (isA_CFDictionary(interface
)) {
352 CFStringRef entities
[] = { kSCPropNetInterfaceType
,
353 kSCPropNetInterfaceSubType
,
354 kSCPropNetInterfaceHardware
};
357 // include the "Interface" entity itself
358 CFSetAddValue(interface_entity_types
, kSCEntNetInterface
);
360 // include the entities associated with the interface
361 for (i
= 0; i
< sizeof(entities
)/sizeof(entities
[0]); i
++) {
364 entity
= CFDictionaryGetValue(interface
, entities
[i
]);
365 if (isA_CFString(entity
)) {
366 CFSetAddValue(interface_entity_types
, entity
);
371 * and, because we've found some misguided network preference code
372 * developers leaving [PPP] entity dictionaries around even though
373 * they are unused and/or unneeded...
375 CFSetAddValue(interface_entity_types
, kSCEntNetPPP
);
378 return interface_entity_types
;
383 SCNetworkServiceCopy(SCPreferencesRef prefs
, CFStringRef serviceID
)
385 CFDictionaryRef entity
;
387 SCNetworkServicePrivateRef servicePrivate
;
389 if (!isA_CFString(serviceID
)) {
390 _SCErrorSet(kSCStatusInvalidArgument
);
394 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
395 serviceID
, // service
396 kSCEntNetInterface
); // entity
397 entity
= SCPreferencesPathGetValue(prefs
, path
);
400 if (!isA_CFDictionary(entity
)) {
401 // a "service" must have an "interface"
402 _SCErrorSet(kSCStatusNoKey
);
406 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, prefs
, serviceID
, NULL
);
407 return (SCNetworkServiceRef
)servicePrivate
;
412 SCNetworkServiceCopyProtocol(SCNetworkServiceRef service
, CFStringRef protocolType
)
414 CFSetRef non_protocol_entities
;
416 CFDictionaryRef protocols
;
417 SCNetworkProtocolPrivateRef protocolPrivate
= NULL
;
418 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
420 if (!isA_SCNetworkService(service
)) {
421 _SCErrorSet(kSCStatusInvalidArgument
);
425 if (!isA_CFString(protocolType
)) {
426 _SCErrorSet(kSCStatusInvalidArgument
);
430 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
431 servicePrivate
->serviceID
, // service
433 protocols
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
436 if ((protocols
!= NULL
) && !isA_CFDictionary(protocols
)) {
438 _SCErrorSet(kSCStatusFailed
);
442 non_protocol_entities
= _copyInterfaceEntityTypes(protocols
);
443 if (CFSetContainsValue(non_protocol_entities
, protocolType
)) {
444 // if the "protocolType" matches an interface entity type
445 _SCErrorSet(kSCStatusInvalidArgument
);
449 if (!CFDictionaryContainsKey(protocols
, protocolType
)) {
450 // if the "protocolType" entity does not exist
451 _SCErrorSet(kSCStatusNoKey
);
455 protocolPrivate
= __SCNetworkProtocolCreatePrivate(NULL
, protocolType
, service
);
459 CFRelease(non_protocol_entities
);
461 return (SCNetworkProtocolRef
)protocolPrivate
;
465 CFArrayRef
/* of SCNetworkProtocolRef's */
466 SCNetworkServiceCopyProtocols(SCNetworkServiceRef service
)
468 CFMutableArrayRef array
;
470 CFSetRef non_protocol_entities
;
472 CFDictionaryRef protocols
;
473 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
475 if (!isA_SCNetworkService(service
)) {
476 _SCErrorSet(kSCStatusInvalidArgument
);
480 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
481 servicePrivate
->serviceID
, // service
483 protocols
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
486 if (!isA_CFDictionary(protocols
)) {
490 non_protocol_entities
= _copyInterfaceEntityTypes(protocols
);
492 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
494 n
= CFDictionaryGetCount(protocols
);
497 const void * keys_q
[N_QUICK
];
498 const void ** keys
= keys_q
;
499 const void * vals_q
[N_QUICK
];
500 const void ** vals
= vals_q
;
502 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
503 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
504 vals
= CFAllocatorAllocate(NULL
, n
* sizeof(CFPropertyListRef
), 0);
506 CFDictionaryGetKeysAndValues(protocols
, keys
, vals
);
507 for (i
= 0; i
< n
; i
++) {
508 SCNetworkProtocolPrivateRef protocolPrivate
;
510 if (!isA_CFDictionary(vals
[i
])) {
511 // if it's not a dictionary then it can't be a protocol entity
515 if (CFSetContainsValue(non_protocol_entities
, keys
[i
])) {
516 // skip any non-protocol (interface) entities
520 protocolPrivate
= __SCNetworkProtocolCreatePrivate(NULL
, keys
[i
], service
);
521 CFArrayAppendValue(array
, (SCNetworkProtocolRef
)protocolPrivate
);
523 CFRelease(protocolPrivate
);
525 if (keys
!= keys_q
) {
526 CFAllocatorDeallocate(NULL
, keys
);
527 CFAllocatorDeallocate(NULL
, vals
);
531 CFRelease(non_protocol_entities
);
538 __SCNetworkServiceSetInterfaceEntity(SCNetworkServiceRef service
,
539 SCNetworkInterfaceRef interface
)
541 CFDictionaryRef entity
;
544 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
546 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
547 servicePrivate
->serviceID
, // service
548 kSCEntNetInterface
); // entity
549 entity
= __SCNetworkInterfaceCopyInterfaceEntity(interface
);
550 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, entity
);
559 mergeDict(const void *key
, const void *value
, void *context
)
561 CFMutableDictionaryRef newDict
= (CFMutableDictionaryRef
)context
;
563 CFDictionarySetValue(newDict
, key
, value
);
569 SCNetworkServiceCreate(SCPreferencesRef prefs
, SCNetworkInterfaceRef interface
)
571 CFArrayRef components
;
572 CFArrayRef interface_config
;
573 CFStringRef interface_name
;
574 SCNetworkInterfaceRef newInterface
;
577 CFStringRef serviceID
;
578 SCNetworkServicePrivateRef servicePrivate
;
579 CFArrayRef supported_protocols
;
581 if (!isA_SCNetworkInterface(interface
)) {
582 _SCErrorSet(kSCStatusInvalidArgument
);
586 // only allow network interfaces which support one or more protocols
587 // to be added to a service. The one exception is that we allow
588 // third-party interface types to be configured.
589 supported_protocols
= SCNetworkInterfaceGetSupportedProtocolTypes(interface
);
590 if (supported_protocols
== NULL
) {
591 CFStringRef interface_type
;
593 interface_type
= SCNetworkInterfaceGetInterfaceType(interface
);
594 if (CFStringFind(interface_type
, CFSTR("."), 0).location
== kCFNotFound
) {
599 // establish the service
600 prefix
= SCPreferencesPathKeyCreateNetworkServices(NULL
);
601 path
= __SCPreferencesPathCreateUniqueChild_WithMoreSCFCompatibility(prefs
, prefix
);
602 if (path
== NULL
) path
= SCPreferencesPathCreateUniqueChild(prefs
, prefix
);
608 components
= CFStringCreateArrayBySeparatingStrings(NULL
, path
, CFSTR("/"));
611 serviceID
= CFArrayGetValueAtIndex(components
, 2);
612 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, prefs
, serviceID
, NULL
);
613 CFRelease(components
);
615 // duplicate the interface and associate the copy with the new service
616 newInterface
= (SCNetworkInterfaceRef
)__SCNetworkInterfaceCreateCopy(NULL
,
620 servicePrivate
->interface
= newInterface
;
622 // establish "default" configuration(s) for the interface
623 for (interface
= newInterface
;
625 interface
= SCNetworkInterfaceGetInterface(interface
)) {
626 SCNetworkInterfaceRef childInterface
;
627 CFStringRef childInterfaceType
= NULL
;
628 CFDictionaryRef config
;
629 CFStringRef interfaceType
;
631 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
632 childInterface
= SCNetworkInterfaceGetInterface(interface
);
633 if (childInterface
!= NULL
) {
634 childInterfaceType
= SCNetworkInterfaceGetInterfaceType(childInterface
);
637 config
= __copyInterfaceTemplate(interfaceType
, childInterfaceType
);
638 if (config
!= NULL
) {
639 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeBluetooth
) ||
640 CFEqual(interfaceType
, kSCNetworkInterfaceTypeIrDA
) ||
641 CFEqual(interfaceType
, kSCNetworkInterfaceTypeModem
) ||
642 CFEqual(interfaceType
, kSCNetworkInterfaceTypeSerial
) ||
643 CFEqual(interfaceType
, kSCNetworkInterfaceTypeWWAN
)) {
644 CFDictionaryRef overrides
;
647 overrides
= __SCNetworkInterfaceGetTemplateOverrides(interface
, kSCNetworkInterfaceTypeModem
);
649 // a ConnectionScript (and related keys) from the interface
650 // should trump the settings from the configuration template.
651 if ((overrides
!= NULL
) &&
652 CFDictionaryContainsKey(overrides
, kSCPropNetModemConnectionScript
)) {
653 CFMutableDictionaryRef newConfig
;
655 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
656 CFDictionaryRemoveValue(newConfig
, kSCPropNetModemConnectionPersonality
);
657 CFDictionaryRemoveValue(newConfig
, kSCPropNetModemConnectionScript
);
658 CFDictionaryRemoveValue(newConfig
, kSCPropNetModemDeviceVendor
);
659 CFDictionaryRemoveValue(newConfig
, kSCPropNetModemDeviceModel
);
664 // update template for v.92 modems
665 if ((overrides
== NULL
) &&
666 CFDictionaryGetValueIfPresent(config
,
667 kSCPropNetModemConnectionScript
,
668 (const void **)&script
) &&
669 CFEqual(script
, CFSTR("v.34 Personality")) &&
670 _SCNetworkInterfaceIsModemV92(interface
)) {
671 CFMutableDictionaryRef newConfig
;
673 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
674 CFDictionarySetValue(newConfig
,
675 kSCPropNetModemConnectionPersonality
,
676 CFSTR("v.92 Personality"));
677 CFDictionarySetValue(newConfig
,
678 kSCPropNetModemDeviceModel
,
679 CFSTR("Apple Modem (v.92)"));
684 if (overrides
!= NULL
) {
685 CFMutableDictionaryRef newConfig
;
687 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
688 CFDictionaryApplyFunction(overrides
, mergeDict
, newConfig
);
692 } else if (CFEqual(interfaceType
, kSCNetworkInterfaceTypePPP
)) {
693 CFDictionaryRef overrides
;
695 overrides
= __SCNetworkInterfaceGetTemplateOverrides(interface
, kSCNetworkInterfaceTypePPP
);
696 if (overrides
!= NULL
) {
697 CFMutableDictionaryRef newConfig
;
699 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
700 CFDictionaryApplyFunction(overrides
, mergeDict
, newConfig
);
706 if (!__SCNetworkInterfaceSetConfiguration(interface
, NULL
, config
, TRUE
)) {
707 SCLog(TRUE
, LOG_DEBUG
,
708 CFSTR("SCNetworkService __SCNetworkInterfaceSetConfiguration failed(), interface=%@, type=NULL"),
715 // add the interface [entity] to the service
716 (void) __SCNetworkServiceSetInterfaceEntity((SCNetworkServiceRef
)servicePrivate
,
717 servicePrivate
->interface
);
719 // push the [deep] interface configuration into the service.
720 interface_config
= __SCNetworkInterfaceCopyDeepConfiguration(servicePrivate
->interface
);
721 __SCNetworkInterfaceSetDeepConfiguration(servicePrivate
->interface
, interface_config
);
722 if (interface_config
!= NULL
) CFRelease(interface_config
);
724 // set the service name to match that of the associated interface
726 // Note: It might seem a bit odd to call SCNetworkServiceGetName
727 // followed by an immediate call to SCNetworkServiceSetName. The
728 // trick here is that if no name has previously been set, the
729 // "get" function will return the name of the associated interface.
731 // ... and we "set" a name to ensure that applications that do
732 // not use the APIs will still find a UserDefinedName property
733 // in the SCDynamicStore.
735 interface_name
= SCNetworkServiceGetName((SCNetworkServiceRef
)servicePrivate
);
736 if (interface_name
!= NULL
) {
737 (void) SCNetworkServiceSetName((SCNetworkServiceRef
)servicePrivate
,
741 return (SCNetworkServiceRef
)servicePrivate
;
746 SCNetworkServiceEstablishDefaultConfiguration(SCNetworkServiceRef service
)
749 SCNetworkInterfaceRef interface
;
751 CFArrayRef protocolTypes
;
753 interface
= SCNetworkServiceGetInterface(service
);
754 if (interface
== NULL
) {
758 protocolTypes
= SCNetworkInterfaceGetSupportedProtocolTypes(interface
);
759 n
= (protocolTypes
!= NULL
) ? CFArrayGetCount(protocolTypes
) : 0;
760 for (i
= 0; i
< n
; i
++) {
762 CFDictionaryRef newEntity
= NULL
;
764 SCNetworkProtocolRef protocol
= NULL
;
765 CFStringRef protocolType
;
767 protocolType
= CFArrayGetValueAtIndex(protocolTypes
, i
);
768 ok
= SCNetworkServiceAddProtocolType(service
, protocolType
);
769 if (!ok
&& (SCError() != kSCStatusKeyExists
)) {
770 // could not add protocol
774 protocol
= SCNetworkServiceCopyProtocol(service
, protocolType
);
775 if (protocol
== NULL
) {
776 // oops, somethings wrong (should never happen)
780 newEntity
= _protocolTemplate(service
, protocolType
);
781 ok
= SCNetworkProtocolSetConfiguration(protocol
, newEntity
);
783 // could not set default configuration
787 enabled
= !CFDictionaryContainsKey(newEntity
, kSCResvInactive
);
788 ok
= SCNetworkProtocolSetEnabled(protocol
, enabled
);
790 // could not enable/disable protocol
796 if (newEntity
!= NULL
) CFRelease(newEntity
);
797 if (protocol
!= NULL
) CFRelease(protocol
);
805 SCNetworkServiceGetEnabled(SCNetworkServiceRef service
)
809 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
811 if (!isA_SCNetworkService(service
)) {
812 _SCErrorSet(kSCStatusInvalidArgument
);
816 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
817 servicePrivate
->serviceID
, // service
819 enabled
= __getPrefsEnabled(servicePrivate
->prefs
, path
);
826 SCNetworkInterfaceRef
827 SCNetworkServiceGetInterface(SCNetworkServiceRef service
)
829 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
831 if (!isA_SCNetworkService(service
)) {
832 _SCErrorSet(kSCStatusInvalidArgument
);
836 if (servicePrivate
->interface
== NULL
) {
837 CFDictionaryRef entity
;
840 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
841 servicePrivate
->serviceID
, // service
842 kSCEntNetInterface
); // entity
843 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
846 if (isA_CFDictionary(entity
)) {
847 servicePrivate
->interface
= _SCNetworkInterfaceCreateWithEntity(NULL
, entity
, service
);
851 return servicePrivate
->interface
;
856 SCNetworkServiceGetName(SCNetworkServiceRef service
)
858 CFDictionaryRef entity
;
859 SCNetworkInterfaceRef interface
;
860 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
861 CFStringRef name
= NULL
;
864 if (!isA_SCNetworkService(service
)) {
865 _SCErrorSet(kSCStatusInvalidArgument
);
869 if (servicePrivate
->name
!= NULL
) {
870 return servicePrivate
->name
;
873 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
874 servicePrivate
->serviceID
, // service
876 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
879 if (isA_CFDictionary(entity
)) {
880 name
= CFDictionaryGetValue(entity
, kSCPropUserDefinedName
);
881 if (isA_CFString(name
)) {
882 servicePrivate
->name
= CFRetain(name
);
886 interface
= SCNetworkServiceGetInterface(service
);
887 while (interface
!= NULL
) {
888 SCNetworkInterfaceRef childInterface
;
890 childInterface
= SCNetworkInterfaceGetInterface(interface
);
891 if (childInterface
== NULL
) {
895 interface
= childInterface
;
898 if (interface
!= NULL
) {
899 CFStringRef interface_name
;
900 CFStringRef suffix
= NULL
;
902 if (servicePrivate
->name
!= NULL
) {
903 interface_name
= __SCNetworkInterfaceGetNonLocalizedDisplayName(interface
);
904 if (interface_name
!= NULL
) {
905 if (CFEqual(name
, interface_name
)) {
906 // if service name matches the [non-]localized
908 CFRelease(servicePrivate
->name
);
909 servicePrivate
->name
= NULL
;
910 } else if (CFStringHasPrefix(name
, interface_name
)) {
911 CFIndex prefixLen
= CFStringGetLength(interface_name
);
912 CFIndex suffixLen
= CFStringGetLength(name
);
914 suffix
= CFStringCreateWithSubstring(NULL
,
916 CFRangeMake(prefixLen
, suffixLen
- prefixLen
));
917 CFRelease(servicePrivate
->name
);
918 servicePrivate
->name
= NULL
;
923 if (servicePrivate
->name
== NULL
) {
924 interface_name
= SCNetworkInterfaceGetLocalizedDisplayName(interface
);
925 if (interface_name
!= NULL
) {
926 if (suffix
!= NULL
) {
927 servicePrivate
->name
= CFStringCreateWithFormat(NULL
,
933 servicePrivate
->name
= CFRetain(interface_name
);
937 if (suffix
!= NULL
) CFRelease(suffix
);
940 return servicePrivate
->name
;
945 SCNetworkServiceGetServiceID(SCNetworkServiceRef service
)
947 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
949 if (!isA_SCNetworkService(service
)) {
950 _SCErrorSet(kSCStatusInvalidArgument
);
954 return servicePrivate
->serviceID
;
959 SCNetworkServiceGetTypeID(void)
961 pthread_once(&initialized
, __SCNetworkServiceInitialize
); /* initialize runtime */
962 return __kSCNetworkServiceTypeID
;
967 SCNetworkServiceRemove(SCNetworkServiceRef service
)
970 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
974 if (!isA_SCNetworkService(service
)) {
975 _SCErrorSet(kSCStatusInvalidArgument
);
979 // remove service from all sets
981 sets
= SCNetworkSetCopyAll(servicePrivate
->prefs
);
986 n
= CFArrayGetCount(sets
);
987 for (i
= 0; i
< n
; i
++) {
990 set
= CFArrayGetValueAtIndex(sets
, i
);
991 ok
= SCNetworkSetRemoveService(set
, service
);
992 if (!ok
&& (SCError() != kSCStatusNoKey
)) {
1002 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1003 servicePrivate
->serviceID
, // service
1005 ok
= SCPreferencesPathRemoveValue(servicePrivate
->prefs
, path
);
1013 SCNetworkServiceRemoveProtocolType(SCNetworkServiceRef service
, CFStringRef protocolType
)
1015 CFDictionaryRef entity
;
1018 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1020 if (!isA_SCNetworkService(service
)) {
1021 _SCErrorSet(kSCStatusInvalidArgument
);
1025 if (!__SCNetworkProtocolIsValidType(protocolType
)) {
1026 _SCErrorSet(kSCStatusInvalidArgument
);
1030 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1031 servicePrivate
->serviceID
, // service
1032 protocolType
); // entity
1034 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1035 if (entity
== NULL
) {
1036 // if "protocol" does not exist
1037 _SCErrorSet(kSCStatusNoKey
);
1041 ok
= SCPreferencesPathRemoveValue(servicePrivate
->prefs
, path
);
1051 SCNetworkServiceSetEnabled(SCNetworkServiceRef service
, Boolean enabled
)
1055 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1057 if (!isA_SCNetworkService(service
)) {
1058 _SCErrorSet(kSCStatusInvalidArgument
);
1062 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1063 servicePrivate
->serviceID
, // service
1065 ok
= __setPrefsEnabled(servicePrivate
->prefs
, path
, enabled
);
1073 SCNetworkServiceSetName(SCNetworkServiceRef service
, CFStringRef name
)
1075 CFDictionaryRef entity
;
1078 CFStringRef saveName
= NULL
;
1079 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
1081 if (!isA_SCNetworkService(service
)) {
1082 _SCErrorSet(kSCStatusInvalidArgument
);
1087 if (!isA_CFString(name
)) {
1088 _SCErrorSet(kSCStatusInvalidArgument
);
1091 saveName
= CFRetain(name
);
1095 SCNetworkInterfaceRef interface
;
1097 interface
= SCNetworkServiceGetInterface(service
);
1098 while (interface
!= NULL
) {
1099 SCNetworkInterfaceRef childInterface
;
1101 childInterface
= SCNetworkInterfaceGetInterface(interface
);
1102 if (childInterface
== NULL
) {
1106 interface
= childInterface
;
1109 if (interface
!= NULL
) {
1110 CFStringRef interface_name
;
1112 interface_name
= SCNetworkInterfaceGetLocalizedDisplayName(interface
);
1113 if (interface_name
!= NULL
) {
1114 if (CFEqual(name
, interface_name
)) {
1115 // if service name matches the localized interface name
1116 // then store the non-localized name.
1117 interface_name
= __SCNetworkInterfaceGetNonLocalizedDisplayName(interface
);
1118 if (interface_name
!= NULL
) {
1119 CFRelease(saveName
);
1120 saveName
= CFRetain(interface_name
);
1122 } else if (CFStringHasPrefix(name
, interface_name
)) {
1123 CFIndex prefixLen
= CFStringGetLength(interface_name
);
1125 CFIndex suffixLen
= CFStringGetLength(name
);
1127 // if service name matches the localized interface name plus
1128 // a few extra characters) then store the non-localized name with
1130 suffix
= CFStringCreateWithSubstring(NULL
,
1132 CFRangeMake(prefixLen
, suffixLen
- prefixLen
));
1133 interface_name
= __SCNetworkInterfaceGetNonLocalizedDisplayName(interface
);
1134 if (interface_name
!= NULL
) {
1135 CFRelease(saveName
);
1136 saveName
= CFStringCreateWithFormat(NULL
,
1148 #define PREVENT_DUPLICATE_SERVICE_NAMES
1149 #ifdef PREVENT_DUPLICATE_SERVICE_NAMES
1153 // ensure that each service is uniquely named within its sets
1155 sets
= SCNetworkSetCopyAll(servicePrivate
->prefs
);
1160 set_count
= CFArrayGetCount(sets
);
1161 for (set_index
= 0; set_index
< set_count
; set_index
++) {
1162 CFIndex service_index
;
1163 Boolean isDup
= FALSE
;
1164 Boolean isMember
= FALSE
;
1165 CFIndex service_count
;
1166 CFArrayRef services
;
1167 SCNetworkSetRef set
= CFArrayGetValueAtIndex(sets
, set_index
);
1169 services
= SCNetworkSetCopyServices(set
);
1171 service_count
= CFArrayGetCount(services
);
1172 for (service_index
= 0; service_index
< service_count
; service_index
++) {
1173 CFStringRef otherID
;
1174 CFStringRef otherName
;
1175 SCNetworkServiceRef otherService
;
1177 otherService
= CFArrayGetValueAtIndex(services
, service_index
);
1179 otherID
= SCNetworkServiceGetServiceID(otherService
);
1180 if (CFEqual(servicePrivate
->serviceID
, otherID
)) {
1181 // if the service is a member of this set
1186 otherName
= SCNetworkServiceGetName(otherService
);
1187 if ((otherName
!= NULL
) && CFEqual(name
, otherName
)) {
1193 CFRelease(services
);
1195 if (isMember
&& isDup
) {
1197 * if this service is a member of the set and
1198 * the "name" is not unique.
1201 if (saveName
!= NULL
) CFRelease(saveName
);
1202 _SCErrorSet(kSCStatusKeyExists
);
1210 #endif /* PREVENT_DUPLICATE_SERVICE_NAMES */
1212 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
1213 servicePrivate
->serviceID
, // service
1215 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
1216 if ((entity
== NULL
) && (name
!= NULL
)) {
1217 entity
= CFDictionaryCreate(NULL
,
1221 &kCFTypeDictionaryKeyCallBacks
,
1222 &kCFTypeDictionaryValueCallBacks
);
1224 if (isA_CFDictionary(entity
)) {
1225 CFMutableDictionaryRef newEntity
;
1227 newEntity
= CFDictionaryCreateMutableCopy(NULL
, 0, entity
);
1228 if (saveName
!= NULL
) {
1229 CFDictionarySetValue(newEntity
, kSCPropUserDefinedName
, saveName
);
1231 CFDictionaryRemoveValue(newEntity
, kSCPropUserDefinedName
);
1233 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, newEntity
);
1234 CFRelease(newEntity
);
1237 if (saveName
!= NULL
) CFRelease(saveName
);
1239 if (servicePrivate
->name
!= NULL
) CFRelease(servicePrivate
->name
);
1240 if (name
!= NULL
) CFRetain(name
);
1241 servicePrivate
->name
= name
;