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