]> git.saurik.com Git - apple/configd.git/blob - SystemConfiguration.fproj/SCNetworkService.c
configd-130.tar.gz
[apple/configd.git] / SystemConfiguration.fproj / SCNetworkService.c
1 /*
2 * Copyright (c) 2004 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 CFMutableDictionaryRef entity;
482 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
483 Boolean ok;
484 CFStringRef path;
485 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
486
487 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
488 servicePrivate->serviceID, // service
489 kSCEntNetInterface); // entity
490 entity = CFDictionaryCreateMutable(NULL,
491 0,
492 &kCFTypeDictionaryKeyCallBacks,
493 &kCFTypeDictionaryValueCallBacks);
494 if (interfacePrivate->entity_type != NULL) {
495 CFDictionarySetValue(entity,
496 kSCPropNetInterfaceType,
497 interfacePrivate->entity_type);
498 }
499 if (interfacePrivate->entity_subtype != NULL) {
500 CFDictionarySetValue(entity,
501 kSCPropNetInterfaceSubType,
502 interfacePrivate->entity_subtype);
503 }
504 if (interfacePrivate->entity_device != NULL) {
505 CFDictionarySetValue(entity,
506 kSCPropNetInterfaceDeviceName,
507 interfacePrivate->entity_device);
508 }
509 if (interfacePrivate->entity_hardware != NULL) {
510 CFDictionarySetValue(entity,
511 kSCPropNetInterfaceHardware,
512 interfacePrivate->entity_hardware);
513 }
514 if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeModem) &&
515 interfacePrivate->supportsDeviceOnHold) {
516 int one = 1;
517 CFNumberRef num;
518
519 num = CFNumberCreate(NULL, kCFNumberIntType, &one);
520 CFDictionarySetValue(entity,
521 kSCPropNetInterfaceSupportsModemOnHold,
522 num);
523 CFRelease(num);
524 }
525 ok = SCPreferencesPathSetValue(servicePrivate->prefs, path, entity);
526 CFRelease(entity);
527 CFRelease(path);
528
529 return ok;
530 }
531
532
533 SCNetworkServiceRef
534 SCNetworkServiceCreate(SCPreferencesRef prefs, SCNetworkInterfaceRef interface)
535 {
536 CFArrayRef components;
537 CFArrayRef interface_config;
538 SCNetworkInterfaceRef newInterface;
539 CFStringRef path;
540 CFStringRef prefix;
541 CFStringRef serviceID;
542 SCNetworkServicePrivateRef servicePrivate;
543
544 // establish the service
545 prefix = SCPreferencesPathKeyCreateNetworkServices(NULL);
546 path = SCPreferencesPathCreateUniqueChild(prefs, prefix);
547 CFRelease(prefix);
548 if (path == NULL) {
549 return NULL;
550 }
551
552 components = CFStringCreateArrayBySeparatingStrings(NULL, path, CFSTR("/"));
553 CFRelease(path);
554
555 serviceID = CFArrayGetValueAtIndex(components, 2);
556 servicePrivate = __SCNetworkServiceCreatePrivate(NULL, serviceID, NULL, prefs);
557 CFRelease(components);
558
559 // duplicate the interface and associate the copy with the new service
560 newInterface = (SCNetworkInterfaceRef)__SCNetworkInterfaceCreateCopy(NULL,
561 interface,
562 (SCNetworkServiceRef)servicePrivate);
563 servicePrivate->interface = newInterface;
564
565 // establish "default" configuration(s) for the interface
566 for (interface = newInterface;
567 interface != NULL;
568 interface = SCNetworkInterfaceGetInterface(interface)) {
569 SCNetworkInterfaceRef childInterface;
570 CFStringRef childInterfaceType = NULL;
571 CFDictionaryRef config;
572 CFStringRef interfaceType;
573
574 interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
575 childInterface = SCNetworkInterfaceGetInterface(servicePrivate->interface);
576 if (childInterface != NULL) {
577 childInterfaceType = SCNetworkInterfaceGetInterfaceType(childInterface);
578 }
579
580 config = __copyInterfaceTemplate(interfaceType, childInterfaceType);
581 if (config != NULL) {
582 (void) __SCNetworkInterfaceSetConfiguration(interface, config, TRUE);
583 CFRelease(config);
584 }
585 }
586
587 // add the interface [entity] to the service
588 (void) __SCNetworkServiceSetInterfaceEntity((SCNetworkServiceRef)servicePrivate,
589 servicePrivate->interface);
590
591 // push the [deep] interface configuration into into the service.
592 interface_config = __SCNetworkInterfaceCopyDeepConfiguration(servicePrivate->interface);
593 __SCNetworkInterfaceSetDeepConfiguration(servicePrivate->interface, interface_config);
594
595 return (SCNetworkServiceRef)servicePrivate;
596 }
597
598
599 Boolean
600 SCNetworkServiceGetEnabled(SCNetworkServiceRef service)
601 {
602 Boolean enabled;
603 CFStringRef path;
604 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
605
606 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
607 servicePrivate->serviceID, // service
608 NULL); // entity
609 enabled = __getPrefsEnabled(servicePrivate->prefs, path);
610 CFRelease(path);
611
612 return enabled;
613 }
614
615
616 SCNetworkInterfaceRef
617 SCNetworkServiceGetInterface(SCNetworkServiceRef service)
618 {
619 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
620
621 if (servicePrivate->interface == NULL) {
622 CFDictionaryRef entity;
623 CFStringRef path;
624
625 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
626 servicePrivate->serviceID, // service
627 kSCEntNetInterface); // entity
628 entity = SCPreferencesPathGetValue(servicePrivate->prefs, path);
629 CFRelease(path);
630
631 if (isA_CFDictionary(entity)) {
632 servicePrivate->interface = __SCNetworkInterfaceCreateWithEntity(NULL, entity, service);
633 }
634 }
635
636 return servicePrivate->interface;
637 }
638
639
640 CFStringRef
641 SCNetworkServiceGetName(SCNetworkServiceRef service)
642 {
643 CFDictionaryRef entity;
644 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
645 CFStringRef name = NULL;
646 CFStringRef path;
647
648 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
649 servicePrivate->serviceID, // service
650 NULL); // entity
651 entity = SCPreferencesPathGetValue(servicePrivate->prefs, path);
652 CFRelease(path);
653
654 if (isA_CFDictionary(entity)) {
655 name = CFDictionaryGetValue(entity, kSCPropUserDefinedName);
656 }
657
658 return isA_CFString(name) ? name : NULL;
659 }
660
661
662 CFStringRef
663 SCNetworkServiceGetServiceID(SCNetworkServiceRef service)
664 {
665 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
666
667 return servicePrivate->serviceID;
668 }
669
670
671 CFTypeID
672 SCNetworkServiceGetTypeID(void)
673 {
674 pthread_once(&initialized, __SCNetworkServiceInitialize); /* initialize runtime */
675 return __kSCNetworkServiceTypeID;
676 }
677
678
679 Boolean
680 SCNetworkServiceRemove(SCNetworkServiceRef service)
681 {
682 Boolean ok = FALSE;
683 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
684 CFArrayRef sets;
685 CFStringRef path;
686
687 // remove service from all sets
688
689 sets = SCNetworkSetCopyAll(servicePrivate->prefs);
690 if (sets != NULL) {
691 CFIndex i;
692 CFIndex n;
693
694 n = CFArrayGetCount(sets);
695 for (i = 0; i < n; i++) {
696 SCNetworkSetRef set;
697
698 set = CFArrayGetValueAtIndex(sets, i);
699 ok = SCNetworkSetRemoveService(set, service);
700 if (!ok && (SCError() != kSCStatusNoKey)) {
701 break;
702 }
703 }
704 CFRelease(sets);
705 }
706
707 // remove service
708
709 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
710 servicePrivate->serviceID, // service
711 NULL); // entity
712 ok = SCPreferencesPathRemoveValue(servicePrivate->prefs, path);
713 CFRelease(path);
714
715 return ok;
716 }
717
718
719 Boolean
720 SCNetworkServiceRemoveProtocolType(SCNetworkServiceRef service, CFStringRef protocolType)
721 {
722 CFDictionaryRef entity;
723 Boolean ok = FALSE;
724 CFStringRef path;
725 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
726
727 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
728 servicePrivate->serviceID, // service
729 protocolType); // entity
730
731 entity = SCPreferencesPathGetValue(servicePrivate->prefs, path);
732 if (entity == NULL) {
733 // if "protocol" does not exist
734 _SCErrorSet(kSCStatusNoKey);
735 goto done;
736 }
737
738 ok = SCPreferencesPathRemoveValue(servicePrivate->prefs, path);
739
740 done :
741
742 CFRelease(path);
743 return ok;
744 }
745
746
747 Boolean
748 SCNetworkServiceSetEnabled(SCNetworkServiceRef service, Boolean enabled)
749 {
750 Boolean ok;
751 CFStringRef path;
752 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
753
754 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
755 servicePrivate->serviceID, // service
756 NULL); // entity
757 ok = __setPrefsEnabled(servicePrivate->prefs, path, enabled);
758 CFRelease(path);
759
760 return ok;
761 }
762
763
764 Boolean
765 SCNetworkServiceSetName(SCNetworkServiceRef service, CFStringRef name)
766 {
767 CFDictionaryRef entity;
768 Boolean ok = FALSE;
769 CFStringRef path;
770 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
771
772 #define PREVENT_DUPLICATE_SERVICE_NAMES
773 #ifdef PREVENT_DUPLICATE_SERVICE_NAMES
774 if (isA_CFString(name)) {
775 CFArrayRef sets;
776
777 // ensure that each service is uniquely named within its sets
778
779 sets = SCNetworkSetCopyAll(servicePrivate->prefs);
780 if (sets != NULL) {
781 CFIndex set_index;
782 CFIndex set_count;
783
784 set_count = CFArrayGetCount(sets);
785 for (set_index = 0; set_index < set_count; set_index++) {
786 CFIndex service_index;
787 Boolean isDup = FALSE;
788 Boolean isMember = FALSE;
789 CFIndex service_count;
790 CFArrayRef services;
791 SCNetworkSetRef set = CFArrayGetValueAtIndex(sets, set_index);
792
793 services = SCNetworkSetCopyServices(set);
794
795 service_count = CFArrayGetCount(services);
796 for (service_index = 0; service_index < service_count; service_index++) {
797 CFStringRef otherID;
798 CFStringRef otherName;
799 SCNetworkServiceRef otherService;
800
801 otherService = CFArrayGetValueAtIndex(services, service_index);
802
803 otherID = SCNetworkServiceGetServiceID(otherService);
804 if (CFEqual(servicePrivate->serviceID, otherID)) {
805 // if the service is a member of this set
806 isMember = TRUE;
807 continue;
808 }
809
810 otherName = SCNetworkServiceGetName(otherService);
811 if ((otherName != NULL) && CFEqual(name, otherName)) {
812 isDup = TRUE;
813 continue;
814 }
815 }
816
817 CFRelease(services);
818
819 if (isMember && isDup) {
820 /*
821 * if this service is a member of the set and
822 * the "name" is not unique.
823 */
824 CFRelease(sets);
825 _SCErrorSet(kSCStatusKeyExists);
826 return FALSE;
827 }
828 }
829
830 CFRelease(sets);
831 }
832 }
833 #endif /* PREVENT_DUPLICATE_SERVICE_NAMES */
834
835 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
836 servicePrivate->serviceID, // service
837 NULL); // entity
838 entity = SCPreferencesPathGetValue(servicePrivate->prefs, path);
839 if ((entity == NULL) && (name != NULL)) {
840 entity = CFDictionaryCreate(NULL,
841 NULL,
842 NULL,
843 0,
844 &kCFTypeDictionaryKeyCallBacks,
845 &kCFTypeDictionaryValueCallBacks);
846 }
847 if (isA_CFDictionary(entity)) {
848 CFMutableDictionaryRef newEntity;
849
850 newEntity = CFDictionaryCreateMutableCopy(NULL, 0, entity);
851 if (isA_CFString(name)) {
852 CFDictionarySetValue(newEntity, kSCPropUserDefinedName, name);
853 } else {
854 CFDictionaryRemoveValue(newEntity, kSCPropUserDefinedName);
855 }
856 ok = SCPreferencesPathSetValue(servicePrivate->prefs, path, newEntity);
857 CFRelease(newEntity);
858 }
859 CFRelease(path);
860
861 return ok;
862 }