]> git.saurik.com Git - apple/configd.git/blob - scutil.tproj/prefs.c
configd-1061.101.1.tar.gz
[apple/configd.git] / scutil.tproj / prefs.c
1 /*
2 * Copyright (c) 2003-2008, 2011-2017, 2019, 2020 Apple 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 29, 2003 Allan Nathanson <ajn@apple.com>
28 * - initial revision
29 */
30
31 #include <TargetConditionals.h>
32 #include <dlfcn.h>
33 #include <unistd.h>
34 #include <sys/param.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37
38 #include "scutil.h"
39 #include "commands.h"
40 #include "prefs.h"
41
42 #include "SCNetworkConfigurationInternal.h"
43
44 #if !TARGET_OS_IPHONE
45 #include <Security/Authorization.h>
46 #endif /* !TARGET_OS_IPHONE */
47
48
49 /* -------------------- */
50
51
52 #if !TARGET_OS_IPHONE
53 static void *
54 __loadSecurity(void) {
55 static void *image = NULL;
56 static dispatch_once_t once;
57
58 dispatch_once(&once, ^{
59 image = _SC_dlopen("/System/Library/Frameworks/Security.framework/Security");
60 });
61
62 return image;
63 }
64
65
66 static OSStatus
67 _AuthorizationCreate(const AuthorizationRights *rights, const AuthorizationEnvironment *environment, AuthorizationFlags flags, AuthorizationRef *authorization)
68 {
69 #undef AuthorizationCreate
70 static typeof (AuthorizationCreate) *dyfunc = NULL;
71 if (dyfunc == NULL) {
72 void *image = __loadSecurity();
73 if (image) dyfunc = dlsym(image, "AuthorizationCreate");
74 }
75 return dyfunc ? dyfunc(rights, environment, flags, authorization) : -1;
76 }
77 #define AuthorizationCreate _AuthorizationCreate
78
79
80 static OSStatus
81 _AuthorizationFree(AuthorizationRef authorization, AuthorizationFlags flags)
82 {
83 #undef AuthorizationFree
84 static typeof (AuthorizationFree) *dyfunc = NULL;
85 if (dyfunc == NULL) {
86 void *image = __loadSecurity();
87 if (image) dyfunc = dlsym(image, "AuthorizationFree");
88 }
89 return dyfunc ? dyfunc(authorization, flags) : -1;
90 }
91 #define AuthorizationFree _AuthorizationFree
92
93
94 /* -------------------- */
95
96 __private_extern__
97 AuthorizationRef
98 _prefs_AuthorizationCreate()
99 {
100 AuthorizationRef authorization = NULL;
101
102 if (getenv("SCPREFERENCES_USE_ENTITLEMENTS") != NULL) {
103 authorization = kSCPreferencesUseEntitlementAuthorization;
104 } else {
105 AuthorizationFlags flags = kAuthorizationFlagDefaults;
106 OSStatus status;
107
108 status = AuthorizationCreate(NULL,
109 kAuthorizationEmptyEnvironment,
110 flags,
111 &authorization);
112 if (status != errAuthorizationSuccess) {
113 SCPrint(TRUE,
114 stdout,
115 CFSTR("AuthorizationCreate() failed: status = %d\n"),
116 (int)status);
117 return NULL;
118 }
119 }
120
121 return authorization;
122 }
123
124
125 __private_extern__
126 void
127 _prefs_AuthorizationFree(AuthorizationRef authorization)
128 {
129 if (authorization != kSCPreferencesUseEntitlementAuthorization) {
130 AuthorizationFree(authorization, kAuthorizationFlagDefaults);
131 // AuthorizationFree(authorization, kAuthorizationFlagDestroyRights);
132 }
133
134 return;
135 }
136
137 #endif /* !TARGET_OS_IPHONE */
138
139 /* -------------------- */
140
141
142 __private_extern__ Boolean _prefs_changed = FALSE;
143
144
145 __private_extern__
146 Boolean
147 _prefs_open(CFStringRef name, const char *path)
148 {
149 char *env = NULL;
150 CFMutableDictionaryRef options = NULL;
151 CFStringRef prefsID = NULL;
152 Boolean useHelper = FALSE;
153 Boolean useOptions = FALSE;
154
155 authorization = NULL;
156
157 if (geteuid() != 0) {
158 // if we need to use a helper
159 useHelper = TRUE;
160
161 #if !TARGET_OS_IPHONE
162 authorization = _prefs_AuthorizationCreate();
163 #else
164 authorization = kSCPreferencesUseEntitlementAuthorization;
165 #endif /* !TARGET_OS_IPHONE */
166 }
167
168 if (getenv("SCPREFERENCES_REMOVE_WHEN_EMPTY") != NULL) {
169 if (options == NULL) {
170 options = CFDictionaryCreateMutable(NULL,
171 0,
172 &kCFTypeDictionaryKeyCallBacks,
173 &kCFTypeDictionaryValueCallBacks);
174 useOptions = TRUE;
175 }
176 CFDictionarySetValue(options, kSCPreferencesOptionRemoveWhenEmpty, kCFBooleanTrue);
177 }
178
179 env = getenv("SCPREFERENCES_PROTECTION_CLASS");
180 if (env != NULL) {
181 CFStringRef str;
182
183 if (options == NULL) {
184 options = CFDictionaryCreateMutable(NULL,
185 0,
186 &kCFTypeDictionaryKeyCallBacks,
187 &kCFTypeDictionaryValueCallBacks);
188 useOptions = TRUE;
189 }
190 str = CFStringCreateWithCString(NULL, env, kCFStringEncodingASCII);
191 CFDictionarySetValue(options, kSCPreferencesOptionProtectionClass, str);
192 CFRelease(str);
193 }
194
195 if (path != NULL) {
196 prefsPath = strdup(path);
197 prefsID = CFStringCreateWithCString(NULL, path, kCFStringEncodingUTF8);
198 }
199
200 if (!useHelper && !useOptions) {
201 // if no helper/options needed
202 prefs = SCPreferencesCreate(NULL, name, prefsID);
203 } else if (!useOptions) {
204 // if no options needed
205 prefs = SCPreferencesCreateWithAuthorization(NULL, name, prefsID, authorization);
206 } else {
207 prefs = SCPreferencesCreateWithOptions(NULL, name, prefsID, authorization, options);
208 CFRelease(options);
209 }
210
211 if (prefsID != NULL) CFRelease(prefsID);
212 if (prefs == NULL) {
213 if (prefsPath != NULL) free(prefsPath);
214 prefsPath = NULL;
215 return FALSE;
216 }
217
218 _prefs_changed = FALSE;
219 return TRUE;
220 }
221
222
223 __private_extern__
224 void
225 _prefs_save()
226 {
227 if (!SCPreferencesCommitChanges(prefs)) {
228 switch (SCError()) {
229 case kSCStatusAccessError :
230 SCPrint(TRUE, stderr, CFSTR("Permission denied.\n"));
231 break;
232 default :
233 SCPrint(TRUE,
234 stdout,
235 CFSTR("SCPreferencesCommitChanges() failed: %s\n"),
236 SCErrorString(SCError()));
237 break;
238 }
239 exit (1);
240 }
241
242 if (!SCPreferencesApplyChanges(prefs)) {
243 SCPrint(TRUE,
244 stdout,
245 CFSTR("SCPreferencesApplyChanges() failed: %s\n"),
246 SCErrorString(SCError()));
247 exit (1);
248 }
249
250 _prefs_changed = FALSE;
251
252 if (ni_prefs != NULL) {
253 if (!SCPreferencesCommitChanges(ni_prefs)) {
254 switch (SCError()) {
255 case kSCStatusAccessError :
256 SCPrint(TRUE, stderr, CFSTR("Permission denied.\n"));
257 break;
258 default :
259 SCPrint(TRUE,
260 stdout,
261 CFSTR("SCPreferencesCommitChanges( <NetworkInterfaces.plist> ) failed: %s\n"),
262 SCErrorString(SCError()));
263 break;
264 }
265 exit (1);
266 }
267
268 if (!SCPreferencesApplyChanges(ni_prefs)) {
269 SCPrint(TRUE,
270 stdout,
271 CFSTR("SCPreferencesApplyChanges( <NetworkInterfaces.plist> ) failed: %s\n"),
272 SCErrorString(SCError()));
273 exit (1);
274 }
275 }
276
277 return;
278 }
279
280
281 __private_extern__
282 void
283 _prefs_close()
284 {
285 if (prefsPath != NULL) {
286 free(prefsPath);
287 prefsPath = NULL;
288 }
289
290 if (prefs != NULL) {
291 CFRelease(prefs);
292 prefs = NULL;
293 _prefs_changed = FALSE;
294 }
295
296 if (ni_prefs != NULL) {
297 CFRelease(ni_prefs);
298 ni_prefs = NULL;
299 }
300
301 if (authorization != NULL) {
302 #if !TARGET_OS_IPHONE
303 _prefs_AuthorizationFree(authorization);
304 #else /* !TARGET_OS_IPHONE */
305 // Uh...if authorization isn't NULL, something went horribly wrong.
306 #endif /* !TARGET_OS_IPHONE */
307 authorization = NULL;
308 }
309
310 return;
311 }
312
313
314 __private_extern__
315 Boolean
316 _prefs_commitRequired(int argc, char **argv, const char *command)
317 {
318 if (_prefs_changed) {
319 if ((currentInput != NULL) &&
320 isatty(fileno(currentInput->fp)) &&
321 ((argc < 1) || (strcmp(argv[0], "!") != 0))
322 ) {
323 SCPrint(TRUE, stdout,
324 CFSTR("preference changes have not been committed\n"
325 "use \"commit\" to save changes"));
326 if (command != NULL) {
327 SCPrint(TRUE, stdout,
328 CFSTR(" or \"%s !\" to abandon changes"),
329 command);
330 }
331 SCPrint(TRUE, stdout, CFSTR("\n"));
332 return TRUE;
333 }
334
335 SCPrint(TRUE, stdout, CFSTR("preference changes abandoned\n"));
336 }
337
338 return FALSE;
339 }
340
341
342 /* -------------------- */
343
344
345 static void
346 get_ComputerName(int argc, char **argv)
347 {
348 #pragma unused(argc)
349 #pragma unused(argv)
350 CFStringEncoding encoding;
351 CFStringRef hostname;
352
353 hostname = SCDynamicStoreCopyComputerName(NULL, &encoding);
354 if (hostname == NULL) {
355 int sc_status = SCError();
356
357 switch (sc_status) {
358 case kSCStatusNoKey :
359 SCPrint(TRUE,
360 stderr,
361 CFSTR("ComputerName: not set\n"));
362 break;
363 default :
364 SCPrint(TRUE,
365 stderr,
366 CFSTR("SCDynamicStoreCopyComputerName() failed: %s\n"),
367 SCErrorString(SCError()));
368 break;
369 }
370 exit (1);
371 }
372
373 SCPrint(TRUE, stdout, CFSTR("%@\n"), hostname);
374 CFRelease(hostname);
375
376 exit(0);
377 }
378
379
380 static void
381 set_ComputerName(int argc, char **argv)
382 {
383 CFStringRef hostname = NULL;
384 Boolean ok;
385
386 ok = _prefs_open(CFSTR("scutil --set ComputerName"), NULL);
387 if (!ok) {
388 SCPrint(TRUE,
389 stdout,
390 CFSTR("Could not open prefs: %s\n"),
391 SCErrorString(SCError()));
392 exit(1);
393 }
394
395 if (argc == 0) {
396 CFStringEncoding old_encoding;
397 CFStringRef old_hostname;
398
399 old_hostname = SCDynamicStoreCopyComputerName(NULL, &old_encoding);
400 hostname = _copyStringFromSTDIN(CFSTR("ComputerName"), old_hostname);
401 if (old_hostname) CFRelease(old_hostname);
402 } else if (strlen(argv[0]) > 0) {
403 hostname = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
404 }
405
406 ok = SCPreferencesSetComputerName(prefs, hostname, kCFStringEncodingUTF8);
407 if (hostname != NULL) CFRelease(hostname);
408 if (!ok) {
409 SCPrint(TRUE,
410 stdout,
411 CFSTR("Could not open prefs: %s\n"),
412 SCErrorString(SCError()));
413 _prefs_close();
414 exit (1);
415 }
416
417 _prefs_save();
418 _prefs_close();
419 exit(0);
420 }
421
422
423 static void
424 get_HostName(int argc, char **argv)
425 {
426 #pragma unused(argc)
427 #pragma unused(argv)
428 CFStringRef hostname;
429 Boolean ok;
430
431 ok = _prefs_open(CFSTR("scutil --get HostName"), NULL);
432 if (!ok) {
433 SCPrint(TRUE,
434 stdout,
435 CFSTR("SCPreferencesCreate() failed: %s\n"),
436 SCErrorString(SCError()));
437 exit(1);
438 }
439
440 hostname = SCPreferencesGetHostName(prefs);
441 if (hostname == NULL) {
442 int sc_status = SCError();
443
444 switch (sc_status) {
445 case kSCStatusNoKey :
446 SCPrint(TRUE,
447 stderr,
448 CFSTR("HostName: not set\n"));
449 break;
450 default :
451 SCPrint(TRUE,
452 stderr,
453 CFSTR("SCPreferencesGetHostName() failed: %s\n"),
454 SCErrorString(SCError()));
455 break;
456 }
457 _prefs_close();
458 exit (1);
459 }
460
461 SCPrint(TRUE, stdout, CFSTR("%@\n"), hostname);
462 _prefs_close();
463 exit(0);
464 }
465
466
467 static void
468 set_HostName(int argc, char **argv)
469 {
470 CFStringRef hostname = NULL;
471 Boolean ok;
472
473 ok = _prefs_open(CFSTR("scutil --set HostName"), NULL);
474 if (!ok) {
475 SCPrint(TRUE,
476 stdout,
477 CFSTR("Could not open prefs: %s\n"),
478 SCErrorString(SCError()));
479 exit(1);
480 }
481
482 if (argc == 0) {
483 hostname = _copyStringFromSTDIN(CFSTR("HostName"), SCPreferencesGetHostName(prefs));
484 } else if (strlen(argv[0]) > 0) {
485 hostname = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
486 }
487
488 ok = SCPreferencesSetHostName(prefs, hostname);
489 if (hostname != NULL) CFRelease(hostname);
490 if (!ok) {
491 SCPrint(TRUE,
492 stderr,
493 CFSTR("SCPreferencesSetHostName() failed: %s\n"),
494 SCErrorString(SCError()));
495 _prefs_close();
496 exit (1);
497 }
498
499 _prefs_save();
500 _prefs_close();
501 exit(0);
502 }
503
504
505 static void
506 get_LocalHostName(int argc, char **argv)
507 {
508 #pragma unused(argc)
509 #pragma unused(argv)
510 CFStringRef hostname;
511
512 hostname = SCDynamicStoreCopyLocalHostName(NULL);
513 if (hostname == NULL) {
514 int sc_status = SCError();
515
516 switch (sc_status) {
517 case kSCStatusNoKey :
518 SCPrint(TRUE,
519 stderr,
520 CFSTR("LocalHostName: not set\n"));
521 break;
522 default :
523 SCPrint(TRUE,
524 stderr,
525 CFSTR("SCDynamicStoreCopyLocalHostName() failed: %s\n"),
526 SCErrorString(SCError()));
527 break;
528 }
529 exit (1);
530 }
531
532 SCPrint(TRUE, stdout, CFSTR("%@\n"), hostname);
533 CFRelease(hostname);
534
535 exit(0);
536 }
537
538
539 static void
540 set_LocalHostName(int argc, char **argv)
541 {
542 CFStringRef hostname = NULL;
543 Boolean ok;
544
545 ok = _prefs_open(CFSTR("scutil --set LocalHostName"), NULL);
546 if (!ok) {
547 SCPrint(TRUE,
548 stdout,
549 CFSTR("Could not open prefs: %s\n"),
550 SCErrorString(SCError()));
551 exit(1);
552 }
553
554 if (argc == 0) {
555 CFStringRef old_hostname;
556
557 old_hostname = SCDynamicStoreCopyLocalHostName(NULL);
558 hostname = _copyStringFromSTDIN(CFSTR("LocalHostName"), old_hostname);
559 if (old_hostname) CFRelease(old_hostname);
560 } else if (strlen(argv[0]) > 0) {
561 hostname = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
562 }
563
564 ok = SCPreferencesSetLocalHostName(prefs, hostname);
565 if (hostname != NULL) CFRelease(hostname);
566 if (!ok) {
567 SCPrint(TRUE,
568 stderr,
569 CFSTR("SCPreferencesSetLocalHostName() failed: %s\n"),
570 SCErrorString(SCError()));
571 _prefs_close();
572 exit (1);
573 }
574
575 _prefs_save();
576 _prefs_close();
577 exit(0);
578 }
579
580
581 /* -------------------- */
582
583
584 typedef void (*pref_func) (int argc, char **argv);
585
586 static const struct {
587 char *pref;
588 pref_func get;
589 pref_func set;
590 } pref_keys[] = {
591 { "ComputerName", get_ComputerName, set_ComputerName },
592 { "HostName", get_HostName, set_HostName },
593 { "LocalHostName", get_LocalHostName, set_LocalHostName }
594 };
595 #define N_PREF_KEYS (sizeof(pref_keys) / sizeof(pref_keys[0]))
596
597
598 __private_extern__
599 int
600 findPref(char *pref)
601 {
602 int i;
603
604 for (i = 0; i < (int)N_PREF_KEYS; i++) {
605 if (strcmp(pref, pref_keys[i].pref) == 0) {
606 return i;
607 }
608 }
609
610 return -1;
611 }
612
613
614 __private_extern__
615 void
616 do_getPref(char *pref, int argc, char **argv)
617 {
618 int i;
619
620 if (argc == 0) {
621 i = findPref(pref);
622 if (i >= 0) {
623 (*pref_keys[i].get)(argc, argv);
624 }
625 return;
626 }
627
628 // process extended get
629 // ie. scutil --get <filename> <prefs path> <key>
630 do_prefs_init();
631
632 do_prefs_open(argc, argv);
633 if (SCError() != kSCStatusOK) {
634 SCPrint(TRUE, stderr, CFSTR("%s\n"), SCErrorString(SCError()));
635 _prefs_close();
636 exit(1);
637 }
638
639 do_prefs_get(--argc, ++argv);
640 if (value != NULL) {
641 CFStringRef key;
642 CFStringRef prefs_val;
643
644 key = CFStringCreateWithCString(NULL, *(++argv), kCFStringEncodingUTF8);
645 prefs_val = CFDictionaryGetValue(value, key);
646 CFRelease(key);
647
648 if (prefs_val != NULL) {
649 SCPrint(TRUE, stdout, CFSTR("%@\n"), prefs_val);
650 _prefs_close();
651 exit(0);
652 }
653 }
654
655 // if path or key not found
656 _prefs_close();
657 exit(1);
658 }
659
660
661 __private_extern__
662 void
663 do_setPref(char *pref, int argc, char **argv)
664 {
665 int i;
666
667 i = findPref(pref);
668 if (i >= 0) {
669 (*pref_keys[i].set)(argc, argv);
670 }
671 return;
672 }
673
674
675 /* -------------------- */
676
677
678 __private_extern__
679 void
680 do_prefs_init()
681 {
682 return;
683 }
684
685
686 __private_extern__
687 void
688 do_prefs_open(int argc, char **argv)
689 {
690 Boolean ok;
691
692 if (prefs != NULL) {
693 if (_prefs_commitRequired(argc, argv, "close")) {
694 return;
695 }
696
697 do_prefs_close(0, NULL);
698 }
699
700 ok = _prefs_open(CFSTR("scutil --prefs"), (argc > 0) ? argv[0] : NULL);
701 if (!ok) {
702 SCPrint(TRUE,
703 stdout,
704 CFSTR("Could not open prefs: %s\n"),
705 SCErrorString(SCError()));
706 return;
707 }
708
709 return;
710 }
711
712
713 __private_extern__
714 void
715 do_prefs_lock(int argc, char **argv)
716 {
717 #pragma unused(argv)
718 Boolean wait = (argc > 0) ? TRUE : FALSE;
719
720 if (!SCPreferencesLock(prefs, wait)) {
721 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
722 return;
723 }
724
725 return;
726 }
727
728
729 __private_extern__
730 void
731 do_prefs_unlock(int argc, char **argv)
732 {
733 #pragma unused(argc)
734 #pragma unused(argv)
735 if (!SCPreferencesUnlock(prefs)) {
736 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
737 return;
738 }
739
740 return;
741 }
742
743
744 __private_extern__
745 void
746 do_prefs_commit(int argc, char **argv)
747 {
748 #pragma unused(argc)
749 #pragma unused(argv)
750 if (!SCPreferencesCommitChanges(prefs)) {
751 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
752 return;
753 }
754
755 _prefs_changed = FALSE;
756 return;
757 }
758
759
760 __private_extern__
761 void
762 do_prefs_apply(int argc, char **argv)
763 {
764 #pragma unused(argc)
765 #pragma unused(argv)
766 if (!SCPreferencesApplyChanges(prefs)) {
767 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
768 }
769
770 return;
771 }
772
773
774 __private_extern__
775 void
776 do_prefs_close(int argc, char **argv)
777 {
778 if (_prefs_commitRequired(argc, argv, "close")) {
779 return;
780 }
781
782 _prefs_close();
783 return;
784 }
785
786
787 __private_extern__
788 void
789 do_prefs_quit(int argc, char **argv)
790 {
791 if (_prefs_commitRequired(argc, argv, "quit")) {
792 return;
793 }
794
795 _prefs_close();
796
797 termRequested = TRUE;
798 return;
799 }
800
801
802 __private_extern__
803 void
804 do_prefs_synchronize(int argc, char **argv)
805 {
806 #pragma unused(argc)
807 #pragma unused(argv)
808 SCPreferencesSynchronize(prefs);
809 if (ni_prefs != NULL) {
810 SCPreferencesSynchronize(ni_prefs);
811 }
812
813 return;
814 }
815
816
817 static CFComparisonResult
818 sort_paths(const void *p1, const void *p2, void *context)
819 {
820 #pragma unused(context)
821 CFStringRef path1 = (CFStringRef)p1;
822 CFStringRef path2 = (CFStringRef)p2;
823 return CFStringCompare(path1, path2, 0);
824 }
825
826
827 __private_extern__
828 void
829 do_prefs_list(int argc, char **argv)
830 {
831 int i;
832 CFIndex n;
833 CFMutableArrayRef paths = NULL;
834 CFStringRef prefix;
835 CFDictionaryRef entity;
836
837 prefix = CFStringCreateWithCString(NULL,
838 (argc >= 1) ? argv[0] : "/",
839 kCFStringEncodingUTF8);
840
841 entity = SCPreferencesPathGetValue(prefs, prefix);
842 if (entity == NULL) {
843 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
844 goto done;
845 }
846
847 paths = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
848
849 n = isA_CFDictionary(entity) ? CFDictionaryGetCount(entity) : 0;
850 if (n > 0) {
851 CFIndex i;
852 const void ** keys;
853 const void ** vals;
854
855 keys = CFAllocatorAllocate(NULL, n * sizeof(CFStringRef), 0);
856 vals = CFAllocatorAllocate(NULL, n * sizeof(CFPropertyListRef), 0);
857 CFDictionaryGetKeysAndValues(entity, keys, vals);
858 for (i = 0; i < n; i++) {
859 if (isA_CFDictionary(vals[i])) {
860 CFArrayAppendValue(paths, keys[i]);
861 }
862 }
863 CFAllocatorDeallocate(NULL, keys);
864 CFAllocatorDeallocate(NULL, vals);
865 }
866
867 n = CFArrayGetCount(paths);
868 CFArraySortValues(paths,
869 CFRangeMake(0, n),
870 sort_paths,
871 NULL);
872
873 if (n > 0) {
874 for (i = 0; i < n; i++) {
875 SCPrint(TRUE,
876 stdout,
877 CFSTR(" path [%d] = %@/%@\n"),
878 i,
879 CFEqual(prefix, CFSTR("/")) ? CFSTR("") : prefix,
880 CFArrayGetValueAtIndex(paths, i));
881 }
882 } else {
883 SCPrint(TRUE, stdout, CFSTR(" no paths.\n"));
884 }
885
886 CFRelease(paths);
887
888 done :
889
890 CFRelease(prefix);
891 return;
892 }
893
894
895 __private_extern__
896 void
897 do_prefs_get(int argc, char **argv)
898 {
899 #pragma unused(argc)
900 CFDictionaryRef dict;
901 CFStringRef link;
902 CFIndex n;
903 CFMutableDictionaryRef newDict;
904 CFStringRef path;
905
906 path = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
907
908 link = SCPreferencesPathGetLink(prefs, path);
909 if (link != NULL) {
910 SCPrint(TRUE, stdout, CFSTR(" --> %@\n"), link);
911 }
912
913 dict = SCPreferencesPathGetValue(prefs, path);
914 CFRelease(path);
915 if (dict == NULL) {
916 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
917 return;
918 }
919
920 newDict = CFDictionaryCreateMutable(NULL,
921 0,
922 &kCFTypeDictionaryKeyCallBacks,
923 &kCFTypeDictionaryValueCallBacks);
924
925 // remove [path] children
926 n = isA_CFDictionary(dict) ? CFDictionaryGetCount(dict) : 0;
927 if (n > 0) {
928 CFIndex i;
929 const void ** keys;
930 const void ** vals;
931
932 keys = CFAllocatorAllocate(NULL, n * sizeof(CFStringRef), 0);
933 vals = CFAllocatorAllocate(NULL, n * sizeof(CFPropertyListRef), 0);
934 CFDictionaryGetKeysAndValues(dict, keys, vals);
935 for (i = 0; i < n; i++) {
936 if (!isA_CFDictionary(vals[i])) {
937 CFDictionaryAddValue(newDict, keys[i], vals[i]);
938 }
939 }
940 CFAllocatorDeallocate(NULL, keys);
941 CFAllocatorDeallocate(NULL, vals);
942 }
943
944 if (value != NULL) {
945 CFRelease(value); /* we have new information, release the old */
946 }
947
948 value = newDict;
949
950 return;
951 }
952
953
954 __private_extern__
955 void
956 do_prefs_set(int argc, char **argv)
957 {
958 CFDictionaryRef dict;
959 CFMutableDictionaryRef newDict = NULL;
960 CFStringRef path;
961
962 path = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
963 newDict = CFDictionaryCreateMutableCopy(NULL, 0, value);
964
965 dict = SCPreferencesPathGetValue(prefs, path);
966 if (dict != NULL) {
967 CFIndex n;
968
969 // retain [path] children
970 n = CFDictionaryGetCount(dict);
971 if (n > 0) {
972 CFIndex i;
973 const void ** keys;
974 const void ** vals;
975
976 keys = CFAllocatorAllocate(NULL, n * sizeof(CFStringRef), 0);
977 vals = CFAllocatorAllocate(NULL, n * sizeof(CFPropertyListRef), 0);
978 CFDictionaryGetKeysAndValues(dict, keys, vals);
979 for (i = 0; i < n; i++) {
980 if (isA_CFDictionary(vals[i])) {
981 if (CFDictionaryContainsKey(newDict, keys[i])) {
982 SCPrint(TRUE, stdout, CFSTR(" key %@ is already a path component and cannot be replaced\n"), keys[i]);
983 goto done;
984 }
985 CFDictionaryAddValue(newDict, keys[i], vals[i]);
986 }
987 }
988 CFAllocatorDeallocate(NULL, keys);
989 CFAllocatorDeallocate(NULL, vals);
990 }
991 } else if (SCError() == kSCStatusInvalidArgument) {
992 SCPrint(TRUE, stdout, CFSTR(" a path component is not a dictionary\n"));
993 goto done;
994 } else if (SCError() != kSCStatusNoKey) {
995 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
996 goto done;
997 }
998
999 if (argc > 1) {
1000 CFStringRef link;
1001 Boolean ok;
1002
1003 // set link
1004 link = CFStringCreateWithCString(NULL, argv[1], kCFStringEncodingUTF8);
1005 ok = SCPreferencesPathSetLink(prefs, path, link);
1006 CFRelease(link);
1007 if (!ok) {
1008 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
1009 goto done;
1010 }
1011 } else {
1012 // set value
1013 if (!SCPreferencesPathSetValue(prefs, path, newDict)) {
1014 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
1015 goto done;
1016 }
1017 }
1018
1019 _prefs_changed = TRUE;
1020
1021 done :
1022
1023 CFRelease(newDict);
1024 CFRelease(path);
1025 return;
1026 }
1027
1028
1029 __private_extern__
1030 void
1031 do_prefs_remove(int argc, char **argv)
1032 {
1033 #pragma unused(argc)
1034 CFStringRef path;
1035
1036 path = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
1037
1038 if (!SCPreferencesPathRemoveValue(prefs, path)) {
1039 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
1040 goto done;
1041 }
1042
1043 _prefs_changed = TRUE;
1044
1045 done :
1046
1047 CFRelease(path);
1048 return;
1049 }
1050
1051 static const char *
1052 on_off_str(Boolean on)
1053 {
1054 return (on ? "on" : "off");
1055 }
1056
1057 /* -------------------- */
1058
1059 #if !TARGET_OS_IPHONE
1060
1061 #include "InterfaceNamerControlPrefs.h"
1062
1063 static void
1064 allow_new_interfaces_usage(void)
1065 {
1066 fprintf(stderr, "usage: scutil --allow-new-interfaces [on|off|default]\n");
1067 return;
1068 }
1069
1070 __private_extern__
1071 void
1072 do_ifnamer(char * pref, int argc, char **argv)
1073 {
1074 Boolean allow = FALSE;
1075
1076 if (argc > 1) {
1077 allow_new_interfaces_usage();
1078 exit(1);
1079 }
1080
1081 if (strcmp(pref, "allow-new-interfaces")) {
1082 exit(0);
1083 }
1084
1085 if (argc == 0) {
1086 SCPrint(TRUE, stdout, CFSTR("AllowNewInterfaces is %s\n"),
1087 on_off_str(InterfaceNamerControlPrefsAllowNewInterfaces()));
1088 exit(0);
1089 }
1090
1091 if ((strcasecmp(argv[0], "disable") == 0) ||
1092 (strcasecmp(argv[0], "no" ) == 0) ||
1093 (strcasecmp(argv[0], "off" ) == 0) ||
1094 (strcasecmp(argv[0], "0" ) == 0)) {
1095 allow = FALSE;
1096 } else if ((strcasecmp(argv[0], "enable") == 0) ||
1097 (strcasecmp(argv[0], "yes" ) == 0) ||
1098 (strcasecmp(argv[0], "on" ) == 0) ||
1099 (strcasecmp(argv[0], "1" ) == 0)) {
1100 allow = TRUE;
1101 } else if (strcasecmp(argv[0], "default") == 0) {
1102 allow = FALSE;
1103 } else {
1104 allow_new_interfaces_usage();
1105 exit(1);
1106 }
1107
1108 if (!InterfaceNamerControlPrefsSetAllowNewInterfaces(allow)) {
1109 SCPrint(TRUE, stderr, CFSTR("failed to set preferences\n"));
1110 exit(2);
1111 }
1112
1113 exit(0);
1114 return;
1115 }
1116
1117 #endif // !TARGET_OS_IPHONE
1118
1119 /* -------------------- */
1120
1121 #include "IPMonitorControlPrefs.h"
1122
1123 __private_extern__
1124 void
1125 do_log(char * log, int argc, char **argv)
1126 {
1127 Boolean verbose = FALSE;
1128
1129 if (strcmp(log, "IPMonitor")) {
1130 exit(0);
1131 }
1132
1133 if (argc == 0) {
1134 SCPrint(TRUE, stdout, CFSTR("IPMonitor log is %s\n"),
1135 on_off_str(IPMonitorControlPrefsIsVerbose()));
1136 exit(0);
1137 }
1138
1139 if ((strcasecmp(argv[0], "disable") == 0) ||
1140 (strcasecmp(argv[0], "no" ) == 0) ||
1141 (strcasecmp(argv[0], "off" ) == 0) ||
1142 (strcasecmp(argv[0], "0" ) == 0)) {
1143 verbose = FALSE;
1144 } else if ((strcasecmp(argv[0], "enable") == 0) ||
1145 (strcasecmp(argv[0], "yes" ) == 0) ||
1146 (strcasecmp(argv[0], "on" ) == 0) ||
1147 (strcasecmp(argv[0], "1" ) == 0)) {
1148 verbose = TRUE;
1149 } else {
1150 SCPrint(TRUE, stdout, CFSTR("invalid value, must be 'on' or 'off'\n"));
1151 exit(1);
1152 }
1153
1154 if (!IPMonitorControlPrefsSetVerbose(verbose)) {
1155 SCPrint(TRUE, stderr, CFSTR("failed to set preferences\n"));
1156 exit(2);
1157 }
1158
1159 exit(0);
1160 return;
1161 }
1162
1163
1164 /* -------------------- */
1165
1166 static SCNetworkInterfaceRef
1167 copy_configured_interface(SCPreferencesRef prefs, CFStringRef if_name)
1168 {
1169 SCNetworkSetRef current_set = NULL;
1170 CFIndex count;
1171 CFIndex i;
1172 SCNetworkInterfaceRef ret_if = NULL;
1173 CFArrayRef services = NULL;
1174
1175 if (prefs == NULL) {
1176 goto done;
1177 }
1178 current_set = SCNetworkSetCopyCurrent(prefs);
1179 if (current_set == NULL) {
1180 goto done;
1181 }
1182 services = SCNetworkSetCopyServices(current_set);
1183 if (services == NULL) {
1184 goto done;
1185 }
1186
1187 count = CFArrayGetCount(services);
1188 for (i = 0; i < count; i++) {
1189 CFStringRef this_if_name;
1190 SCNetworkInterfaceRef this_if;
1191 SCNetworkServiceRef s;
1192
1193 s = (SCNetworkServiceRef)CFArrayGetValueAtIndex(services, i);
1194 if (!SCNetworkServiceGetEnabled(s)) {
1195 /* skip disabled services */
1196 continue;
1197 }
1198 this_if = SCNetworkServiceGetInterface(s);
1199 if (this_if == NULL) {
1200 continue;
1201 }
1202 this_if_name = SCNetworkInterfaceGetBSDName(this_if);
1203 if (this_if_name == NULL) {
1204 continue;
1205 }
1206 if (CFEqual(this_if_name, if_name)) {
1207 CFRetain(this_if);
1208 ret_if = this_if;
1209 break;
1210 }
1211 }
1212
1213 done:
1214 if (current_set != NULL) {
1215 CFRelease(current_set);
1216 }
1217 if (services != NULL) {
1218 CFRelease(services);
1219 }
1220 return (ret_if);
1221 }
1222
1223 static void
1224 disable_until_needed_usage(void)
1225 {
1226 fprintf(stderr, "usage: scutil --disable-until-needed <interfaceName> [on|off|default]\n");
1227 return;
1228 }
1229
1230 #include <SystemConfiguration/SCNetworkConfigurationPrivate.h>
1231
1232 __private_extern__
1233 void
1234 do_disable_until_needed(int argc, char **argv)
1235 {
1236 const char * if_name;
1237 CFStringRef if_name_cf;
1238 SCNetworkInterfaceRef net_if;
1239 Boolean on = FALSE;
1240 const char * on_off = "?";
1241 Boolean ok;
1242 Boolean set_default = FALSE;
1243 Boolean set_value = FALSE;
1244
1245 if (argc < 1 || argc > 2) {
1246 disable_until_needed_usage();
1247 exit(1);
1248 }
1249 if_name = argv[0];
1250 if (argc > 1) {
1251 on_off = argv[1];
1252 if (strcasecmp(on_off, "on") == 0) {
1253 on = TRUE;
1254 } else if (strcasecmp(on_off, "off") == 0) {
1255 on = FALSE;
1256 } else if ((strcmp(on_off, "") == 0) || (strcasecmp(on_off, "default") == 0)) {
1257 set_default = TRUE;
1258 on_off = "default";
1259 } else {
1260 disable_until_needed_usage();
1261 exit(1);
1262 }
1263 set_value = TRUE;
1264 }
1265 ok = _prefs_open(CFSTR("scutil --disable-until-needed"), NULL);
1266 if (!ok) {
1267 SCPrint(TRUE,
1268 stdout,
1269 CFSTR("Could not open prefs: %s\n"),
1270 SCErrorString(SCError()));
1271 exit(1);
1272 }
1273 if_name_cf = CFStringCreateWithCStringNoCopy(NULL,
1274 if_name,
1275 kCFStringEncodingASCII,
1276 kCFAllocatorNull);
1277 net_if = copy_configured_interface(prefs, if_name_cf);
1278 if (net_if == NULL) {
1279 fprintf(stderr, "%s is not configured\n", if_name);
1280 exit(1);
1281 }
1282 if (set_value) {
1283 if (!set_default) {
1284 ok = SCNetworkInterfaceSetDisableUntilNeeded(net_if, on);
1285 } else {
1286 ok = __SCNetworkInterfaceSetDisableUntilNeededValue(net_if, NULL);
1287 }
1288 if (!ok) {
1289 fprintf(stderr, "failed to turn disable-until-needed %s\n",
1290 on_off);
1291 exit(1);
1292 }
1293 _prefs_save();
1294 } else {
1295 on = SCNetworkInterfaceGetDisableUntilNeeded(net_if);
1296 printf("%s disable-until-needed is %s\n", if_name, on_off_str(on));
1297 }
1298 _prefs_close();
1299 exit(0);
1300 return;
1301 }