]> git.saurik.com Git - apple/configd.git/blame - SystemConfiguration.fproj/SCNetworkService.c
configd-137.2.tar.gz
[apple/configd.git] / SystemConfiguration.fproj / SCNetworkService.c
CommitLineData
dbf6a266 1/*
ba83da55 2 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
dbf6a266
A
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
42static CFStringRef __SCNetworkServiceCopyDescription (CFTypeRef cf);
43static void __SCNetworkServiceDeallocate (CFTypeRef cf);
44static Boolean __SCNetworkServiceEqual (CFTypeRef cf1, CFTypeRef cf2);
45
46
47static CFTypeID __kSCNetworkServiceTypeID = _kCFRuntimeNotATypeID;
48
49
50static 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
63static pthread_once_t initialized = PTHREAD_ONCE_INIT;
64
65
66static __inline__ CFTypeRef
67isA_SCNetworkService(CFTypeRef obj)
68{
69 return (isA_CFType(obj, SCNetworkServiceGetTypeID()));
70}
71
72
73static 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
90static 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
105static 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
124static 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
168Boolean
169SCNetworkServiceAddProtocolType(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
226CFArrayRef /* of SCNetworkServiceRef's */
227SCNetworkServiceCopyAll(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 */
302static 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
342SCNetworkServiceRef
343SCNetworkServiceCopy(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
366SCNetworkProtocolRef
367SCNetworkServiceCopyProtocol(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
410CFArrayRef /* of SCNetworkProtocolRef's */
411SCNetworkServiceCopyProtocols(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
477static Boolean
478__SCNetworkServiceSetInterfaceEntity(SCNetworkServiceRef service,
479 SCNetworkInterfaceRef interface)
480{
ba83da55
A
481 CFMutableDictionaryRef entity;
482 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
dbf6a266
A
483 Boolean ok;
484 CFStringRef path;
485 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
486
487 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
488 servicePrivate->serviceID, // service
489 kSCEntNetInterface); // entity
ba83da55
A
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 }
dbf6a266
A
525 ok = SCPreferencesPathSetValue(servicePrivate->prefs, path, entity);
526 CFRelease(entity);
527 CFRelease(path);
528
529 return ok;
530}
531
532
533SCNetworkServiceRef
534SCNetworkServiceCreate(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);
ba83da55 575 childInterface = SCNetworkInterfaceGetInterface(servicePrivate->interface);
dbf6a266
A
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
ba83da55 591 // push the [deep] interface configuration into into the service.
dbf6a266
A
592 interface_config = __SCNetworkInterfaceCopyDeepConfiguration(servicePrivate->interface);
593 __SCNetworkInterfaceSetDeepConfiguration(servicePrivate->interface, interface_config);
594
595 return (SCNetworkServiceRef)servicePrivate;
596}
597
598
599Boolean
600SCNetworkServiceGetEnabled(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
616SCNetworkInterfaceRef
617SCNetworkServiceGetInterface(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
640CFStringRef
641SCNetworkServiceGetName(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
662CFStringRef
663SCNetworkServiceGetServiceID(SCNetworkServiceRef service)
664{
665 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
666
667 return servicePrivate->serviceID;
668}
669
670
671CFTypeID
672SCNetworkServiceGetTypeID(void)
673{
674 pthread_once(&initialized, __SCNetworkServiceInitialize); /* initialize runtime */
675 return __kSCNetworkServiceTypeID;
676}
677
678
679Boolean
680SCNetworkServiceRemove(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)) {
ba83da55 701 break;
dbf6a266
A
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
719Boolean
720SCNetworkServiceRemoveProtocolType(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
747Boolean
748SCNetworkServiceSetEnabled(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
764Boolean
765SCNetworkServiceSetName(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}