]> git.saurik.com Git - apple/configd.git/blob - SystemConfiguration.fproj/SCNetworkService.c
configd-137.3.tar.gz
[apple/configd.git] / SystemConfiguration.fproj / SCNetworkService.c
1 /*
2 * Copyright (c) 2004, 2005 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 /*
25 * Modification History
26 *
27 * May 13, 2004 Allan Nathanson <ajn@apple.com>
28 * - initial revision
29 */
30
31
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>
38
39 #include <pthread.h>
40
41
42 static CFStringRef __SCNetworkServiceCopyDescription (CFTypeRef cf);
43 static void __SCNetworkServiceDeallocate (CFTypeRef cf);
44 static Boolean __SCNetworkServiceEqual (CFTypeRef cf1, CFTypeRef cf2);
45
46
47 static CFTypeID __kSCNetworkServiceTypeID = _kCFRuntimeNotATypeID;
48
49
50 static const CFRuntimeClass __SCNetworkServiceClass = {
51 0, // version
52 "SCNetworkService", // className
53 NULL, // init
54 NULL, // copy
55 __SCNetworkServiceDeallocate, // dealloc
56 __SCNetworkServiceEqual, // equal
57 NULL, // hash
58 NULL, // copyFormattingDesc
59 __SCNetworkServiceCopyDescription // copyDebugDesc
60 };
61
62
63 static pthread_once_t initialized = PTHREAD_ONCE_INIT;
64
65
66 static __inline__ CFTypeRef
67 isA_SCNetworkService(CFTypeRef obj)
68 {
69 return (isA_CFType(obj, SCNetworkServiceGetTypeID()));
70 }
71
72
73 static CFStringRef
74 __SCNetworkServiceCopyDescription(CFTypeRef cf)
75 {
76 CFAllocatorRef allocator = CFGetAllocator(cf);
77 CFMutableStringRef result;
78 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)cf;
79
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(" }"));
85
86 return result;
87 }
88
89
90 static void
91 __SCNetworkServiceDeallocate(CFTypeRef cf)
92 {
93 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)cf;
94
95 /* release resources */
96
97 CFRelease(servicePrivate->serviceID);
98 if (servicePrivate->interface != NULL) CFRelease(servicePrivate->interface);
99 CFRelease(servicePrivate->prefs);
100
101 return;
102 }
103
104
105 static Boolean
106 __SCNetworkServiceEqual(CFTypeRef cf1, CFTypeRef cf2)
107 {
108 SCNetworkServicePrivateRef s1 = (SCNetworkServicePrivateRef)cf1;
109 SCNetworkServicePrivateRef s2 = (SCNetworkServicePrivateRef)cf2;
110
111 if (s1 == s2)
112 return TRUE;
113
114 if (s1->prefs != s2->prefs)
115 return FALSE; // if not the same prefs
116
117 if (!CFEqual(s1->serviceID, s2->serviceID))
118 return FALSE; // if not the same service identifier
119
120 return TRUE;
121 }
122
123
124 static void
125 __SCNetworkServiceInitialize(void)
126 {
127 __kSCNetworkServiceTypeID = _CFRuntimeRegisterClass(&__SCNetworkServiceClass);
128 return;
129 }
130
131
132 __private_extern__ SCNetworkServicePrivateRef
133 __SCNetworkServiceCreatePrivate(CFAllocatorRef allocator,
134 CFStringRef serviceID,
135 SCNetworkInterfaceRef interface,
136 SCPreferencesRef prefs)
137 {
138 SCNetworkServicePrivateRef servicePrivate;
139 uint32_t size;
140
141 /* initialize runtime */
142 pthread_once(&initialized, __SCNetworkServiceInitialize);
143
144 /* allocate target */
145 size = sizeof(SCNetworkServicePrivate) - sizeof(CFRuntimeBase);
146 servicePrivate = (SCNetworkServicePrivateRef)_CFRuntimeCreateInstance(allocator,
147 __kSCNetworkServiceTypeID,
148 size,
149 NULL);
150 if (servicePrivate == NULL) {
151 return NULL;
152 }
153
154 servicePrivate->prefs = CFRetain(prefs);
155 servicePrivate->serviceID = CFStringCreateCopy(NULL, serviceID);
156 servicePrivate->interface = (interface != NULL) ? CFRetain(interface) : NULL;
157
158 return servicePrivate;
159 }
160
161
162 /* ---------- SCNetworkService APIs ---------- */
163
164
165 #define N_QUICK 64
166
167
168 Boolean
169 SCNetworkServiceAddProtocolType(SCNetworkServiceRef service, CFStringRef protocolType)
170 {
171 CFDictionaryRef entity;
172 CFDictionaryRef newEntity = NULL;
173 Boolean ok = FALSE;
174 CFStringRef path;
175 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
176
177 if (!__SCNetworkProtocolIsValidType(protocolType)) {
178 _SCErrorSet(kSCStatusInvalidArgument);
179 return FALSE;
180 }
181
182 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
183 servicePrivate->serviceID, // service
184 protocolType); // entity
185
186 entity = SCPreferencesPathGetValue(servicePrivate->prefs, path);
187 if (entity != NULL) {
188 // if "protocol" already exists
189 _SCErrorSet(kSCStatusKeyExists);
190 goto done;
191 }
192
193 if (servicePrivate->interface != NULL) {
194 SCNetworkInterfaceRef childInterface;
195 CFStringRef childInterfaceType = NULL;
196 CFStringRef interfaceType;
197
198 interfaceType = SCNetworkInterfaceGetInterfaceType(servicePrivate->interface);
199 childInterface = SCNetworkInterfaceGetInterface(servicePrivate->interface);
200 if (childInterface != NULL) {
201 childInterfaceType = SCNetworkInterfaceGetInterfaceType(childInterface);
202 }
203
204 newEntity = __copyProtocolTemplate(interfaceType, childInterfaceType, protocolType);
205 }
206
207 if (newEntity == NULL) {
208 newEntity = CFDictionaryCreate(NULL,
209 NULL,
210 NULL,
211 0,
212 &kCFTypeDictionaryKeyCallBacks,
213 &kCFTypeDictionaryValueCallBacks);
214 }
215
216 ok = SCPreferencesPathSetValue(servicePrivate->prefs, path, newEntity);
217 CFRelease(newEntity);
218
219 done :
220
221 CFRelease(path);
222 return ok;
223 }
224
225
226 CFArrayRef /* of SCNetworkServiceRef's */
227 SCNetworkServiceCopyAll(SCPreferencesRef prefs)
228 {
229 CFMutableArrayRef array;
230 CFIndex n;
231 CFStringRef path;
232 CFDictionaryRef services;
233
234 path = SCPreferencesPathKeyCreateNetworkServices(NULL);
235 services = SCPreferencesPathGetValue(prefs, path);
236 CFRelease(path);
237
238 if ((services != NULL) && !isA_CFDictionary(services)) {
239 return NULL;
240 }
241
242 array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
243
244 n = (services != NULL) ? CFDictionaryGetCount(services) : 0;
245 if (n > 0) {
246 CFIndex i;
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;
251
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);
255 }
256 CFDictionaryGetKeysAndValues(services, keys, vals);
257 for (i = 0; i < n; i++) {
258 CFDictionaryRef entity;
259 SCNetworkServicePrivateRef servicePrivate;
260
261 if (!isA_CFDictionary(vals[i])) {
262 SCLog(TRUE,
263 LOG_INFO,
264 CFSTR("SCNetworkServiceCopyAll(): error w/service \"%@\"\n"),
265 keys[i]);
266 continue;
267 }
268
269 entity = CFDictionaryGetValue(vals[i], kSCEntNetInterface);
270 if (!isA_CFDictionary(entity)) {
271 // if no "interface"
272 SCLog(TRUE,
273 LOG_INFO,
274 CFSTR("SCNetworkServiceCopyAll(): no \"%@\" entity for service \"%@\"\n"),
275 kSCEntNetInterface,
276 keys[i]);
277 continue;
278 }
279
280 servicePrivate = __SCNetworkServiceCreatePrivate(NULL, keys[i], NULL, prefs);
281 CFArrayAppendValue(array, (SCNetworkServiceRef)servicePrivate);
282 CFRelease(servicePrivate);
283 }
284 if (keys != keys_q) {
285 CFAllocatorDeallocate(NULL, keys);
286 CFAllocatorDeallocate(NULL, vals);
287 }
288 }
289
290 return array;
291 }
292
293
294 /*
295 * build a list of all of a servives entity types that are associated
296 * with the services interface. The list will include :
297 *
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, ...)
301 */
302 static CFSetRef
303 _copyInterfaceEntityTypes(CFDictionaryRef protocols)
304 {
305 CFDictionaryRef interface;
306 CFMutableSetRef interface_entity_types;
307
308 interface_entity_types = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
309
310 interface = CFDictionaryGetValue(protocols, kSCEntNetInterface);
311 if (isA_CFDictionary(interface)) {
312 CFStringRef entities[] = { kSCPropNetInterfaceType,
313 kSCPropNetInterfaceSubType,
314 kSCPropNetInterfaceHardware };
315 int i;
316
317 // include the "Interface" entity itself
318 CFSetAddValue(interface_entity_types, kSCEntNetInterface);
319
320 // include the entities associated with the interface
321 for (i = 0; i < sizeof(entities)/sizeof(entities[0]); i++) {
322 CFStringRef entity;
323
324 entity = CFDictionaryGetValue(interface, entities[i]);
325 if (isA_CFString(entity)) {
326 CFSetAddValue(interface_entity_types, entity);
327 }
328 }
329
330 /*
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...
334 */
335 CFSetAddValue(interface_entity_types, kSCEntNetPPP);
336 }
337
338 return interface_entity_types;
339 }
340
341
342 SCNetworkServiceRef
343 SCNetworkServiceCopy(SCPreferencesRef prefs, CFStringRef serviceID)
344 {
345 CFDictionaryRef entity;
346 CFStringRef path;
347 SCNetworkServicePrivateRef servicePrivate;
348
349 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
350 serviceID, // service
351 kSCEntNetInterface); // entity
352 entity = SCPreferencesPathGetValue(prefs, path);
353 CFRelease(path);
354
355 if (!isA_CFDictionary(entity)) {
356 // a "service" must have an "interface"
357 _SCErrorSet(kSCStatusNoKey);
358 return NULL;
359 }
360
361 servicePrivate = __SCNetworkServiceCreatePrivate(NULL, serviceID, NULL, prefs);
362 return (SCNetworkServiceRef)servicePrivate;
363 }
364
365
366 SCNetworkProtocolRef
367 SCNetworkServiceCopyProtocol(SCNetworkServiceRef service, CFStringRef protocolType)
368 {
369 CFSetRef non_protocol_entities;
370 CFStringRef path;
371 CFDictionaryRef protocols;
372 SCNetworkProtocolPrivateRef protocolPrivate = NULL;
373 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
374
375 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
376 servicePrivate->serviceID, // service
377 NULL); // entity
378 protocols = SCPreferencesPathGetValue(servicePrivate->prefs, path);
379 CFRelease(path);
380
381 if ((protocols != NULL) && !isA_CFDictionary(protocols)) {
382 // if corrupt prefs
383 _SCErrorSet(kSCStatusFailed);
384 return NULL;
385 }
386
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);
391 goto done;
392 }
393
394 if (!CFDictionaryContainsKey(protocols, protocolType)) {
395 // if the "protocolType" entity does not exist
396 _SCErrorSet(kSCStatusNoKey);
397 goto done;
398 }
399
400 protocolPrivate = __SCNetworkProtocolCreatePrivate(NULL, protocolType, service);
401
402 done :
403
404 CFRelease(non_protocol_entities);
405
406 return (SCNetworkProtocolRef)protocolPrivate;
407 }
408
409
410 CFArrayRef /* of SCNetworkProtocolRef's */
411 SCNetworkServiceCopyProtocols(SCNetworkServiceRef service)
412 {
413 CFMutableArrayRef array;
414 CFIndex n;
415 CFSetRef non_protocol_entities;
416 CFStringRef path;
417 CFDictionaryRef protocols;
418 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
419
420 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
421 servicePrivate->serviceID, // service
422 NULL); // entity
423 protocols = SCPreferencesPathGetValue(servicePrivate->prefs, path);
424 CFRelease(path);
425
426 if (!isA_CFDictionary(protocols)) {
427 return NULL;
428 }
429
430 non_protocol_entities = _copyInterfaceEntityTypes(protocols);
431
432 array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
433
434 n = CFDictionaryGetCount(protocols);
435 if (n > 0) {
436 CFIndex i;
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;
441
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);
445 }
446 CFDictionaryGetKeysAndValues(protocols, keys, vals);
447 for (i = 0; i < n; i++) {
448 SCNetworkProtocolPrivateRef protocolPrivate;
449
450 if (!isA_CFDictionary(vals[i])) {
451 // if it's not a dictionary then it can't be a protocol entity
452 continue;
453 }
454
455 if (CFSetContainsValue(non_protocol_entities, keys[i])) {
456 // skip any non-protocol (interface) entities
457 continue;
458 }
459
460 protocolPrivate = __SCNetworkProtocolCreatePrivate(NULL, keys[i], service);
461 CFArrayAppendValue(array, (SCNetworkProtocolRef)protocolPrivate);
462
463 CFRelease(protocolPrivate);
464 }
465 if (keys != keys_q) {
466 CFAllocatorDeallocate(NULL, keys);
467 CFAllocatorDeallocate(NULL, vals);
468 }
469 }
470
471 CFRelease(non_protocol_entities);
472
473 return array;
474 }
475
476
477 static Boolean
478 __SCNetworkServiceSetInterfaceEntity(SCNetworkServiceRef service,
479 SCNetworkInterfaceRef interface)
480 {
481 CFDictionaryRef entity;
482 Boolean ok;
483 CFStringRef path;
484 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
485
486 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
487 servicePrivate->serviceID, // service
488 kSCEntNetInterface); // entity
489 entity = __SCNetworkInterfaceCopyInterfaceEntity(interface);
490 ok = SCPreferencesPathSetValue(servicePrivate->prefs, path, entity);
491 CFRelease(entity);
492 CFRelease(path);
493
494 return ok;
495 }
496
497
498 SCNetworkServiceRef
499 SCNetworkServiceCreate(SCPreferencesRef prefs, SCNetworkInterfaceRef interface)
500 {
501 CFArrayRef components;
502 CFArrayRef interface_config;
503 SCNetworkInterfaceRef newInterface;
504 CFStringRef path;
505 CFStringRef prefix;
506 CFStringRef serviceID;
507 SCNetworkServicePrivateRef servicePrivate;
508 CFArrayRef supported_protocols;
509
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;
516
517 interface_type = SCNetworkInterfaceGetInterfaceType(interface);
518 if (CFStringFind(interface_type, CFSTR("."), 0).location == kCFNotFound) {
519 return NULL;
520 }
521 }
522
523 // establish the service
524 prefix = SCPreferencesPathKeyCreateNetworkServices(NULL);
525 path = SCPreferencesPathCreateUniqueChild(prefs, prefix);
526 CFRelease(prefix);
527 if (path == NULL) {
528 return NULL;
529 }
530
531 components = CFStringCreateArrayBySeparatingStrings(NULL, path, CFSTR("/"));
532 CFRelease(path);
533
534 serviceID = CFArrayGetValueAtIndex(components, 2);
535 servicePrivate = __SCNetworkServiceCreatePrivate(NULL, serviceID, NULL, prefs);
536 CFRelease(components);
537
538 // duplicate the interface and associate the copy with the new service
539 newInterface = (SCNetworkInterfaceRef)__SCNetworkInterfaceCreateCopy(NULL,
540 interface,
541 (SCNetworkServiceRef)servicePrivate);
542 servicePrivate->interface = newInterface;
543
544 // establish "default" configuration(s) for the interface
545 for (interface = newInterface;
546 interface != NULL;
547 interface = SCNetworkInterfaceGetInterface(interface)) {
548 SCNetworkInterfaceRef childInterface;
549 CFStringRef childInterfaceType = NULL;
550 CFDictionaryRef config;
551 CFStringRef interfaceType;
552
553 interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
554 childInterface = SCNetworkInterfaceGetInterface(interface);
555 if (childInterface != NULL) {
556 childInterfaceType = SCNetworkInterfaceGetInterfaceType(childInterface);
557 }
558
559 config = __copyInterfaceTemplate(interfaceType, childInterfaceType);
560 if (config != NULL) {
561 if (CFEqual(interfaceType, kSCNetworkInterfaceTypeModem) ||
562 CFEqual(interfaceType, kSCNetworkInterfaceTypeSerial)) {
563 CFStringRef modemCCL;
564
565 modemCCL = __SCNetworkInterfaceGetModemCCL(interface);
566 if (modemCCL == NULL) {
567 if (__SCNetworkInterfaceIsModemV92(interface)) {
568 modemCCL = CFSTR("Apple Internal 56K Modem (v.92)");
569 }
570 }
571
572 if (modemCCL != NULL) {
573 CFMutableDictionaryRef newConfig;
574
575 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config);
576 CFDictionarySetValue(newConfig, kSCPropNetModemConnectionScript, modemCCL);
577
578 CFRelease(config);
579 config = newConfig;
580 }
581 }
582
583 (void) __SCNetworkInterfaceSetConfiguration(interface, config, TRUE);
584 CFRelease(config);
585 }
586 }
587
588 // add the interface [entity] to the service
589 (void) __SCNetworkServiceSetInterfaceEntity((SCNetworkServiceRef)servicePrivate,
590 servicePrivate->interface);
591
592 // push the [deep] interface configuration into the service.
593 interface_config = __SCNetworkInterfaceCopyDeepConfiguration(servicePrivate->interface);
594 __SCNetworkInterfaceSetDeepConfiguration(servicePrivate->interface, interface_config);
595
596 return (SCNetworkServiceRef)servicePrivate;
597 }
598
599
600 Boolean
601 SCNetworkServiceGetEnabled(SCNetworkServiceRef service)
602 {
603 Boolean enabled;
604 CFStringRef path;
605 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
606
607 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
608 servicePrivate->serviceID, // service
609 NULL); // entity
610 enabled = __getPrefsEnabled(servicePrivate->prefs, path);
611 CFRelease(path);
612
613 return enabled;
614 }
615
616
617 SCNetworkInterfaceRef
618 SCNetworkServiceGetInterface(SCNetworkServiceRef service)
619 {
620 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
621
622 if (servicePrivate->interface == NULL) {
623 CFDictionaryRef entity;
624 CFStringRef path;
625
626 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
627 servicePrivate->serviceID, // service
628 kSCEntNetInterface); // entity
629 entity = SCPreferencesPathGetValue(servicePrivate->prefs, path);
630 CFRelease(path);
631
632 if (isA_CFDictionary(entity)) {
633 servicePrivate->interface = __SCNetworkInterfaceCreateWithEntity(NULL, entity, service);
634 }
635 }
636
637 return servicePrivate->interface;
638 }
639
640
641 CFStringRef
642 SCNetworkServiceGetName(SCNetworkServiceRef service)
643 {
644 CFDictionaryRef entity;
645 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
646 CFStringRef name = NULL;
647 CFStringRef path;
648
649 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
650 servicePrivate->serviceID, // service
651 NULL); // entity
652 entity = SCPreferencesPathGetValue(servicePrivate->prefs, path);
653 CFRelease(path);
654
655 if (isA_CFDictionary(entity)) {
656 name = CFDictionaryGetValue(entity, kSCPropUserDefinedName);
657 }
658
659 return isA_CFString(name) ? name : NULL;
660 }
661
662
663 CFStringRef
664 SCNetworkServiceGetServiceID(SCNetworkServiceRef service)
665 {
666 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
667
668 return servicePrivate->serviceID;
669 }
670
671
672 CFTypeID
673 SCNetworkServiceGetTypeID(void)
674 {
675 pthread_once(&initialized, __SCNetworkServiceInitialize); /* initialize runtime */
676 return __kSCNetworkServiceTypeID;
677 }
678
679
680 Boolean
681 SCNetworkServiceRemove(SCNetworkServiceRef service)
682 {
683 Boolean ok = FALSE;
684 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
685 CFArrayRef sets;
686 CFStringRef path;
687
688 // remove service from all sets
689
690 sets = SCNetworkSetCopyAll(servicePrivate->prefs);
691 if (sets != NULL) {
692 CFIndex i;
693 CFIndex n;
694
695 n = CFArrayGetCount(sets);
696 for (i = 0; i < n; i++) {
697 SCNetworkSetRef set;
698
699 set = CFArrayGetValueAtIndex(sets, i);
700 ok = SCNetworkSetRemoveService(set, service);
701 if (!ok && (SCError() != kSCStatusNoKey)) {
702 CFRelease(sets);
703 return ok;
704 }
705 }
706 CFRelease(sets);
707 }
708
709 // remove service
710
711 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
712 servicePrivate->serviceID, // service
713 NULL); // entity
714 ok = SCPreferencesPathRemoveValue(servicePrivate->prefs, path);
715 CFRelease(path);
716
717 return ok;
718 }
719
720
721 Boolean
722 SCNetworkServiceRemoveProtocolType(SCNetworkServiceRef service, CFStringRef protocolType)
723 {
724 CFDictionaryRef entity;
725 Boolean ok = FALSE;
726 CFStringRef path;
727 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
728
729 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
730 servicePrivate->serviceID, // service
731 protocolType); // entity
732
733 entity = SCPreferencesPathGetValue(servicePrivate->prefs, path);
734 if (entity == NULL) {
735 // if "protocol" does not exist
736 _SCErrorSet(kSCStatusNoKey);
737 goto done;
738 }
739
740 ok = SCPreferencesPathRemoveValue(servicePrivate->prefs, path);
741
742 done :
743
744 CFRelease(path);
745 return ok;
746 }
747
748
749 Boolean
750 SCNetworkServiceSetEnabled(SCNetworkServiceRef service, Boolean enabled)
751 {
752 Boolean ok;
753 CFStringRef path;
754 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
755
756 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
757 servicePrivate->serviceID, // service
758 NULL); // entity
759 ok = __setPrefsEnabled(servicePrivate->prefs, path, enabled);
760 CFRelease(path);
761
762 return ok;
763 }
764
765
766 Boolean
767 SCNetworkServiceSetName(SCNetworkServiceRef service, CFStringRef name)
768 {
769 CFDictionaryRef entity;
770 Boolean ok = FALSE;
771 CFStringRef path;
772 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
773
774 #define PREVENT_DUPLICATE_SERVICE_NAMES
775 #ifdef PREVENT_DUPLICATE_SERVICE_NAMES
776 if (isA_CFString(name)) {
777 CFArrayRef sets;
778
779 // ensure that each service is uniquely named within its sets
780
781 sets = SCNetworkSetCopyAll(servicePrivate->prefs);
782 if (sets != NULL) {
783 CFIndex set_index;
784 CFIndex set_count;
785
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;
792 CFArrayRef services;
793 SCNetworkSetRef set = CFArrayGetValueAtIndex(sets, set_index);
794
795 services = SCNetworkSetCopyServices(set);
796
797 service_count = CFArrayGetCount(services);
798 for (service_index = 0; service_index < service_count; service_index++) {
799 CFStringRef otherID;
800 CFStringRef otherName;
801 SCNetworkServiceRef otherService;
802
803 otherService = CFArrayGetValueAtIndex(services, service_index);
804
805 otherID = SCNetworkServiceGetServiceID(otherService);
806 if (CFEqual(servicePrivate->serviceID, otherID)) {
807 // if the service is a member of this set
808 isMember = TRUE;
809 continue;
810 }
811
812 otherName = SCNetworkServiceGetName(otherService);
813 if ((otherName != NULL) && CFEqual(name, otherName)) {
814 isDup = TRUE;
815 continue;
816 }
817 }
818
819 CFRelease(services);
820
821 if (isMember && isDup) {
822 /*
823 * if this service is a member of the set and
824 * the "name" is not unique.
825 */
826 CFRelease(sets);
827 _SCErrorSet(kSCStatusKeyExists);
828 return FALSE;
829 }
830 }
831
832 CFRelease(sets);
833 }
834 }
835 #endif /* PREVENT_DUPLICATE_SERVICE_NAMES */
836
837 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
838 servicePrivate->serviceID, // service
839 NULL); // entity
840 entity = SCPreferencesPathGetValue(servicePrivate->prefs, path);
841 if ((entity == NULL) && (name != NULL)) {
842 entity = CFDictionaryCreate(NULL,
843 NULL,
844 NULL,
845 0,
846 &kCFTypeDictionaryKeyCallBacks,
847 &kCFTypeDictionaryValueCallBacks);
848 }
849 if (isA_CFDictionary(entity)) {
850 CFMutableDictionaryRef newEntity;
851
852 newEntity = CFDictionaryCreateMutableCopy(NULL, 0, entity);
853 if (isA_CFString(name)) {
854 CFDictionarySetValue(newEntity, kSCPropUserDefinedName, name);
855 } else {
856 CFDictionaryRemoveValue(newEntity, kSCPropUserDefinedName);
857 }
858 ok = SCPreferencesPathSetValue(servicePrivate->prefs, path, newEntity);
859 CFRelease(newEntity);
860 }
861 CFRelease(path);
862
863 return ok;
864 }