2 * Copyright (c) 2004, 2005 Apple Computer, 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 <SystemConfiguration/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
);
47 static CFTypeID __kSCNetworkServiceTypeID
= _kCFRuntimeNotATypeID
;
50 static const CFRuntimeClass __SCNetworkServiceClass
= {
52 "SCNetworkService", // className
55 __SCNetworkServiceDeallocate
, // dealloc
56 __SCNetworkServiceEqual
, // equal
58 NULL
, // copyFormattingDesc
59 __SCNetworkServiceCopyDescription
// copyDebugDesc
63 static pthread_once_t initialized
= PTHREAD_ONCE_INIT
;
66 static __inline__ CFTypeRef
67 isA_SCNetworkService(CFTypeRef obj
)
69 return (isA_CFType(obj
, SCNetworkServiceGetTypeID()));
74 __SCNetworkServiceCopyDescription(CFTypeRef cf
)
76 CFAllocatorRef allocator
= CFGetAllocator(cf
);
77 CFMutableStringRef result
;
78 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)cf
;
80 result
= CFStringCreateMutable(allocator
, 0);
81 CFStringAppendFormat(result
, NULL
, CFSTR("<SCNetworkService %p [%p]> { "), cf
, allocator
);
82 CFStringAppendFormat(result
, NULL
, CFSTR("id=%@"), servicePrivate
->serviceID
);
83 // CFStringAppendFormat(result, NULL, CFSTR(", prefs=%@"), servicePrivate->prefs);
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 CFRelease(servicePrivate
->prefs
);
106 __SCNetworkServiceEqual(CFTypeRef cf1
, CFTypeRef cf2
)
108 SCNetworkServicePrivateRef s1
= (SCNetworkServicePrivateRef
)cf1
;
109 SCNetworkServicePrivateRef s2
= (SCNetworkServicePrivateRef
)cf2
;
114 if (s1
->prefs
!= s2
->prefs
)
115 return FALSE
; // if not the same prefs
117 if (!CFEqual(s1
->serviceID
, s2
->serviceID
))
118 return FALSE
; // if not the same service identifier
125 __SCNetworkServiceInitialize(void)
127 __kSCNetworkServiceTypeID
= _CFRuntimeRegisterClass(&__SCNetworkServiceClass
);
132 __private_extern__ SCNetworkServicePrivateRef
133 __SCNetworkServiceCreatePrivate(CFAllocatorRef allocator
,
134 CFStringRef serviceID
,
135 SCNetworkInterfaceRef interface
,
136 SCPreferencesRef prefs
)
138 SCNetworkServicePrivateRef servicePrivate
;
141 /* initialize runtime */
142 pthread_once(&initialized
, __SCNetworkServiceInitialize
);
144 /* allocate target */
145 size
= sizeof(SCNetworkServicePrivate
) - sizeof(CFRuntimeBase
);
146 servicePrivate
= (SCNetworkServicePrivateRef
)_CFRuntimeCreateInstance(allocator
,
147 __kSCNetworkServiceTypeID
,
150 if (servicePrivate
== NULL
) {
154 servicePrivate
->prefs
= CFRetain(prefs
);
155 servicePrivate
->serviceID
= CFStringCreateCopy(NULL
, serviceID
);
156 servicePrivate
->interface
= (interface
!= NULL
) ? CFRetain(interface
) : NULL
;
158 return servicePrivate
;
162 /* ---------- SCNetworkService APIs ---------- */
169 SCNetworkServiceAddProtocolType(SCNetworkServiceRef service
, CFStringRef protocolType
)
171 CFDictionaryRef entity
;
172 CFDictionaryRef newEntity
= NULL
;
175 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
177 if (!__SCNetworkProtocolIsValidType(protocolType
)) {
178 _SCErrorSet(kSCStatusInvalidArgument
);
182 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
183 servicePrivate
->serviceID
, // service
184 protocolType
); // entity
186 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
187 if (entity
!= NULL
) {
188 // if "protocol" already exists
189 _SCErrorSet(kSCStatusKeyExists
);
193 if (servicePrivate
->interface
!= NULL
) {
194 SCNetworkInterfaceRef childInterface
;
195 CFStringRef childInterfaceType
= NULL
;
196 CFStringRef interfaceType
;
198 interfaceType
= SCNetworkInterfaceGetInterfaceType(servicePrivate
->interface
);
199 childInterface
= SCNetworkInterfaceGetInterface(servicePrivate
->interface
);
200 if (childInterface
!= NULL
) {
201 childInterfaceType
= SCNetworkInterfaceGetInterfaceType(childInterface
);
204 newEntity
= __copyProtocolTemplate(interfaceType
, childInterfaceType
, protocolType
);
207 if (newEntity
== NULL
) {
208 newEntity
= CFDictionaryCreate(NULL
,
212 &kCFTypeDictionaryKeyCallBacks
,
213 &kCFTypeDictionaryValueCallBacks
);
216 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, newEntity
);
217 CFRelease(newEntity
);
226 CFArrayRef
/* of SCNetworkServiceRef's */
227 SCNetworkServiceCopyAll(SCPreferencesRef prefs
)
229 CFMutableArrayRef array
;
232 CFDictionaryRef services
;
234 path
= SCPreferencesPathKeyCreateNetworkServices(NULL
);
235 services
= SCPreferencesPathGetValue(prefs
, path
);
238 if ((services
!= NULL
) && !isA_CFDictionary(services
)) {
242 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
244 n
= (services
!= NULL
) ? CFDictionaryGetCount(services
) : 0;
247 const void * keys_q
[N_QUICK
];
248 const void ** keys
= keys_q
;
249 const void * vals_q
[N_QUICK
];
250 const void ** vals
= vals_q
;
252 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
253 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
254 vals
= CFAllocatorAllocate(NULL
, n
* sizeof(CFPropertyListRef
), 0);
256 CFDictionaryGetKeysAndValues(services
, keys
, vals
);
257 for (i
= 0; i
< n
; i
++) {
258 CFDictionaryRef entity
;
259 SCNetworkServicePrivateRef servicePrivate
;
261 if (!isA_CFDictionary(vals
[i
])) {
264 CFSTR("SCNetworkServiceCopyAll(): error w/service \"%@\"\n"),
269 entity
= CFDictionaryGetValue(vals
[i
], kSCEntNetInterface
);
270 if (!isA_CFDictionary(entity
)) {
274 CFSTR("SCNetworkServiceCopyAll(): no \"%@\" entity for service \"%@\"\n"),
280 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, keys
[i
], NULL
, prefs
);
281 CFArrayAppendValue(array
, (SCNetworkServiceRef
)servicePrivate
);
282 CFRelease(servicePrivate
);
284 if (keys
!= keys_q
) {
285 CFAllocatorDeallocate(NULL
, keys
);
286 CFAllocatorDeallocate(NULL
, vals
);
295 * build a list of all of a servives entity types that are associated
296 * with the services interface. The list will include :
298 * - entity types associated with the interface type (Ethernet, FireWire, PPP, ...)
299 * - entity types associated with the interface sub-type (PPPSerial, PPPoE, L2TP, PPTP, ...)
300 * - entity types associated with the hardware device (Ethernet, AirPort, FireWire, Modem, ...)
303 _copyInterfaceEntityTypes(CFDictionaryRef protocols
)
305 CFDictionaryRef interface
;
306 CFMutableSetRef interface_entity_types
;
308 interface_entity_types
= CFSetCreateMutable(NULL
, 0, &kCFTypeSetCallBacks
);
310 interface
= CFDictionaryGetValue(protocols
, kSCEntNetInterface
);
311 if (isA_CFDictionary(interface
)) {
312 CFStringRef entities
[] = { kSCPropNetInterfaceType
,
313 kSCPropNetInterfaceSubType
,
314 kSCPropNetInterfaceHardware
};
317 // include the "Interface" entity itself
318 CFSetAddValue(interface_entity_types
, kSCEntNetInterface
);
320 // include the entities associated with the interface
321 for (i
= 0; i
< sizeof(entities
)/sizeof(entities
[0]); i
++) {
324 entity
= CFDictionaryGetValue(interface
, entities
[i
]);
325 if (isA_CFString(entity
)) {
326 CFSetAddValue(interface_entity_types
, entity
);
331 * and, because we've found some misguided network preference code
332 * developers leaving [PPP] entity dictionaries around even though
333 * they are unused and/or unneeded...
335 CFSetAddValue(interface_entity_types
, kSCEntNetPPP
);
338 return interface_entity_types
;
343 SCNetworkServiceCopy(SCPreferencesRef prefs
, CFStringRef serviceID
)
345 CFDictionaryRef entity
;
347 SCNetworkServicePrivateRef servicePrivate
;
349 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
350 serviceID
, // service
351 kSCEntNetInterface
); // entity
352 entity
= SCPreferencesPathGetValue(prefs
, path
);
355 if (!isA_CFDictionary(entity
)) {
356 // a "service" must have an "interface"
357 _SCErrorSet(kSCStatusNoKey
);
361 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, serviceID
, NULL
, prefs
);
362 return (SCNetworkServiceRef
)servicePrivate
;
367 SCNetworkServiceCopyProtocol(SCNetworkServiceRef service
, CFStringRef protocolType
)
369 CFSetRef non_protocol_entities
;
371 CFDictionaryRef protocols
;
372 SCNetworkProtocolPrivateRef protocolPrivate
= NULL
;
373 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
375 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
376 servicePrivate
->serviceID
, // service
378 protocols
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
381 if ((protocols
!= NULL
) && !isA_CFDictionary(protocols
)) {
383 _SCErrorSet(kSCStatusFailed
);
387 non_protocol_entities
= _copyInterfaceEntityTypes(protocols
);
388 if (CFSetContainsValue(non_protocol_entities
, protocolType
)) {
389 // if the "protocolType" matches an interface entity type
390 _SCErrorSet(kSCStatusInvalidArgument
);
394 if (!CFDictionaryContainsKey(protocols
, protocolType
)) {
395 // if the "protocolType" entity does not exist
396 _SCErrorSet(kSCStatusNoKey
);
400 protocolPrivate
= __SCNetworkProtocolCreatePrivate(NULL
, protocolType
, service
);
404 CFRelease(non_protocol_entities
);
406 return (SCNetworkProtocolRef
)protocolPrivate
;
410 CFArrayRef
/* of SCNetworkProtocolRef's */
411 SCNetworkServiceCopyProtocols(SCNetworkServiceRef service
)
413 CFMutableArrayRef array
;
415 CFSetRef non_protocol_entities
;
417 CFDictionaryRef protocols
;
418 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
420 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
421 servicePrivate
->serviceID
, // service
423 protocols
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
426 if (!isA_CFDictionary(protocols
)) {
430 non_protocol_entities
= _copyInterfaceEntityTypes(protocols
);
432 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
434 n
= CFDictionaryGetCount(protocols
);
437 const void * keys_q
[N_QUICK
];
438 const void ** keys
= keys_q
;
439 const void * vals_q
[N_QUICK
];
440 const void ** vals
= vals_q
;
442 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
443 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
444 vals
= CFAllocatorAllocate(NULL
, n
* sizeof(CFPropertyListRef
), 0);
446 CFDictionaryGetKeysAndValues(protocols
, keys
, vals
);
447 for (i
= 0; i
< n
; i
++) {
448 SCNetworkProtocolPrivateRef protocolPrivate
;
450 if (!isA_CFDictionary(vals
[i
])) {
451 // if it's not a dictionary then it can't be a protocol entity
455 if (CFSetContainsValue(non_protocol_entities
, keys
[i
])) {
456 // skip any non-protocol (interface) entities
460 protocolPrivate
= __SCNetworkProtocolCreatePrivate(NULL
, keys
[i
], service
);
461 CFArrayAppendValue(array
, (SCNetworkProtocolRef
)protocolPrivate
);
463 CFRelease(protocolPrivate
);
465 if (keys
!= keys_q
) {
466 CFAllocatorDeallocate(NULL
, keys
);
467 CFAllocatorDeallocate(NULL
, vals
);
471 CFRelease(non_protocol_entities
);
478 __SCNetworkServiceSetInterfaceEntity(SCNetworkServiceRef service
,
479 SCNetworkInterfaceRef interface
)
481 CFDictionaryRef entity
;
484 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
486 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
487 servicePrivate
->serviceID
, // service
488 kSCEntNetInterface
); // entity
489 entity
= __SCNetworkInterfaceCopyInterfaceEntity(interface
);
490 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, entity
);
499 SCNetworkServiceCreate(SCPreferencesRef prefs
, SCNetworkInterfaceRef interface
)
501 CFArrayRef components
;
502 CFArrayRef interface_config
;
503 SCNetworkInterfaceRef newInterface
;
506 CFStringRef serviceID
;
507 SCNetworkServicePrivateRef servicePrivate
;
508 CFArrayRef supported_protocols
;
510 // only allow network interfaces which support one or more protocols
511 // to be added to a service. The one exception is that we allow
512 // third-party interface types to be configured.
513 supported_protocols
= SCNetworkInterfaceGetSupportedProtocolTypes(interface
);
514 if (supported_protocols
== NULL
) {
515 CFStringRef interface_type
;
517 interface_type
= SCNetworkInterfaceGetInterfaceType(interface
);
518 if (CFStringFind(interface_type
, CFSTR("."), 0).location
== kCFNotFound
) {
523 // establish the service
524 prefix
= SCPreferencesPathKeyCreateNetworkServices(NULL
);
525 path
= SCPreferencesPathCreateUniqueChild(prefs
, prefix
);
531 components
= CFStringCreateArrayBySeparatingStrings(NULL
, path
, CFSTR("/"));
534 serviceID
= CFArrayGetValueAtIndex(components
, 2);
535 servicePrivate
= __SCNetworkServiceCreatePrivate(NULL
, serviceID
, NULL
, prefs
);
536 CFRelease(components
);
538 // duplicate the interface and associate the copy with the new service
539 newInterface
= (SCNetworkInterfaceRef
)__SCNetworkInterfaceCreateCopy(NULL
,
541 (SCNetworkServiceRef
)servicePrivate
);
542 servicePrivate
->interface
= newInterface
;
544 // establish "default" configuration(s) for the interface
545 for (interface
= newInterface
;
547 interface
= SCNetworkInterfaceGetInterface(interface
)) {
548 SCNetworkInterfaceRef childInterface
;
549 CFStringRef childInterfaceType
= NULL
;
550 CFDictionaryRef config
;
551 CFStringRef interfaceType
;
553 interfaceType
= SCNetworkInterfaceGetInterfaceType(interface
);
554 childInterface
= SCNetworkInterfaceGetInterface(interface
);
555 if (childInterface
!= NULL
) {
556 childInterfaceType
= SCNetworkInterfaceGetInterfaceType(childInterface
);
559 config
= __copyInterfaceTemplate(interfaceType
, childInterfaceType
);
560 if (config
!= NULL
) {
561 if (CFEqual(interfaceType
, kSCNetworkInterfaceTypeModem
) ||
562 CFEqual(interfaceType
, kSCNetworkInterfaceTypeSerial
)) {
563 CFStringRef modemCCL
;
565 modemCCL
= __SCNetworkInterfaceGetModemCCL(interface
);
566 if (modemCCL
== NULL
) {
567 if (__SCNetworkInterfaceIsModemV92(interface
)) {
568 modemCCL
= CFSTR("Apple Internal 56K Modem (v.92)");
572 if (modemCCL
!= NULL
) {
573 CFMutableDictionaryRef newConfig
;
575 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
576 CFDictionarySetValue(newConfig
, kSCPropNetModemConnectionScript
, modemCCL
);
583 (void) __SCNetworkInterfaceSetConfiguration(interface
, config
, TRUE
);
588 // add the interface [entity] to the service
589 (void) __SCNetworkServiceSetInterfaceEntity((SCNetworkServiceRef
)servicePrivate
,
590 servicePrivate
->interface
);
592 // push the [deep] interface configuration into the service.
593 interface_config
= __SCNetworkInterfaceCopyDeepConfiguration(servicePrivate
->interface
);
594 __SCNetworkInterfaceSetDeepConfiguration(servicePrivate
->interface
, interface_config
);
596 return (SCNetworkServiceRef
)servicePrivate
;
601 SCNetworkServiceGetEnabled(SCNetworkServiceRef service
)
605 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
607 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
608 servicePrivate
->serviceID
, // service
610 enabled
= __getPrefsEnabled(servicePrivate
->prefs
, path
);
617 SCNetworkInterfaceRef
618 SCNetworkServiceGetInterface(SCNetworkServiceRef service
)
620 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
622 if (servicePrivate
->interface
== NULL
) {
623 CFDictionaryRef entity
;
626 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
627 servicePrivate
->serviceID
, // service
628 kSCEntNetInterface
); // entity
629 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
632 if (isA_CFDictionary(entity
)) {
633 servicePrivate
->interface
= __SCNetworkInterfaceCreateWithEntity(NULL
, entity
, service
);
637 return servicePrivate
->interface
;
642 SCNetworkServiceGetName(SCNetworkServiceRef service
)
644 CFDictionaryRef entity
;
645 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
646 CFStringRef name
= NULL
;
649 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
650 servicePrivate
->serviceID
, // service
652 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
655 if (isA_CFDictionary(entity
)) {
656 name
= CFDictionaryGetValue(entity
, kSCPropUserDefinedName
);
659 return isA_CFString(name
) ? name
: NULL
;
664 SCNetworkServiceGetServiceID(SCNetworkServiceRef service
)
666 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
668 return servicePrivate
->serviceID
;
673 SCNetworkServiceGetTypeID(void)
675 pthread_once(&initialized
, __SCNetworkServiceInitialize
); /* initialize runtime */
676 return __kSCNetworkServiceTypeID
;
681 SCNetworkServiceRemove(SCNetworkServiceRef service
)
684 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
688 // remove service from all sets
690 sets
= SCNetworkSetCopyAll(servicePrivate
->prefs
);
695 n
= CFArrayGetCount(sets
);
696 for (i
= 0; i
< n
; i
++) {
699 set
= CFArrayGetValueAtIndex(sets
, i
);
700 ok
= SCNetworkSetRemoveService(set
, service
);
701 if (!ok
&& (SCError() != kSCStatusNoKey
)) {
711 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
712 servicePrivate
->serviceID
, // service
714 ok
= SCPreferencesPathRemoveValue(servicePrivate
->prefs
, path
);
722 SCNetworkServiceRemoveProtocolType(SCNetworkServiceRef service
, CFStringRef protocolType
)
724 CFDictionaryRef entity
;
727 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
729 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
730 servicePrivate
->serviceID
, // service
731 protocolType
); // entity
733 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
734 if (entity
== NULL
) {
735 // if "protocol" does not exist
736 _SCErrorSet(kSCStatusNoKey
);
740 ok
= SCPreferencesPathRemoveValue(servicePrivate
->prefs
, path
);
750 SCNetworkServiceSetEnabled(SCNetworkServiceRef service
, Boolean enabled
)
754 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
756 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
757 servicePrivate
->serviceID
, // service
759 ok
= __setPrefsEnabled(servicePrivate
->prefs
, path
, enabled
);
767 SCNetworkServiceSetName(SCNetworkServiceRef service
, CFStringRef name
)
769 CFDictionaryRef entity
;
772 SCNetworkServicePrivateRef servicePrivate
= (SCNetworkServicePrivateRef
)service
;
774 #define PREVENT_DUPLICATE_SERVICE_NAMES
775 #ifdef PREVENT_DUPLICATE_SERVICE_NAMES
776 if (isA_CFString(name
)) {
779 // ensure that each service is uniquely named within its sets
781 sets
= SCNetworkSetCopyAll(servicePrivate
->prefs
);
786 set_count
= CFArrayGetCount(sets
);
787 for (set_index
= 0; set_index
< set_count
; set_index
++) {
788 CFIndex service_index
;
789 Boolean isDup
= FALSE
;
790 Boolean isMember
= FALSE
;
791 CFIndex service_count
;
793 SCNetworkSetRef set
= CFArrayGetValueAtIndex(sets
, set_index
);
795 services
= SCNetworkSetCopyServices(set
);
797 service_count
= CFArrayGetCount(services
);
798 for (service_index
= 0; service_index
< service_count
; service_index
++) {
800 CFStringRef otherName
;
801 SCNetworkServiceRef otherService
;
803 otherService
= CFArrayGetValueAtIndex(services
, service_index
);
805 otherID
= SCNetworkServiceGetServiceID(otherService
);
806 if (CFEqual(servicePrivate
->serviceID
, otherID
)) {
807 // if the service is a member of this set
812 otherName
= SCNetworkServiceGetName(otherService
);
813 if ((otherName
!= NULL
) && CFEqual(name
, otherName
)) {
821 if (isMember
&& isDup
) {
823 * if this service is a member of the set and
824 * the "name" is not unique.
827 _SCErrorSet(kSCStatusKeyExists
);
835 #endif /* PREVENT_DUPLICATE_SERVICE_NAMES */
837 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
838 servicePrivate
->serviceID
, // service
840 entity
= SCPreferencesPathGetValue(servicePrivate
->prefs
, path
);
841 if ((entity
== NULL
) && (name
!= NULL
)) {
842 entity
= CFDictionaryCreate(NULL
,
846 &kCFTypeDictionaryKeyCallBacks
,
847 &kCFTypeDictionaryValueCallBacks
);
849 if (isA_CFDictionary(entity
)) {
850 CFMutableDictionaryRef newEntity
;
852 newEntity
= CFDictionaryCreateMutableCopy(NULL
, 0, entity
);
853 if (isA_CFString(name
)) {
854 CFDictionarySetValue(newEntity
, kSCPropUserDefinedName
, name
);
856 CFDictionaryRemoveValue(newEntity
, kSCPropUserDefinedName
);
858 ok
= SCPreferencesPathSetValue(servicePrivate
->prefs
, path
, newEntity
);
859 CFRelease(newEntity
);