]> git.saurik.com Git - apple/configd.git/blob - SystemConfiguration.fproj/SCNetworkSet.c
72653fac7337aa351131e6eab80ef289e1385fce
[apple/configd.git] / SystemConfiguration.fproj / SCNetworkSet.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 "SCNetworkConfiguration.h"
40 #include "SCNetworkConfigurationInternal.h"
41
42 #include <pthread.h>
43
44
45 static CFStringRef __SCNetworkSetCopyDescription (CFTypeRef cf);
46 static void __SCNetworkSetDeallocate (CFTypeRef cf);
47 static Boolean __SCNetworkSetEqual (CFTypeRef cf1, CFTypeRef cf2);
48
49
50 static CFTypeID __kSCNetworkSetTypeID = _kCFRuntimeNotATypeID;
51
52
53 static const CFRuntimeClass __SCNetworkSetClass = {
54 0, // version
55 "SCNetworkSet", // className
56 NULL, // init
57 NULL, // copy
58 __SCNetworkSetDeallocate, // dealloc
59 __SCNetworkSetEqual, // equal
60 NULL, // hash
61 NULL, // copyFormattingDesc
62 __SCNetworkSetCopyDescription // copyDebugDesc
63 };
64
65
66 static pthread_once_t initialized = PTHREAD_ONCE_INIT;
67
68
69 static __inline__ CFTypeRef
70 isA_SCNetworkSet(CFTypeRef obj)
71 {
72 return (isA_CFType(obj, SCNetworkSetGetTypeID()));
73 }
74
75
76 static CFStringRef
77 __SCNetworkSetCopyDescription(CFTypeRef cf)
78 {
79 CFAllocatorRef allocator = CFGetAllocator(cf);
80 CFMutableStringRef result;
81 SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)cf;
82
83 result = CFStringCreateMutable(allocator, 0);
84 CFStringAppendFormat(result, NULL, CFSTR("<SCNetworkSet %p [%p]> { "), cf, allocator);
85 CFStringAppendFormat(result, NULL, CFSTR("id=%@"), setPrivate->setID);
86 // CFStringAppendFormat(result, NULL, CFSTR(", prefs=%@"), setPrivate->prefs);
87 CFStringAppendFormat(result, NULL, CFSTR(" }"));
88
89 return result;
90 }
91
92
93 static void
94 __SCNetworkSetDeallocate(CFTypeRef cf)
95 {
96 SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)cf;
97
98 SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCNetworkSetDeallocate:"));
99
100 /* release resources */
101
102 CFRelease(setPrivate->setID);
103 CFRelease(setPrivate->prefs);
104
105 return;
106 }
107
108
109 static Boolean
110 __SCNetworkSetEqual(CFTypeRef cf1, CFTypeRef cf2)
111 {
112 SCNetworkSetPrivateRef s1 = (SCNetworkSetPrivateRef)cf1;
113 SCNetworkSetPrivateRef s2 = (SCNetworkSetPrivateRef)cf2;
114
115 if (s1 == s2)
116 return TRUE;
117
118 if (s1->prefs != s2->prefs)
119 return FALSE; // if not the same prefs
120
121 if (!CFEqual(s1->setID, s2->setID))
122 return FALSE; // if not the same set identifier
123
124 return TRUE;
125 }
126
127
128 static void
129 __SCNetworkSetInitialize(void)
130 {
131 __kSCNetworkSetTypeID = _CFRuntimeRegisterClass(&__SCNetworkSetClass);
132 return;
133 }
134
135
136 static SCNetworkSetPrivateRef
137 __SCNetworkSetCreatePrivate(CFAllocatorRef allocator,
138 SCPreferencesRef prefs,
139 CFStringRef setID)
140 {
141 SCNetworkSetPrivateRef setPrivate;
142 uint32_t size;
143
144 /* initialize runtime */
145 pthread_once(&initialized, __SCNetworkSetInitialize);
146
147 SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCNetworkSetCreatePrivate:"));
148
149 /* allocate target */
150 size = sizeof(SCNetworkSetPrivate) - sizeof(CFRuntimeBase);
151 setPrivate = (SCNetworkSetPrivateRef)_CFRuntimeCreateInstance(allocator,
152 __kSCNetworkSetTypeID,
153 size,
154 NULL);
155 if (setPrivate == NULL) {
156 return NULL;
157 }
158
159 setPrivate->setID = CFStringCreateCopy(NULL, setID);
160 setPrivate->prefs = CFRetain(prefs);
161
162 return setPrivate;
163 }
164
165
166 #define N_QUICK 16
167
168
169 Boolean
170 SCNetworkSetAddService(SCNetworkSetRef set, SCNetworkServiceRef service)
171 {
172 SCNetworkInterfaceRef interface;
173 CFArrayRef interface_config = NULL;
174 CFStringRef link;
175 Boolean ok;
176 CFStringRef path;
177 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
178 SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set;
179
180 #define PREVENT_DUPLICATE_SETS
181 #ifdef PREVENT_DUPLICATE_SETS
182 CFArrayRef sets;
183
184 // ensure that each service is only a member of ONE set
185
186 sets = SCNetworkSetCopyAll(setPrivate->prefs);
187 if (sets != NULL) {
188 CFIndex i;
189 CFIndex n;
190
191 n = CFArrayGetCount(sets);
192 for (i = 0; i < n; i++) {
193 Boolean found;
194 CFArrayRef services;
195 SCNetworkSetRef set;
196
197 set = CFArrayGetValueAtIndex(sets, i);
198 services = SCNetworkSetCopyServices(set);
199 found = CFArrayContainsValue(services,
200 CFRangeMake(0, CFArrayGetCount(services)),
201 service);
202 CFRelease(services);
203
204 if (found) {
205 CFRelease(sets);
206 _SCErrorSet(kSCStatusKeyExists);
207 return FALSE;
208 }
209 }
210 CFRelease(sets);
211 }
212 #endif /* PREVENT_DUPLICATE_SETS */
213
214 // get the [deep] interface configuration settings
215 interface = SCNetworkServiceGetInterface(service);
216 if (interface != NULL) {
217 interface_config = __SCNetworkInterfaceCopyDeepConfiguration(interface);
218 }
219
220 // create the link between "set" and the "service"
221 path = SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL, // allocator
222 setPrivate->setID, // set
223 servicePrivate->serviceID, // service
224 NULL); // entity
225 link = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
226 servicePrivate->serviceID, // service
227 NULL); // entity
228 ok = SCPreferencesPathSetLink(setPrivate->prefs, path, link);
229 CFRelease(path);
230 CFRelease(link);
231 if (!ok) {
232 return ok;
233 }
234
235 // push the [deep] interface configuration into all sets which contain this service.
236 if (interface != NULL) {
237 __SCNetworkInterfaceSetDeepConfiguration(interface, interface_config);
238 }
239
240 return ok;
241 }
242
243
244 SCNetworkSetRef
245 SCNetworkSetCopy(SCPreferencesRef prefs, CFStringRef setID)
246 {
247 CFDictionaryRef entity;
248 CFStringRef path;
249 SCNetworkSetPrivateRef setPrivate;
250
251 path = SCPreferencesPathKeyCreateSet(NULL, setID);
252 entity = SCPreferencesPathGetValue(prefs, path);
253 CFRelease(path);
254
255 if (!isA_CFDictionary(entity)) {
256 _SCErrorSet(kSCStatusNoKey);
257 return NULL;
258 }
259
260 setPrivate = __SCNetworkSetCreatePrivate(NULL, prefs, setID);
261 return (SCNetworkSetRef)setPrivate;
262 }
263
264
265 CFArrayRef /* of SCNetworkServiceRef's */
266 SCNetworkSetCopyAll(SCPreferencesRef prefs)
267 {
268 CFMutableArrayRef array;
269 CFIndex n;
270 CFStringRef path;
271 CFDictionaryRef sets;
272
273 path = SCPreferencesPathKeyCreateSets(NULL);
274 sets = SCPreferencesPathGetValue(prefs, path);
275 CFRelease(path);
276
277 if ((sets != NULL) && !isA_CFDictionary(sets)) {
278 return NULL;
279 }
280
281 array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
282
283 n = (sets != NULL) ? CFDictionaryGetCount(sets) : 0;
284 if (n > 0) {
285 CFIndex i;
286 const void * keys_q[N_QUICK];
287 const void ** keys = keys_q;
288 const void * vals_q[N_QUICK];
289 const void ** vals = vals_q;
290
291 if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) {
292 keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0);
293 vals = CFAllocatorAllocate(NULL, n * sizeof(CFPropertyListRef), 0);
294 }
295 CFDictionaryGetKeysAndValues(sets, keys, vals);
296 for (i = 0; i < n; i++) {
297 SCNetworkSetPrivateRef setPrivate;
298
299 if (!isA_CFDictionary(vals[i])) {
300 SCLog(TRUE,
301 LOG_INFO,
302 CFSTR("SCNetworkSetCopyAll(): error w/set \"%@\"\n"),
303 keys[i]);
304 continue;
305 }
306
307 setPrivate = __SCNetworkSetCreatePrivate(NULL, prefs, keys[i]);
308 CFArrayAppendValue(array, (SCNetworkSetRef)setPrivate);
309 CFRelease(setPrivate);
310 }
311 if (keys != keys_q) {
312 CFAllocatorDeallocate(NULL, keys);
313 CFAllocatorDeallocate(NULL, vals);
314 }
315 }
316
317 return array;
318 }
319
320
321 SCNetworkSetRef
322 SCNetworkSetCopyCurrent(SCPreferencesRef prefs)
323 {
324 CFArrayRef components;
325 CFStringRef currentID;
326 SCNetworkSetPrivateRef setPrivate = NULL;
327
328 currentID = SCPreferencesGetValue(prefs, kSCPrefCurrentSet);
329 if (!isA_CFString(currentID)) {
330 return NULL;
331 }
332
333 components = CFStringCreateArrayBySeparatingStrings(NULL, currentID, CFSTR("/"));
334 if (CFArrayGetCount(components) == 3) {
335 CFStringRef setID;
336 CFStringRef path;
337
338 setID = CFArrayGetValueAtIndex(components, 2);
339 path = SCPreferencesPathKeyCreateSet(NULL, setID);
340 if (CFEqual(path, currentID)) {
341 setPrivate = __SCNetworkSetCreatePrivate(NULL, prefs, setID);
342 } else {
343 SCLog(TRUE, LOG_ERR, CFSTR("SCNetworkSetCopyCurrent(): preferences are non-conformant"));
344 }
345 CFRelease(path);
346 }
347 CFRelease(components);
348
349 return (SCNetworkSetRef)setPrivate;
350 }
351
352
353 CFArrayRef /* of SCNetworkServiceRef's */
354 SCNetworkSetCopyServices(SCNetworkSetRef set)
355 {
356 CFMutableArrayRef array;
357 CFDictionaryRef dict;
358 CFIndex n;
359 CFStringRef path;
360 SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set;
361
362 path = SCPreferencesPathKeyCreateSetNetworkService(NULL, setPrivate->setID, NULL);
363 dict = SCPreferencesPathGetValue(setPrivate->prefs, path);
364 CFRelease(path);
365 if ((dict != NULL) && !isA_CFDictionary(dict)) {
366 return NULL;
367 }
368
369 array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
370
371 n = (dict != NULL) ? CFDictionaryGetCount(dict) : 0;
372 if (n > 0) {
373 CFIndex i;
374 const void * keys_q[N_QUICK];
375 const void ** keys = keys_q;
376
377 if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) {
378 keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0);
379 }
380 CFDictionaryGetKeysAndValues(dict, keys, NULL);
381 for (i = 0; i < n; i++) {
382 CFArrayRef components;
383 CFStringRef link;
384
385 path = SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL,
386 setPrivate->setID,
387 (CFStringRef)keys[i],
388 NULL);
389 link = SCPreferencesPathGetLink(setPrivate->prefs, path);
390 CFRelease(path);
391 if (link == NULL) {
392 SCLog(TRUE,
393 LOG_INFO,
394 CFSTR("SCNetworkSetCopyServices(): service \"%@\" for set \"%@\" is not a link\n"),
395 keys[i],
396 setPrivate->setID);
397 continue; // if the service is not a link
398 }
399
400 components = CFStringCreateArrayBySeparatingStrings(NULL, link, CFSTR("/"));
401 if (CFArrayGetCount(components) == 3) {
402 CFStringRef serviceID;
403
404 serviceID = CFArrayGetValueAtIndex(components, 2);
405 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
406 serviceID, // service
407 NULL); // entity
408 if (CFEqual(path, link)) {
409 SCNetworkServicePrivateRef servicePrivate;
410
411 servicePrivate = __SCNetworkServiceCreatePrivate(NULL,
412 serviceID,
413 NULL,
414 setPrivate->prefs);
415 CFArrayAppendValue(array, (SCNetworkServiceRef)servicePrivate);
416 CFRelease(servicePrivate);
417 }
418 CFRelease(path);
419 }
420 CFRelease(components);
421 }
422 if (keys != keys_q) {
423 CFAllocatorDeallocate(NULL, keys);
424 }
425 }
426
427 return array;
428 }
429
430
431 SCNetworkSetRef
432 SCNetworkSetCreate(SCPreferencesRef prefs)
433 {
434 CFArrayRef components;
435 CFStringRef path;
436 CFStringRef prefix;
437 CFStringRef setID;
438 SCNetworkSetPrivateRef setPrivate;
439
440 prefix = SCPreferencesPathKeyCreateSets(NULL);
441 path = SCPreferencesPathCreateUniqueChild(prefs, prefix);
442 CFRelease(prefix);
443 if (path == NULL) {
444 return NULL;
445 }
446
447 components = CFStringCreateArrayBySeparatingStrings(NULL, path, CFSTR("/"));
448 CFRelease(path);
449
450 setID = CFArrayGetValueAtIndex(components, 2);
451 setPrivate = __SCNetworkSetCreatePrivate(NULL, prefs, setID);
452 CFRelease(components);
453
454 return (SCNetworkSetRef)setPrivate;
455 }
456
457
458 CFStringRef
459 SCNetworkSetGetSetID(SCNetworkSetRef set)
460 {
461 SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set;
462
463 return setPrivate->setID;
464 }
465
466
467 CFStringRef
468 SCNetworkSetGetName(SCNetworkSetRef set)
469 {
470 CFDictionaryRef entity;
471 CFStringRef name = NULL;
472 CFStringRef path;
473 SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set;
474
475 path = SCPreferencesPathKeyCreateSet(NULL, setPrivate->setID);
476 entity = SCPreferencesPathGetValue(setPrivate->prefs, path);
477 CFRelease(path);
478
479 if (isA_CFDictionary(entity)) {
480 name = CFDictionaryGetValue(entity, kSCPropUserDefinedName);
481 }
482
483 return isA_CFString(name) ? name : NULL;
484 }
485
486
487 CFArrayRef /* of serviceID CFStringRef's */
488 SCNetworkSetGetServiceOrder(SCNetworkSetRef set)
489 {
490 CFDictionaryRef dict;
491 CFStringRef path;
492 CFArrayRef serviceOrder;
493 SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set;
494
495 path = SCPreferencesPathKeyCreateSetNetworkGlobalEntity(NULL, setPrivate->setID, kSCEntNetIPv4);
496 if (path == NULL) {
497 return NULL;
498 }
499
500 dict = SCPreferencesPathGetValue(setPrivate->prefs, path);
501 CFRelease(path);
502 if (!isA_CFDictionary(dict)) {
503 return NULL;
504 }
505
506 serviceOrder = CFDictionaryGetValue(dict, kSCPropNetServiceOrder);
507 serviceOrder = isA_CFArray(serviceOrder);
508
509 return serviceOrder;
510 }
511
512
513 CFTypeID
514 SCNetworkSetGetTypeID(void)
515 {
516 pthread_once(&initialized, __SCNetworkSetInitialize); /* initialize runtime */
517 return __kSCNetworkSetTypeID;
518 }
519
520
521 Boolean
522 SCNetworkSetRemove(SCNetworkSetRef set)
523 {
524 CFStringRef currentPath;
525 Boolean ok = FALSE;
526 CFStringRef path;
527 SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set;
528
529 currentPath = SCPreferencesGetValue(setPrivate->prefs, kSCPrefCurrentSet);
530 path = SCPreferencesPathKeyCreateSet(NULL, setPrivate->setID);
531 if (!isA_CFString(currentPath) || !CFEqual(currentPath, path)) {
532 ok = SCPreferencesPathRemoveValue(setPrivate->prefs, path);
533 }
534 CFRelease(path);
535
536 return ok;
537 }
538
539
540 Boolean
541 SCNetworkSetRemoveService(SCNetworkSetRef set, SCNetworkServiceRef service)
542 {
543 SCNetworkInterfaceRef interface;
544 CFArrayRef interface_config = NULL;
545 Boolean ok;
546 CFStringRef path;
547 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
548 SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set;
549
550 // get the [deep] interface configuration settings
551 interface = SCNetworkServiceGetInterface(service);
552 if (interface != NULL) {
553 interface_config = __SCNetworkInterfaceCopyDeepConfiguration(interface);
554 if (interface_config != NULL) {
555 // remove the interface configuration from all sets which contain this service.
556 __SCNetworkInterfaceSetDeepConfiguration(interface, NULL);
557 }
558 }
559
560 // remove the link between "set" and the "service"
561 path = SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL,
562 setPrivate->setID,
563 servicePrivate->serviceID,
564 NULL);
565 ok = SCPreferencesPathRemoveValue(setPrivate->prefs, path);
566 CFRelease(path);
567 if (!ok) {
568 goto done;
569 }
570
571 // push the [deep] interface configuration [back] into all sets which contain the service.
572 if (interface_config != NULL) {
573 __SCNetworkInterfaceSetDeepConfiguration(interface, interface_config);
574 }
575
576 done :
577
578 if (interface_config != NULL) CFRelease(interface_config);
579 return ok;
580 }
581
582
583 Boolean
584 SCNetworkSetSetCurrent(SCNetworkSetRef set)
585 {
586 Boolean ok;
587 CFStringRef path;
588 SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set;
589
590 path = SCPreferencesPathKeyCreateSet(NULL, setPrivate->setID);
591 ok = SCPreferencesSetValue(setPrivate->prefs, kSCPrefCurrentSet, path);
592 CFRelease(path);
593 return ok;
594 }
595
596
597 Boolean
598 SCNetworkSetSetName(SCNetworkSetRef set, CFStringRef name)
599 {
600 CFDictionaryRef entity;
601 Boolean ok = FALSE;
602 CFStringRef path;
603 SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set;
604
605 #define PREVENT_DUPLICATE_SET_NAMES
606 #ifdef PREVENT_DUPLICATE_SET_NAMES
607 if (isA_CFString(name)) {
608 CFArrayRef sets;
609
610 // ensure that each set is uniquely named
611
612 sets = SCNetworkSetCopyAll(setPrivate->prefs);
613 if (sets != NULL) {
614 CFIndex i;
615 CFIndex n;
616
617 n = CFArrayGetCount(sets);
618 for (i = 0; i < n; i++) {
619 CFStringRef otherID;
620 CFStringRef otherName;
621 SCNetworkSetRef set = CFArrayGetValueAtIndex(sets, i);
622
623 otherID = SCNetworkSetGetSetID(set);
624 if (CFEqual(setPrivate->setID, otherID)) {
625 continue; // skip current set
626 }
627
628 otherName = SCNetworkSetGetName(set);
629 if ((otherName != NULL) && CFEqual(name, otherName)) {
630 // if "name" not unique
631 CFRelease(sets);
632 _SCErrorSet(kSCStatusKeyExists);
633 return FALSE;
634 }
635 }
636 CFRelease(sets);
637 }
638 }
639 #endif /* PREVENT_DUPLICATE_SET_NAMES */
640
641 // update the "name"
642
643 path = SCPreferencesPathKeyCreateSet(NULL, setPrivate->setID);
644 entity = SCPreferencesPathGetValue(setPrivate->prefs, path);
645 if ((entity == NULL) && (name != NULL)) {
646 entity = CFDictionaryCreate(NULL,
647 NULL,
648 NULL,
649 0,
650 &kCFTypeDictionaryKeyCallBacks,
651 &kCFTypeDictionaryValueCallBacks);
652 }
653 if (isA_CFDictionary(entity)) {
654 CFMutableDictionaryRef newEntity;
655
656 newEntity = CFDictionaryCreateMutableCopy(NULL, 0, entity);
657 if (isA_CFString(name)) {
658 CFDictionarySetValue(newEntity, kSCPropUserDefinedName, name);
659 } else {
660 CFDictionaryRemoveValue(newEntity, kSCPropUserDefinedName);
661 }
662 ok = SCPreferencesPathSetValue(setPrivate->prefs, path, newEntity);
663 CFRelease(newEntity);
664 }
665 CFRelease(path);
666
667 return ok;
668 }
669
670
671 Boolean
672 SCNetworkSetSetServiceOrder(SCNetworkSetRef set, CFArrayRef newOrder)
673 {
674 CFDictionaryRef dict;
675 CFMutableDictionaryRef newDict;
676 Boolean ok;
677 CFStringRef path;
678 SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set;
679
680 path = SCPreferencesPathKeyCreateSetNetworkGlobalEntity(NULL, setPrivate->setID, kSCEntNetIPv4);
681 if (path == NULL) {
682 return FALSE;
683 }
684
685 dict = SCPreferencesPathGetValue(setPrivate->prefs, path);
686 if (dict != NULL) {
687 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
688 } else {
689 newDict = CFDictionaryCreateMutable(NULL,
690 0,
691 &kCFTypeDictionaryKeyCallBacks,
692 &kCFTypeDictionaryValueCallBacks);
693 }
694
695 CFDictionarySetValue(newDict, kSCPropNetServiceOrder, newOrder);
696 ok = SCPreferencesPathSetValue(setPrivate->prefs, path, newDict);
697 CFRelease(newDict);
698 CFRelease(path);
699
700 return ok;
701 }