]> git.saurik.com Git - apple/configd.git/blame - scutil.tproj/prefs.c
configd-1109.101.1.tar.gz
[apple/configd.git] / scutil.tproj / prefs.c
CommitLineData
009ee3c6 1/*
78deefe8 2 * Copyright (c) 2003-2008, 2011-2017, 2019, 2020 Apple Inc. All rights reserved.
009ee3c6
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
942cecd7 5 *
009ee3c6
A
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.
942cecd7 12 *
009ee3c6
A
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.
942cecd7 20 *
009ee3c6
A
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
43bfd57e 31#include <TargetConditionals.h>
942cecd7 32#include <dlfcn.h>
edebe297
A
33#include <unistd.h>
34#include <sys/param.h>
35#include <sys/types.h>
36#include <sys/stat.h>
edebe297 37
009ee3c6 38#include "scutil.h"
edebe297 39#include "commands.h"
009ee3c6
A
40#include "prefs.h"
41
942cecd7
A
42#include "SCNetworkConfigurationInternal.h"
43
44#if !TARGET_OS_IPHONE
45#include <Security/Authorization.h>
46#endif /* !TARGET_OS_IPHONE */
47
edebe297
A
48
49/* -------------------- */
50
51
a40a14f8 52#if !TARGET_OS_IPHONE
edebe297
A
53static void *
54__loadSecurity(void) {
942cecd7
A
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;
edebe297 63}
009ee3c6
A
64
65
5e9ce69e 66static OSStatus
edebe297 67_AuthorizationCreate(const AuthorizationRights *rights, const AuthorizationEnvironment *environment, AuthorizationFlags flags, AuthorizationRef *authorization)
009ee3c6 68{
edebe297
A
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
5e9ce69e 80static OSStatus
edebe297
A
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
5e9ce69e
A
96__private_extern__
97AuthorizationRef
98_prefs_AuthorizationCreate()
edebe297
A
99{
100 AuthorizationRef authorization = NULL;
5e9ce69e
A
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"),
78403150 116 (int)status);
5e9ce69e
A
117 return NULL;
118 }
009ee3c6
A
119 }
120
edebe297 121 return authorization;
009ee3c6 122}
5e9ce69e
A
123
124
125__private_extern__
126void
127_prefs_AuthorizationFree(AuthorizationRef authorization)
128{
129 if (authorization != kSCPreferencesUseEntitlementAuthorization) {
130 AuthorizationFree(authorization, kAuthorizationFlagDefaults);
131// AuthorizationFree(authorization, kAuthorizationFlagDestroyRights);
132 }
133
134 return;
135}
136
a40a14f8 137#endif /* !TARGET_OS_IPHONE */
009ee3c6 138
edebe297
A
139/* -------------------- */
140
141
142__private_extern__ Boolean _prefs_changed = FALSE;
143
144
145__private_extern__
146Boolean
78deefe8 147_prefs_open(CFStringRef name, const char *path)
edebe297 148{
1ef45fa4 149 char *env = NULL;
6bb65964 150 CFMutableDictionaryRef options = NULL;
78deefe8 151 CFStringRef prefsID = NULL;
6bb65964
A
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
a40a14f8 161#if !TARGET_OS_IPHONE
5e9ce69e 162 authorization = _prefs_AuthorizationCreate();
17d3ee29 163#else
5e9ce69e 164 authorization = kSCPreferencesUseEntitlementAuthorization;
a40a14f8 165#endif /* !TARGET_OS_IPHONE */
6bb65964
A
166 }
167
168 if (getenv("SCPREFERENCES_REMOVE_WHEN_EMPTY") != NULL) {
6bb65964
A
169 if (options == NULL) {
170 options = CFDictionaryCreateMutable(NULL,
171 0,
172 &kCFTypeDictionaryKeyCallBacks,
173 &kCFTypeDictionaryValueCallBacks);
1ef45fa4 174 useOptions = TRUE;
6bb65964
A
175 }
176 CFDictionarySetValue(options, kSCPreferencesOptionRemoveWhenEmpty, kCFBooleanTrue);
177 }
178
1ef45fa4
A
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 }
1ef45fa4 194
78deefe8
A
195 if (path != NULL) {
196 prefsPath = strdup(path);
197 prefsID = CFStringCreateWithCString(NULL, path, kCFStringEncodingUTF8);
198 }
199
6bb65964
A
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
edebe297 205 prefs = SCPreferencesCreateWithAuthorization(NULL, name, prefsID, authorization);
6bb65964
A
206 } else {
207 prefs = SCPreferencesCreateWithOptions(NULL, name, prefsID, authorization, options);
208 CFRelease(options);
edebe297
A
209 }
210
78deefe8 211 if (prefsID != NULL) CFRelease(prefsID);
edebe297 212 if (prefs == NULL) {
78deefe8
A
213 if (prefsPath != NULL) free(prefsPath);
214 prefsPath = NULL;
edebe297
A
215 return FALSE;
216 }
217
218 _prefs_changed = FALSE;
219 return TRUE;
220}
221
222
223__private_extern__
224void
225_prefs_save()
009ee3c6
A
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
78deefe8
A
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
009ee3c6
A
277 return;
278}
279
280
edebe297
A
281__private_extern__
282void
283_prefs_close()
284{
78deefe8
A
285 if (prefsPath != NULL) {
286 free(prefsPath);
287 prefsPath = NULL;
288 }
289
edebe297
A
290 if (prefs != NULL) {
291 CFRelease(prefs);
292 prefs = NULL;
293 _prefs_changed = FALSE;
294 }
295
78deefe8
A
296 if (ni_prefs != NULL) {
297 CFRelease(ni_prefs);
298 ni_prefs = NULL;
299 }
300
edebe297 301 if (authorization != NULL) {
a40a14f8 302#if !TARGET_OS_IPHONE
5e9ce69e 303 _prefs_AuthorizationFree(authorization);
a40a14f8
A
304#else /* !TARGET_OS_IPHONE */
305 // Uh...if authorization isn't NULL, something went horribly wrong.
306#endif /* !TARGET_OS_IPHONE */
edebe297
A
307 authorization = NULL;
308 }
309
310 return;
311}
312
313
314__private_extern__
315Boolean
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
009ee3c6
A
345static void
346get_ComputerName(int argc, char **argv)
347{
1ef45fa4
A
348#pragma unused(argc)
349#pragma unused(argv)
009ee3c6
A
350 CFStringEncoding encoding;
351 CFStringRef hostname;
009ee3c6
A
352
353 hostname = SCDynamicStoreCopyComputerName(NULL, &encoding);
edebe297 354 if (hostname == NULL) {
009ee3c6
A
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
edebe297 373 SCPrint(TRUE, stdout, CFSTR("%@\n"), hostname);
009ee3c6 374 CFRelease(hostname);
edebe297 375
009ee3c6
A
376 exit(0);
377}
378
379
380static void
381set_ComputerName(int argc, char **argv)
382{
78403150
A
383 CFStringRef hostname = NULL;
384 Boolean ok;
edebe297
A
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 }
009ee3c6
A
394
395 if (argc == 0) {
5e9ce69e
A
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);
78403150 402 } else if (strlen(argv[0]) > 0) {
a40a14f8 403 hostname = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
009ee3c6
A
404 }
405
a40a14f8 406 ok = SCPreferencesSetComputerName(prefs, hostname, kCFStringEncodingUTF8);
edebe297
A
407 if (hostname != NULL) CFRelease(hostname);
408 if (!ok) {
009ee3c6
A
409 SCPrint(TRUE,
410 stdout,
edebe297 411 CFSTR("Could not open prefs: %s\n"),
009ee3c6 412 SCErrorString(SCError()));
edebe297 413 _prefs_close();
009ee3c6
A
414 exit (1);
415 }
edebe297
A
416
417 _prefs_save();
418 _prefs_close();
009ee3c6
A
419 exit(0);
420}
421
422
dbf6a266
A
423static void
424get_HostName(int argc, char **argv)
425{
1ef45fa4
A
426#pragma unused(argc)
427#pragma unused(argv)
dbf6a266 428 CFStringRef hostname;
edebe297
A
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 }
dbf6a266 439
dbf6a266
A
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 }
edebe297 457 _prefs_close();
dbf6a266
A
458 exit (1);
459 }
460
461 SCPrint(TRUE, stdout, CFSTR("%@\n"), hostname);
edebe297 462 _prefs_close();
dbf6a266
A
463 exit(0);
464}
465
466
467static void
468set_HostName(int argc, char **argv)
469{
edebe297
A
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 }
dbf6a266
A
481
482 if (argc == 0) {
5e9ce69e 483 hostname = _copyStringFromSTDIN(CFSTR("HostName"), SCPreferencesGetHostName(prefs));
78403150 484 } else if (strlen(argv[0]) > 0) {
a40a14f8 485 hostname = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
dbf6a266
A
486 }
487
edebe297
A
488 ok = SCPreferencesSetHostName(prefs, hostname);
489 if (hostname != NULL) CFRelease(hostname);
490 if (!ok) {
dbf6a266
A
491 SCPrint(TRUE,
492 stderr,
493 CFSTR("SCPreferencesSetHostName() failed: %s\n"),
494 SCErrorString(SCError()));
edebe297 495 _prefs_close();
dbf6a266
A
496 exit (1);
497 }
edebe297
A
498
499 _prefs_save();
500 _prefs_close();
dbf6a266
A
501 exit(0);
502}
503
504
009ee3c6
A
505static void
506get_LocalHostName(int argc, char **argv)
507{
1ef45fa4
A
508#pragma unused(argc)
509#pragma unused(argv)
009ee3c6
A
510 CFStringRef hostname;
511
512 hostname = SCDynamicStoreCopyLocalHostName(NULL);
edebe297 513 if (hostname == NULL) {
009ee3c6
A
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);
be997540 534
009ee3c6
A
535 exit(0);
536}
537
538
539static void
540set_LocalHostName(int argc, char **argv)
541{
78403150 542 CFStringRef hostname = NULL;
edebe297
A
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 }
009ee3c6
A
553
554 if (argc == 0) {
5e9ce69e
A
555 CFStringRef old_hostname;
556
557 old_hostname = SCDynamicStoreCopyLocalHostName(NULL);
558 hostname = _copyStringFromSTDIN(CFSTR("LocalHostName"), old_hostname);
559 if (old_hostname) CFRelease(old_hostname);
78403150 560 } else if (strlen(argv[0]) > 0) {
a40a14f8 561 hostname = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
009ee3c6
A
562 }
563
edebe297
A
564 ok = SCPreferencesSetLocalHostName(prefs, hostname);
565 if (hostname != NULL) CFRelease(hostname);
566 if (!ok) {
009ee3c6
A
567 SCPrint(TRUE,
568 stderr,
569 CFSTR("SCPreferencesSetLocalHostName() failed: %s\n"),
570 SCErrorString(SCError()));
edebe297 571 _prefs_close();
009ee3c6
A
572 exit (1);
573 }
edebe297
A
574
575 _prefs_save();
576 _prefs_close();
009ee3c6
A
577 exit(0);
578}
579
580
edebe297
A
581/* -------------------- */
582
583
009ee3c6
A
584typedef void (*pref_func) (int argc, char **argv);
585
dbf6a266 586static const struct {
009ee3c6
A
587 char *pref;
588 pref_func get;
589 pref_func set;
dbf6a266 590} pref_keys[] = {
009ee3c6 591 { "ComputerName", get_ComputerName, set_ComputerName },
dbf6a266 592 { "HostName", get_HostName, set_HostName },
009ee3c6
A
593 { "LocalHostName", get_LocalHostName, set_LocalHostName }
594};
dbf6a266 595#define N_PREF_KEYS (sizeof(pref_keys) / sizeof(pref_keys[0]))
009ee3c6
A
596
597
dbf6a266 598__private_extern__
009ee3c6
A
599int
600findPref(char *pref)
601{
602 int i;
603
dbf6a266
A
604 for (i = 0; i < (int)N_PREF_KEYS; i++) {
605 if (strcmp(pref, pref_keys[i].pref) == 0) {
009ee3c6
A
606 return i;
607 }
608 }
609
610 return -1;
611}
612
613
dbf6a266 614__private_extern__
009ee3c6
A
615void
616do_getPref(char *pref, int argc, char **argv)
617{
618 int i;
619
5e9ce69e
A
620 if (argc == 0) {
621 i = findPref(pref);
622 if (i >= 0) {
623 (*pref_keys[i].get)(argc, argv);
624 }
625 return;
009ee3c6 626 }
5e9ce69e 627
942cecd7 628 // process extended get
5e9ce69e
A
629 // ie. scutil --get <filename> <prefs path> <key>
630 do_prefs_init();
942cecd7 631
5e9ce69e 632 do_prefs_open(argc, argv);
942cecd7
A
633 if (SCError() != kSCStatusOK) {
634 SCPrint(TRUE, stderr, CFSTR("%s\n"), SCErrorString(SCError()));
635 _prefs_close();
636 exit(1);
637 }
5e9ce69e 638
942cecd7 639 do_prefs_get(--argc, ++argv);
5e9ce69e
A
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);
5e9ce69e 650 _prefs_close();
78403150 651 exit(0);
5e9ce69e
A
652 }
653 }
78403150
A
654
655 // if path or key not found
5e9ce69e 656 _prefs_close();
78403150 657 exit(1);
009ee3c6
A
658}
659
660
dbf6a266 661__private_extern__
009ee3c6
A
662void
663do_setPref(char *pref, int argc, char **argv)
664{
665 int i;
666
667 i = findPref(pref);
668 if (i >= 0) {
dbf6a266 669 (*pref_keys[i].set)(argc, argv);
009ee3c6
A
670 }
671 return;
672}
edebe297
A
673
674
675/* -------------------- */
676
677
678__private_extern__
679void
680do_prefs_init()
681{
682 return;
683}
684
685
686__private_extern__
687void
688do_prefs_open(int argc, char **argv)
689{
690 Boolean ok;
edebe297
A
691
692 if (prefs != NULL) {
693 if (_prefs_commitRequired(argc, argv, "close")) {
694 return;
695 }
696
697 do_prefs_close(0, NULL);
698 }
699
78deefe8 700 ok = _prefs_open(CFSTR("scutil --prefs"), (argc > 0) ? argv[0] : NULL);
edebe297
A
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__
714void
715do_prefs_lock(int argc, char **argv)
716{
1ef45fa4 717#pragma unused(argv)
edebe297
A
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__
730void
731do_prefs_unlock(int argc, char **argv)
732{
1ef45fa4
A
733#pragma unused(argc)
734#pragma unused(argv)
edebe297
A
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__
745void
746do_prefs_commit(int argc, char **argv)
747{
1ef45fa4
A
748#pragma unused(argc)
749#pragma unused(argv)
edebe297
A
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__
761void
762do_prefs_apply(int argc, char **argv)
763{
1ef45fa4
A
764#pragma unused(argc)
765#pragma unused(argv)
edebe297
A
766 if (!SCPreferencesApplyChanges(prefs)) {
767 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
768 }
769
770 return;
771}
772
773
774__private_extern__
775void
776do_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__
788void
789do_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
6d034b4e
A
802__private_extern__
803void
804do_prefs_synchronize(int argc, char **argv)
805{
1ef45fa4
A
806#pragma unused(argc)
807#pragma unused(argv)
6d034b4e 808 SCPreferencesSynchronize(prefs);
78deefe8
A
809 if (ni_prefs != NULL) {
810 SCPreferencesSynchronize(ni_prefs);
811 }
812
6d034b4e
A
813 return;
814}
815
816
edebe297 817static CFComparisonResult
1ef45fa4
A
818sort_paths(const void *p1, const void *p2, void *context)
819{
820#pragma unused(context)
edebe297
A
821 CFStringRef path1 = (CFStringRef)p1;
822 CFStringRef path2 = (CFStringRef)p2;
823 return CFStringCompare(path1, path2, 0);
824}
825
826
827__private_extern__
828void
829do_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__
896void
897do_prefs_get(int argc, char **argv)
898{
1ef45fa4 899#pragma unused(argc)
edebe297
A
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__
955void
956do_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__
1030void
1031do_prefs_remove(int argc, char **argv)
1032{
1ef45fa4 1033#pragma unused(argc)
edebe297
A
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}
5e9ce69e 1050
9de8ab86
A
1051static const char *
1052on_off_str(Boolean on)
1053{
1054 return (on ? "on" : "off");
1055}
1056
5e9ce69e
A
1057/* -------------------- */
1058
43bfd57e
A
1059#if !TARGET_OS_IPHONE
1060
1061#include "InterfaceNamerControlPrefs.h"
1062
1063static void
1064allow_new_interfaces_usage(void)
1065{
1066 fprintf(stderr, "usage: scutil --allow-new-interfaces [on|off|default]\n");
1067 return;
1068}
1069
1070__private_extern__
1071void
1072do_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
5e9ce69e
A
1121#include "IPMonitorControlPrefs.h"
1122
1123__private_extern__
1124void
1125do_log(char * log, int argc, char **argv)
1126{
942cecd7
A
1127 Boolean verbose = FALSE;
1128
5e9ce69e 1129 if (strcmp(log, "IPMonitor")) {
942cecd7 1130 exit(0);
5e9ce69e 1131 }
942cecd7 1132
5e9ce69e 1133 if (argc == 0) {
942cecd7
A
1134 SCPrint(TRUE, stdout, CFSTR("IPMonitor log is %s\n"),
1135 on_off_str(IPMonitorControlPrefsIsVerbose()));
1136 exit(0);
5e9ce69e 1137 }
5e9ce69e 1138
942cecd7
A
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)) {
5e9ce69e 1143 verbose = FALSE;
942cecd7
A
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);
5e9ce69e 1157 }
942cecd7 1158
5e9ce69e
A
1159 exit(0);
1160 return;
1161}
1162
1163
9de8ab86
A
1164/* -------------------- */
1165
1166static SCNetworkInterfaceRef
1167copy_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);
942cecd7 1194 if (!SCNetworkServiceGetEnabled(s)) {
9de8ab86
A
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
1223static void
1224disable_until_needed_usage(void)
1225{
942cecd7 1226 fprintf(stderr, "usage: scutil --disable-until-needed <interfaceName> [on|off|default]\n");
9de8ab86
A
1227 return;
1228}
1229
1230#include <SystemConfiguration/SCNetworkConfigurationPrivate.h>
1231
1232__private_extern__
1233void
1234do_disable_until_needed(int argc, char **argv)
1235{
1236 const char * if_name;
1237 CFStringRef if_name_cf;
1238 SCNetworkInterfaceRef net_if;
942cecd7
A
1239 Boolean on = FALSE;
1240 const char * on_off = "?";
9de8ab86 1241 Boolean ok;
942cecd7
A
1242 Boolean set_default = FALSE;
1243 Boolean set_value = FALSE;
9de8ab86
A
1244
1245 if (argc < 1 || argc > 2) {
1246 disable_until_needed_usage();
1247 exit(1);
1248 }
1249 if_name = argv[0];
942cecd7
A
1250 if (argc > 1) {
1251 on_off = argv[1];
9de8ab86
A
1252 if (strcasecmp(on_off, "on") == 0) {
1253 on = TRUE;
942cecd7 1254 } else if (strcasecmp(on_off, "off") == 0) {
9de8ab86 1255 on = FALSE;
942cecd7
A
1256 } else if ((strcmp(on_off, "") == 0) || (strcasecmp(on_off, "default") == 0)) {
1257 set_default = TRUE;
1258 on_off = "default";
1259 } else {
9de8ab86
A
1260 disable_until_needed_usage();
1261 exit(1);
1262 }
942cecd7 1263 set_value = TRUE;
9de8ab86
A
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) {
942cecd7
A
1283 if (!set_default) {
1284 ok = SCNetworkInterfaceSetDisableUntilNeeded(net_if, on);
1285 } else {
1286 ok = __SCNetworkInterfaceSetDisableUntilNeededValue(net_if, NULL);
1287 }
1288 if (!ok) {
9de8ab86 1289 fprintf(stderr, "failed to turn disable-until-needed %s\n",
942cecd7 1290 on_off);
9de8ab86
A
1291 exit(1);
1292 }
1293 _prefs_save();
942cecd7 1294 } else {
9de8ab86
A
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}