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