]> git.saurik.com Git - apple/configd.git/blob - scutil.tproj/net.c
configd-1109.101.1.tar.gz
[apple/configd.git] / scutil.tproj / net.c
1 /*
2 * Copyright (c) 2004-2007, 2009-2011, 2014, 2016, 2017, 2019, 2020 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 /*
25 * Modification History
26 *
27 * August 5, 2004 Allan Nathanson <ajn@apple.com>
28 * - initial revision
29 */
30
31
32 #include "scutil.h"
33 #include "commands.h"
34 #include "prefs.h"
35 #include "net.h"
36 #include "net_interface.h"
37 #include "net_protocol.h"
38 #include "net_service.h"
39 #include "net_set.h"
40
41 #include "SCNetworkConfigurationInternal.h"
42 #include "SCPreferencesInternal.h"
43
44 #include <unistd.h>
45
46
47 __private_extern__ CFMutableArrayRef new_interfaces = NULL;
48
49 __private_extern__ CFArrayRef interfaces = NULL;
50 __private_extern__ CFArrayRef services = NULL;
51 __private_extern__ CFArrayRef protocols = NULL;
52 __private_extern__ CFArrayRef sets = NULL;
53
54 __private_extern__ SCNetworkInterfaceRef net_interface = NULL;
55 __private_extern__ SCNetworkServiceRef net_service = NULL;
56 __private_extern__ SCNetworkProtocolRef net_protocol = NULL;
57 __private_extern__ SCNetworkSetRef net_set = NULL;
58
59 __private_extern__ CFNumberRef CFNumberRef_0 = NULL;
60 __private_extern__ CFNumberRef CFNumberRef_1 = NULL;
61
62
63 /* -------------------- */
64
65
66 __private_extern__
67 CF_RETURNS_RETAINED CFNumberRef
68 _copy_number(const char *arg)
69 {
70 int val;
71
72 if (sscanf(arg, "%d", &val) != 1) {
73 return NULL;
74 }
75
76 return CFNumberCreate(NULL, kCFNumberIntType, &val);
77 }
78
79
80 /* -------------------- */
81
82
83 __private_extern__
84 CFIndex
85 _find_option(const char *option, optionsRef options, const int nOptions)
86 {
87 CFIndex i;
88
89 for (i = 0; i < nOptions; i++) {
90 if (strcasecmp(option, options[i].option) == 0) {
91 return i;
92 }
93 }
94
95 return kCFNotFound;
96 }
97
98
99 __private_extern__
100 CFIndex
101 _find_selection(CFStringRef choice, selections choices[], unsigned int *flags)
102 {
103 CFIndex i;
104
105 i = 0;
106 while (choices[i].selection != NULL) {
107 if (CFStringCompare(choice,
108 choices[i].selection,
109 kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
110 if (flags != NULL) {
111 *flags = choices[i].flags;
112 }
113 return i;
114 }
115 i++;
116 }
117
118 return kCFNotFound;
119 }
120
121
122 __private_extern__
123 Boolean
124 _process_options(optionsRef options, int nOptions, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
125 {
126 while (argc > 0) {
127 CFIndex optionIndex = kCFNotFound;
128
129 optionIndex = _find_option(argv[0], options, nOptions);
130 if (optionIndex == kCFNotFound) {
131 SCPrint(TRUE, stdout, CFSTR("set what?\n"));
132 return FALSE;
133 }
134 argv++;
135 argc--;
136
137 switch (options[optionIndex].type) {
138 case isOther :
139 // all option processing is managed by the "handler"
140 break;
141 case isHelp :
142 SCPrint(TRUE, stdout, CFSTR("%s\n"), options[optionIndex].info);
143 return FALSE;
144 case isChooseOne : {
145 CFStringRef choice;
146 selections *choices = (selections *)options[optionIndex].info;
147 unsigned int flags;
148 CFIndex i;
149
150 if (argc < 1) {
151 SCPrint(TRUE, stdout,
152 CFSTR("%s not specified\n"),
153 options[optionIndex].description != NULL ? options[optionIndex].description : "selection");
154 return FALSE;
155 }
156
157 choice = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
158 i = _find_selection(choice, choices, &flags);
159 CFRelease(choice);
160
161 if (i != kCFNotFound) {
162 if (choices[i].flags & selectionNotAvailable) {
163 SCPrint(TRUE, stdout,
164 CFSTR("cannot select %s\n"),
165 options[optionIndex].description != NULL ? options[optionIndex].description : "selection");
166 return FALSE;
167 }
168
169 if (choices[i].key != NULL) {
170 CFDictionarySetValue(newConfiguration,
171 *(options[optionIndex].key),
172 *(choices[i].key));
173 } else {
174 CFDictionaryRemoveValue(newConfiguration,
175 *(options[optionIndex].key));
176 }
177 } else {
178 SCPrint(TRUE, stdout,
179 CFSTR("invalid %s\n"),
180 options[optionIndex].description != NULL ? options[optionIndex].description : "selection");
181 return FALSE;
182 }
183
184 argv++;
185 argc--;
186 break;
187 }
188 case isChooseMultiple :
189 if (argc < 1) {
190 SCPrint(TRUE, stdout,
191 CFSTR("%s(s) not specified\n"),
192 options[optionIndex].description != NULL ? options[optionIndex].description : "selection");
193 return FALSE;
194 }
195
196 if (strlen(argv[0]) > 0) {
197 CFIndex i;
198 CFIndex n;
199 CFMutableArrayRef chosen;
200 CFStringRef str;
201 CFArrayRef str_array;
202
203 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
204 str_array = CFStringCreateArrayBySeparatingStrings(NULL, str, CFSTR(","));
205 CFRelease(str);
206
207 chosen = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
208
209 n = CFArrayGetCount(str_array);
210 for (i = 0; i < n; i++) {
211 CFStringRef choice;
212 selections *choices = (selections *)options[optionIndex].info;
213 unsigned int flags;
214 CFIndex j;
215
216 choice = CFArrayGetValueAtIndex(str_array, i);
217 j = _find_selection(choice, choices, &flags);
218
219 if (j != kCFNotFound) {
220 if (choices[j].flags & selectionNotAvailable) {
221 SCPrint(TRUE, stdout,
222 CFSTR("cannot select %s\n"),
223 options[optionIndex].description != NULL ? options[optionIndex].description : "selection");
224 CFArrayRemoveAllValues(chosen);
225 break;
226 }
227
228 CFArrayAppendValue(chosen, *(choices[j].key));
229 } else {
230 SCPrint(TRUE, stdout,
231 CFSTR("invalid %s\n"),
232 options[optionIndex].description != NULL ? options[optionIndex].description : "selection");
233 CFArrayRemoveAllValues(chosen);
234 break;
235 }
236 }
237 CFRelease(str_array);
238
239 if (CFArrayGetCount(chosen) > 0) {
240 CFDictionarySetValue(newConfiguration, *(options[optionIndex].key), chosen);
241 } else {
242 CFDictionaryRemoveValue(newConfiguration, *(options[optionIndex].key));
243 }
244 CFRelease(chosen);
245 } else {
246 CFDictionaryRemoveValue(newConfiguration, *(options[optionIndex].key));
247 }
248
249 argv++;
250 argc--;
251 break;
252 case isBool :
253 if (argc < 1) {
254 SCPrint(TRUE, stdout,
255 CFSTR("%s not specified\n"),
256 options[optionIndex].description != NULL ? options[optionIndex].description : "enable/disable");
257 return FALSE;
258 }
259
260 if ((strcasecmp(argv[0], "disable") == 0) ||
261 (strcasecmp(argv[0], "no" ) == 0) ||
262 (strcasecmp(argv[0], "off" ) == 0) ||
263 (strcasecmp(argv[0], "0" ) == 0)) {
264 CFDictionarySetValue(newConfiguration, *(options[optionIndex].key), kCFBooleanFalse);
265 } else if ((strcasecmp(argv[0], "enable") == 0) ||
266 (strcasecmp(argv[0], "yes" ) == 0) ||
267 (strcasecmp(argv[0], "on" ) == 0) ||
268 (strcasecmp(argv[0], "1" ) == 0)) {
269 CFDictionarySetValue(newConfiguration, *(options[optionIndex].key), kCFBooleanTrue);
270 } else if (strcmp(argv[0], "") == 0) {
271 CFDictionaryRemoveValue(newConfiguration, *(options[optionIndex].key));
272 } else {
273 SCPrint(TRUE, stdout, CFSTR("invalid value\n"));
274 return FALSE;
275 }
276
277 argv++;
278 argc--;
279 break;
280 case isBoolean :
281 if (argc < 1) {
282 SCPrint(TRUE, stdout,
283 CFSTR("%s not specified\n"),
284 options[optionIndex].description != NULL ? options[optionIndex].description : "enable/disable");
285 return FALSE;
286 }
287
288 if ((strcasecmp(argv[0], "disable") == 0) ||
289 (strcasecmp(argv[0], "no" ) == 0) ||
290 (strcasecmp(argv[0], "off" ) == 0) ||
291 (strcasecmp(argv[0], "0" ) == 0)) {
292 CFDictionarySetValue(newConfiguration, *(options[optionIndex].key), CFNumberRef_0);
293 } else if ((strcasecmp(argv[0], "enable") == 0) ||
294 (strcasecmp(argv[0], "yes" ) == 0) ||
295 (strcasecmp(argv[0], "on" ) == 0) ||
296 (strcasecmp(argv[0], "1" ) == 0)) {
297 CFDictionarySetValue(newConfiguration, *(options[optionIndex].key), CFNumberRef_1);
298 } else if (strcmp(argv[0], "") == 0) {
299 CFDictionaryRemoveValue(newConfiguration, *(options[optionIndex].key));
300 } else {
301 SCPrint(TRUE, stdout, CFSTR("invalid value\n"));
302 return FALSE;
303 }
304
305 argv++;
306 argc--;
307 break;
308 case isNumber :
309 if (argc < 1) {
310 SCPrint(TRUE, stdout,
311 CFSTR("%s not specified\n"),
312 options[optionIndex].description != NULL ? options[optionIndex].description : "value");
313 return FALSE;
314 }
315
316 if (strlen(argv[0]) > 0) {
317 CFNumberRef num;
318
319 num = _copy_number(argv[0]);
320 if (num != NULL) {
321 CFDictionarySetValue(newConfiguration, *(options[optionIndex].key), num);
322 CFRelease(num);
323 } else {
324 SCPrint(TRUE, stdout, CFSTR("invalid value\n"));
325 return FALSE;
326 }
327 } else {
328 CFDictionaryRemoveValue(newConfiguration, *(options[optionIndex].key));
329 }
330
331 argv++;
332 argc--;
333 break;
334 case isString :
335 if (argc < 1) {
336 SCPrint(TRUE, stdout,
337 CFSTR("%s not specified\n"),
338 options[optionIndex].description != NULL ? options[optionIndex].description : "value");
339 return FALSE;
340 }
341
342 if (strlen(argv[0]) > 0) {
343 CFStringRef str;
344
345 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
346 CFDictionarySetValue(newConfiguration, *(options[optionIndex].key), str);
347 CFRelease(str);
348 } else {
349 CFDictionaryRemoveValue(newConfiguration, *(options[optionIndex].key));
350 }
351
352 argv++;
353 argc--;
354 break;
355 case isStringArray :
356 if (argc < 1) {
357 SCPrint(TRUE, stdout,
358 CFSTR("%s(s) not specified\n"),
359 options[optionIndex].description != NULL ? options[optionIndex].description : "value");
360 return FALSE;
361 }
362
363 if (strlen(argv[0]) > 0) {
364 CFStringRef str;
365 CFArrayRef str_array;
366
367 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
368 str_array = CFStringCreateArrayBySeparatingStrings(NULL, str, CFSTR(","));
369 CFRelease(str);
370
371 CFDictionarySetValue(newConfiguration, *(options[optionIndex].key), str_array);
372 CFRelease(str_array);
373 } else {
374 CFDictionaryRemoveValue(newConfiguration, *(options[optionIndex].key));
375 }
376
377 argv++;
378 argc--;
379 break;
380 }
381
382 if (options[optionIndex].handler != NULL) {
383 CFStringRef key;
384 int nArgs;
385
386 key = options[optionIndex].key != NULL ? *(options[optionIndex].key) : NULL;
387 nArgs = (*options[optionIndex].handler)(key,
388 options[optionIndex].description,
389 options[optionIndex].info,
390 argc,
391 argv,
392 newConfiguration);
393 if (nArgs < 0) {
394 return FALSE;
395 }
396
397 argv += nArgs;
398 argc -= nArgs;
399 }
400 }
401
402 return TRUE;
403 }
404
405
406 /* -------------------- */
407
408
409 #define N_QUICK 32
410
411 __private_extern__
412 void
413 _show_entity(CFDictionaryRef entity, CFStringRef prefix)
414 {
415 CFArrayRef array;
416 const void * keys_q[N_QUICK];
417 const void ** keys = keys_q;
418 CFIndex i;
419 CFIndex n;
420 CFMutableArrayRef sorted;
421
422 n = CFDictionaryGetCount(entity);
423 if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) {
424 keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0);
425 }
426 CFDictionaryGetKeysAndValues(entity, keys, NULL);
427
428 array = CFArrayCreate(NULL, keys, n, &kCFTypeArrayCallBacks);
429 sorted = CFArrayCreateMutableCopy(NULL, n, array);
430 if (n > 1) {
431 CFArraySortValues(sorted,
432 CFRangeMake(0, n),
433 (CFComparatorFunction)CFStringCompare,
434 NULL);
435 }
436
437 for (i = 0; i < n; i++) {
438 CFStringRef key;
439 CFTypeRef value;
440
441 key = CFArrayGetValueAtIndex(sorted, i);
442 value = CFDictionaryGetValue(entity, key);
443 if (isA_CFArray(value)) {
444 CFIndex i;
445 CFIndex n = CFArrayGetCount(value);
446
447 SCPrint(TRUE, stdout, CFSTR("%@ %@ = ("), prefix, key);
448 for (i = 0; i < n; i++) {
449 CFTypeRef val;
450
451 val = CFArrayGetValueAtIndex(value, i);
452 SCPrint(TRUE, stdout,
453 CFSTR("%s%@"),
454 (i > 0) ? ", " : "",
455 val);
456 }
457 SCPrint(TRUE, stdout, CFSTR(")\n"));
458 } else {
459 SCPrint(TRUE, stdout, CFSTR("%@ %@ = %@\n"), prefix, key, value);
460 }
461 }
462
463 CFRelease(sorted);
464 CFRelease(array);
465 if (keys != keys_q) {
466 CFAllocatorDeallocate(NULL, keys);
467 }
468
469 return;
470 }
471
472
473 /* -------------------- */
474
475
476 static void
477 _net_close()
478 {
479 if (net_interface != NULL) {
480 CFRelease(net_interface);
481 net_interface = NULL;
482 }
483
484 if (net_service != NULL) {
485 CFRelease(net_service);
486 net_service = NULL;
487 }
488
489 if (net_protocol != NULL) {
490 CFRelease(net_protocol);
491 net_protocol = NULL;
492 }
493
494 if (net_set != NULL) {
495 CFRelease(net_set);
496 net_set = NULL;
497 }
498
499 if (interfaces != NULL) {
500 CFRelease(interfaces);
501 interfaces = NULL;
502 }
503
504 if (services != NULL) {
505 CFRelease(services);
506 services = NULL;
507 }
508
509 if (protocols != NULL) {
510 CFRelease(protocols);
511 protocols = NULL;
512 }
513
514 if (sets != NULL) {
515 CFRelease(sets);
516 sets = NULL;
517 }
518
519 if (new_interfaces != NULL) {
520 CFRelease(new_interfaces);
521 new_interfaces = NULL;
522 }
523
524 return;
525 }
526
527
528 __private_extern__
529 void
530 do_net_init()
531 {
532 int one = 1;
533 int zero = 0;
534
535 CFNumberRef_0 = CFNumberCreate(NULL, kCFNumberIntType, &zero);
536 CFNumberRef_1 = CFNumberCreate(NULL, kCFNumberIntType, &one);
537
538 return;
539 }
540
541
542 __private_extern__
543 void
544 do_net_open(int argc, char **argv)
545 {
546 Boolean ok;
547
548 if (prefs != NULL) {
549 if (_prefs_commitRequired(argc, argv, "close")) {
550 return;
551 }
552
553 _net_close();
554 _prefs_close();
555 }
556
557 ok = _prefs_open(CFSTR("scutil --net"), (argc > 0) ? argv[0] : NULL);
558 if (!ok) {
559 SCPrint(TRUE,
560 stdout,
561 CFSTR("Could not open prefs: %s\n"),
562 SCErrorString(SCError()));
563 return;
564 }
565
566 net_set = SCNetworkSetCopyCurrent(prefs);
567 if (net_set != NULL) {
568 CFStringRef setName;
569
570 setName = SCNetworkSetGetName(net_set);
571 if (setName != NULL) {
572 SCPrint(TRUE, stdout, CFSTR("set \"%@\" selected\n"), setName);
573 } else {
574 SCPrint(TRUE, stdout,
575 CFSTR("set ID \"%@\" selected\n"),
576 SCNetworkSetGetSetID(net_set));
577 }
578 }
579
580 return;
581 }
582
583
584 __private_extern__
585 void
586 do_net_commit(int argc, char **argv)
587 {
588 #pragma unused(argc)
589 #pragma unused(argv)
590 if (!SCPreferencesCommitChanges(prefs)) {
591 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
592 return;
593 }
594
595 _prefs_changed = FALSE;
596 return;
597 }
598
599
600 __private_extern__
601 void
602 do_net_apply(int argc, char **argv)
603 {
604 #pragma unused(argc)
605 #pragma unused(argv)
606 if (!SCPreferencesApplyChanges(prefs)) {
607 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
608 }
609 return;
610 }
611
612
613 __private_extern__
614 void
615 do_net_close(int argc, char **argv)
616 {
617 if (_prefs_commitRequired(argc, argv, "close")) {
618 return;
619 }
620
621 _net_close();
622 _prefs_close();
623
624 return;
625 }
626
627
628 __private_extern__
629 void
630 do_net_quit(int argc, char **argv)
631 {
632 if (_prefs_commitRequired(argc, argv, "quit")) {
633 return;
634 }
635
636 _net_close();
637 _prefs_close();
638
639 termRequested = TRUE;
640 return;
641 }
642
643
644 /* -------------------- */
645
646
647 typedef void (*net_func) (int argc, char **argv);
648
649 static const struct {
650 char *key;
651 net_func create;
652 net_func disable;
653 net_func enable;
654 net_func select;
655 net_func set;
656 net_func show;
657 net_func remove;
658 } net_keys[] = {
659
660 { "interfaces", NULL , NULL , NULL ,
661 NULL , NULL , show_interfaces ,
662 NULL },
663
664 { "interface", create_interface, NULL , NULL ,
665 select_interface, set_interface , show_interface ,
666 NULL },
667
668 { "services", NULL , NULL , NULL ,
669 NULL , NULL , show_services ,
670 NULL },
671
672 { "service", create_service , disable_service , enable_service ,
673 select_service , set_service , show_service ,
674 remove_service },
675
676 { "protocols", NULL , NULL , NULL ,
677 NULL , NULL , show_protocols ,
678 NULL },
679
680 { "protocol", create_protocol , disable_protocol, enable_protocol ,
681 select_protocol , set_protocol , show_protocol ,
682 remove_protocol },
683
684 { "sets", NULL , NULL , NULL ,
685 NULL , NULL , show_sets ,
686 NULL },
687
688 { "set", create_set , NULL , NULL ,
689 select_set , set_set , show_set ,
690 remove_set }
691
692 };
693 #define N_NET_KEYS (sizeof(net_keys) / sizeof(net_keys[0]))
694
695
696 static int
697 findNetKey(char *key)
698 {
699 int i;
700
701 for (i = 0; i < (int)N_NET_KEYS; i++) {
702 if (strcmp(key, net_keys[i].key) == 0) {
703 return i;
704 }
705 }
706
707 return -1;
708 }
709
710
711 /* -------------------- */
712
713
714 __private_extern__
715 void
716 do_net_create(int argc, char **argv)
717 {
718 char *key;
719 int i;
720
721 key = argv[0];
722 argv++;
723 argc--;
724
725 i = findNetKey(key);
726 if (i < 0) {
727 SCPrint(TRUE, stderr, CFSTR("create what?\n"));
728 return;
729 }
730
731 if (net_keys[i].create == NULL) {
732 SCPrint(TRUE, stderr, CFSTR("create what?\n"));
733 return;
734 }
735
736 (*net_keys[i].create)(argc, argv);
737 return;
738 }
739
740
741 __private_extern__
742 void
743 do_net_disable(int argc, char **argv)
744 {
745 char *key;
746 int i;
747
748 key = argv[0];
749 argv++;
750 argc--;
751
752 i = findNetKey(key);
753 if (i < 0) {
754 SCPrint(TRUE, stderr, CFSTR("disable what?\n"));
755 return;
756 }
757
758 if (net_keys[i].disable == NULL) {
759 SCPrint(TRUE, stderr, CFSTR("disable what?\n"));
760 return;
761 }
762
763 (*net_keys[i].disable)(argc, argv);
764 return;
765 }
766
767
768 __private_extern__
769 void
770 do_net_enable(int argc, char **argv)
771 {
772 char *key;
773 int i;
774
775 key = argv[0];
776 argv++;
777 argc--;
778
779 i = findNetKey(key);
780 if (i < 0) {
781 SCPrint(TRUE, stderr, CFSTR("enable what?\n"));
782 return;
783 }
784
785 if (net_keys[i].enable == NULL) {
786 SCPrint(TRUE, stderr, CFSTR("enable what?\n"));
787 return;
788 }
789
790 (*net_keys[i].enable)(argc, argv);
791 return;
792 }
793
794
795 static void
796 do_net_migrate_perform(int argc, char **argv)
797 {
798 char * sourceConfiguration = NULL;
799 char * targetConfiguration = NULL;
800 char * currentConfiguration = NULL;
801 CFStringRef str = NULL;
802 CFURLRef sourceConfigurationURL = NULL;
803 CFURLRef targetConfigurationURL = NULL;
804 CFURLRef currentConfigurationURL = NULL;
805 CFArrayRef migrationFiles = NULL;
806
807 sourceConfiguration = argv[0];
808 targetConfiguration = argv[1];
809
810 if (argc == 3) {
811 currentConfiguration = argv[2];
812 }
813
814 SCPrint(_sc_debug, stdout,
815 CFSTR("sourceConfiguration: %s\n"
816 "targetConfiguration: %s\n"
817 "currentConfiguration: %s\n"),
818 sourceConfiguration,
819 targetConfiguration,
820 (currentConfiguration != NULL) ? currentConfiguration : "<current system>" );
821
822 str = CFStringCreateWithCString(NULL, sourceConfiguration, kCFStringEncodingUTF8);
823 sourceConfigurationURL = CFURLCreateWithFileSystemPath(NULL, str, kCFURLPOSIXPathStyle, TRUE);
824 CFRelease(str);
825
826 str = CFStringCreateWithCString(NULL, targetConfiguration, kCFStringEncodingUTF8);
827 targetConfigurationURL = CFURLCreateWithFileSystemPath(NULL, str, kCFURLPOSIXPathStyle, TRUE);
828 CFRelease(str);
829
830 if (currentConfiguration != NULL) {
831 str = CFStringCreateWithCString(NULL, currentConfiguration, kCFStringEncodingUTF8);
832 currentConfigurationURL = CFURLCreateWithFileSystemPath(NULL, str, kCFURLPOSIXPathStyle, TRUE);
833 CFRelease(str);
834 }
835
836 migrationFiles = _SCNetworkConfigurationPerformMigration(sourceConfigurationURL, currentConfigurationURL, targetConfigurationURL, NULL);
837
838 if (migrationFiles != NULL) {
839 SCPrint(TRUE, stdout, CFSTR("Migration complete\n"));
840 SCPrint(_sc_debug, stdout, CFSTR("updated files: %@\n"), migrationFiles);
841 } else {
842 SCPrint(TRUE, stdout, CFSTR("Migration failed\n"));
843 }
844
845 if (sourceConfigurationURL != NULL) {
846 CFRelease(sourceConfigurationURL);
847 }
848 if (targetConfigurationURL != NULL) {
849 CFRelease(targetConfigurationURL);
850 }
851 if (currentConfigurationURL != NULL) {
852 CFRelease(currentConfigurationURL);
853 }
854 if (migrationFiles != NULL) {
855 CFRelease(migrationFiles);
856 }
857 }
858
859
860 static void
861 do_net_migrate_validate(int argc, char **argv)
862 {
863 #pragma unused(argc)
864 char *configuration = NULL;
865 CFURLRef configurationURL = NULL;
866 char *expectedConfiguration = NULL;
867 CFURLRef expectedConfigurationURL = NULL;
868 Boolean isValid = FALSE;
869 CFStringRef str = NULL;
870
871 configuration = argv[0];
872 str = CFStringCreateWithCString(NULL, configuration, kCFStringEncodingUTF8);
873 configurationURL = CFURLCreateWithFileSystemPath(NULL, str, kCFURLPOSIXPathStyle, TRUE);
874 CFRelease(str);
875
876 expectedConfiguration = argv[1];
877 str = CFStringCreateWithCString(NULL, expectedConfiguration, kCFStringEncodingUTF8);
878 expectedConfigurationURL = CFURLCreateWithFileSystemPath(NULL, str, kCFURLPOSIXPathStyle, TRUE);
879 CFRelease(str);
880
881 isValid = _SCNetworkMigrationAreConfigurationsIdentical(configurationURL, expectedConfigurationURL);
882
883 SCPrint(TRUE, stdout, CFSTR("Configuration at location %s %s\n"), configuration, isValid ? "is valid" : "is NOT valid");
884
885 if (configurationURL != NULL) {
886 CFRelease(configurationURL);
887 }
888 if (expectedConfigurationURL != NULL) {
889 CFRelease(expectedConfigurationURL);
890 }
891 }
892
893
894 __private_extern__
895 void
896 do_net_migrate(int argc, char **argv)
897 {
898 char *key;
899
900 key = argv[0];
901 argv++;
902 argc--;
903
904 if (strcmp(key, "perform") == 0) {
905 do_net_migrate_perform(argc, argv);
906 } else if (strcmp(key, "validate") == 0) {
907 do_net_migrate_validate(argc, argv);
908 } else {
909 SCPrint(TRUE, stderr, CFSTR("migrate what?\n"));
910 return;
911 }
912
913 }
914
915
916 __private_extern__
917 void
918 do_net_remove(int argc, char **argv)
919 {
920 char *key;
921 int i;
922
923 key = argv[0];
924 argv++;
925 argc--;
926
927 i = findNetKey(key);
928 if (i < 0) {
929 SCPrint(TRUE, stderr, CFSTR("remove what?\n"));
930 return;
931 }
932
933 if (net_keys[i].remove == NULL) {
934 SCPrint(TRUE, stderr, CFSTR("remove what?\n"));
935 return;
936 }
937
938 (*net_keys[i].remove)(argc, argv);
939 return;
940 }
941
942
943 __private_extern__
944 void
945 do_net_select(int argc, char **argv)
946 {
947 char *key;
948 int i;
949
950 key = argv[0];
951 argv++;
952 argc--;
953
954 i = findNetKey(key);
955 if (i < 0) {
956 SCPrint(TRUE, stderr, CFSTR("select what?\n"));
957 return;
958 }
959
960 if (*net_keys[i].select == NULL) {
961 SCPrint(TRUE, stderr, CFSTR("select what?\n"));
962 return;
963 }
964
965 (*net_keys[i].select)(argc, argv);
966 return;
967 }
968
969
970 __private_extern__
971 void
972 do_net_set(int argc, char **argv)
973 {
974 char *key;
975 int i;
976
977 key = argv[0];
978 argv++;
979 argc--;
980
981 i = findNetKey(key);
982 if (i < 0) {
983 SCPrint(TRUE, stderr, CFSTR("set what?\n"));
984 return;
985 }
986
987 (*net_keys[i].set)(argc, argv);
988 return;
989 }
990
991
992 __private_extern__
993 void
994 do_net_show(int argc, char **argv)
995 {
996 char *key;
997 int i;
998
999 key = argv[0];
1000 argv++;
1001 argc--;
1002
1003 i = findNetKey(key);
1004 if (i < 0) {
1005 SCPrint(TRUE, stderr, CFSTR("show what?\n"));
1006 return;
1007 }
1008
1009 (*net_keys[i].show)(argc, argv);
1010 return;
1011 }
1012
1013
1014 __private_extern__
1015 void
1016 do_net_clean(int argc, char **argv)
1017 {
1018 #pragma unused(argc)
1019 #pragma unused(argv)
1020 Boolean updated;
1021
1022 if (prefs == NULL) {
1023 SCPrint(TRUE, stdout, CFSTR("network configuration not open\n"));
1024 return;
1025 }
1026
1027 if (ni_prefs == NULL) {
1028 ni_prefs = SCPreferencesCreateCompanion(prefs, INTERFACES_DEFAULT_CONFIG);
1029 if (ni_prefs == NULL) {
1030 SC_log(LOG_NOTICE, "SCPreferencesCreate( <NetworkInterfaces.plist> ) failed: %s", SCErrorString(SCError()));
1031 }
1032 }
1033
1034 updated = __SCNetworkConfigurationClean(prefs, ni_prefs);
1035
1036 if (updated) {
1037 SCPrint(TRUE, stdout,
1038 CFSTR("network configuration updated, use \"commit\" to save\n"));
1039 if ((prefsPath == NULL) || (strcmp(prefsPath, PREFS_DEFAULT_CONFIG_PLIST) == 0)) {
1040 SCPrint(TRUE, stdout,
1041 CFSTR( "\n"
1042 "NOTE: because you have modified the system's \"live\" network configuration,\n"
1043 " a <reboot> is also REQUIRED.\n"
1044 "\n"));
1045 }
1046 _prefs_changed = TRUE;
1047 } else {
1048 SCPrint(TRUE, stdout, CFSTR("network configuration not updated\n"));
1049 }
1050
1051 return;
1052 }
1053
1054
1055 __private_extern__
1056 void
1057 do_net_update(int argc, char **argv)
1058 {
1059 #pragma unused(argc)
1060 #pragma unused(argv)
1061 SCNetworkSetRef set;
1062 Boolean setCreated = FALSE;
1063 Boolean setUpdated = FALSE;
1064
1065 if (prefs == NULL) {
1066 SCPrint(TRUE, stdout, CFSTR("network configuration not open\n"));
1067 return;
1068 }
1069
1070 if (net_set != NULL) {
1071 set = CFRetain(net_set);
1072 } else {
1073 set = SCNetworkSetCopyCurrent(prefs);
1074 if (set == NULL) {
1075 // if no "current" set, create a new/default ("Automatic") set
1076 set = _SCNetworkSetCreateDefault(prefs);
1077 if (set == NULL) {
1078 SCPrint(TRUE, stdout,
1079 CFSTR("could not initialize \"Automatic\" set: %s\n"),
1080 SCErrorString(SCError()));
1081 return;
1082 }
1083
1084 if (net_set != NULL) CFRelease(net_set);
1085 net_set = set;
1086 CFRetain(set);
1087
1088 setCreated = TRUE;
1089
1090 if (sets != NULL) {
1091 CFRelease(sets);
1092 sets = NULL;
1093 }
1094 }
1095 }
1096
1097 setUpdated = SCNetworkSetEstablishDefaultConfiguration(set);
1098 if (setUpdated) {
1099 CFStringRef setName;
1100
1101 _prefs_changed = TRUE;
1102
1103 setName = SCNetworkSetGetName(set);
1104 if (setName != NULL) {
1105 SCPrint(TRUE, stdout,
1106 CFSTR("set \"%@\" (%@) %supdated\n"),
1107 setName,
1108 SCNetworkSetGetSetID(set),
1109 setCreated ? "created, selected, and " : "");
1110 } else {
1111 SCPrint(TRUE, stdout,
1112 CFSTR("set ID \"%@\" %supdated\n"),
1113 SCNetworkSetGetSetID(set),
1114 setCreated ? "created, selected, and " : "");
1115 }
1116 _prefs_changed = TRUE;
1117 }
1118
1119 CFRelease(set);
1120 return;
1121 }
1122
1123
1124 __private_extern__
1125 void
1126 do_net_upgrade(int argc, char **argv)
1127 {
1128 Boolean do_commit = FALSE;
1129 Boolean upgraded;
1130
1131 if (prefs == NULL) {
1132 SCPrint(TRUE, stdout, CFSTR("network configuration not open\n"));
1133 return;
1134 }
1135
1136 if (prefsPath != NULL) {
1137 const char *prefs_plist;
1138
1139 prefs_plist = strrchr(prefsPath, '/');
1140 if (prefs_plist != NULL) {
1141 prefs_plist++;
1142 } else {
1143 prefs_plist = prefsPath;
1144 }
1145
1146 if (strcmp(prefs_plist, PREFS_DEFAULT_CONFIG_PLIST) != 0) {
1147 SCPrint(TRUE, stdout, CFSTR("not updating a \"preferences.plist\" file\n"));
1148 return;
1149 }
1150 }
1151
1152 if (argc > 0) {
1153 if (strcmp(argv[0], PREFS_DEFAULT_CONFIG_PLIST) == 0) {
1154 upgraded = __SCNetworkConfigurationUpgrade(&prefs, NULL, do_commit);
1155 } else if (strcmp(argv[0], INTERFACES_DEFAULT_CONFIG_PLIST) == 0) {
1156 if (ni_prefs == NULL) {
1157 ni_prefs = SCPreferencesCreateCompanion(prefs, INTERFACES_DEFAULT_CONFIG);
1158 if (ni_prefs == NULL) {
1159 SC_log(LOG_NOTICE, "SCPreferencesCreate( <NetworkInterfaces.plist> ) failed: %s", SCErrorString(SCError()));
1160 }
1161 }
1162
1163 do_commit = TRUE; // using alternate, created on-the-fly preferences.plist
1164
1165 upgraded = __SCNetworkConfigurationUpgrade(NULL, &ni_prefs, do_commit);
1166 } else {
1167 SCPrint(TRUE, stdout, CFSTR("invalid .plist (\"preferences.plist\", \"NetworkInterfaces.plist\"\n"));
1168 return;
1169 }
1170 } else {
1171 upgraded = __SCNetworkConfigurationUpgrade(&prefs, &ni_prefs, do_commit);
1172 }
1173
1174 if (upgraded) {
1175 SCPrint(TRUE, stdout,
1176 do_commit ? CFSTR("network configuration upgraded/saved\n")
1177 : CFSTR("network configuration upgraded, use \"commit\" to save\n"));
1178 if ((prefsPath == NULL) || (strcmp(prefsPath, PREFS_DEFAULT_CONFIG_PLIST) == 0)) {
1179 SCPrint(TRUE, stdout,
1180 do_commit ? CFSTR("\n"
1181 "NOTE: because you have modified the system's \"live\" network configuration,\n"
1182 " a <reboot> is also REQUIRED.\n"
1183 "\n")
1184
1185 : CFSTR("\n"
1186 "NOTE: because you are modifying the system's \"live\" network configuration,\n"
1187 " a <reboot> will also be REQUIRED.\n"
1188 "\n")
1189 );
1190 }
1191
1192 if (!do_commit) {
1193 _prefs_changed = TRUE;
1194 }
1195 } else {
1196 SCPrint(TRUE, stdout, CFSTR("network configuration upgrade not needed\n"));
1197 }
1198
1199 return;
1200 }
1201
1202
1203 #include "SCPreferencesInternal.h"
1204 #include <fcntl.h>
1205 #include <unistd.h>
1206 __private_extern__
1207 void
1208 do_net_snapshot(int argc, char **argv)
1209 {
1210 #pragma unused(argc)
1211 #pragma unused(argv)
1212 if (prefs == NULL) {
1213 SCPrint(TRUE, stdout, CFSTR("network configuration not open\n"));
1214 return;
1215 }
1216
1217 if (prefs != NULL) {
1218 SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
1219
1220 if (prefsPrivate->prefs != NULL) {
1221 int fd;
1222 static int n_snapshot = 0;
1223 char *path;
1224 CFDataRef xmlData;
1225
1226 asprintf(&path, "/tmp/prefs_snapshot_%d", n_snapshot++);
1227 (void)unlink(path);
1228 fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644);
1229 free(path);
1230 if (fd == -1) {
1231 SCPrint(TRUE, stdout, CFSTR("could not write snapshot: open() failed : %s\n"), strerror(errno));
1232 return;
1233 }
1234
1235 xmlData = CFPropertyListCreateData(NULL, prefsPrivate->prefs, kCFPropertyListXMLFormat_v1_0, 0, NULL);
1236 if (xmlData != NULL) {
1237 (void) write(fd, CFDataGetBytePtr(xmlData), CFDataGetLength(xmlData));
1238 CFRelease(xmlData);
1239 } else {
1240 SCPrint(TRUE, stdout, CFSTR("could not write snapshot: CFPropertyListCreateData() failed\n"));
1241 }
1242
1243 (void) close(fd);
1244 } else {
1245 SCPrint(TRUE, stdout, CFSTR("prefs have not been accessed\n"));
1246 }
1247 }
1248
1249 return;
1250 }
1251
1252 __private_extern__
1253 void
1254 do_configuration(int argc, char **argv)
1255 {
1256 const char *description = NULL;
1257 SCPreferencesRef ni_prefs;
1258 CFStringRef path = NULL;
1259 SCPreferencesRef prefs;
1260 int _sc_log_save;
1261
1262 // scutil --configuration
1263 // scutil --configuration <path-to-preferences.plist>
1264 // scutil --configuraiton <description> <path-to-preferences.plist>
1265
1266 if (argc > 0) {
1267 if (argc > 1) {
1268 description = argv[0];
1269 }
1270 path = CFStringCreateWithCString(NULL,
1271 argc > 1 ? argv[1] : argv[0],
1272 kCFStringEncodingUTF8);
1273 }
1274 prefs = SCPreferencesCreate(NULL, CFSTR("scutil --configuration"), path);
1275 ni_prefs = SCPreferencesCreateCompanion(prefs, INTERFACES_DEFAULT_CONFIG);
1276
1277 _sc_log_save = _sc_log;
1278 _sc_log = kSCLogDestinationFile;
1279 __SCNetworkConfigurationReport(LOG_NOTICE, description, prefs, ni_prefs);
1280 _sc_log = _sc_log_save;
1281
1282 if (path != NULL) CFRelease(path);
1283 CFRelease(prefs);
1284 CFRelease(ni_prefs);
1285 exit(0);
1286 }