1/*
2 * Copyright (c) 2004-2007, 2009-2011 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 <unistd.h>
42
43
44__private_extern__ CFMutableArrayRef		new_interfaces	= NULL;
45
46__private_extern__ CFArrayRef			interfaces	= NULL;
47__private_extern__ CFArrayRef			services	= NULL;
48__private_extern__ CFArrayRef			protocols	= NULL;
49__private_extern__ CFArrayRef			sets		= NULL;
50
51__private_extern__ SCNetworkInterfaceRef	net_interface	= NULL;
52__private_extern__ SCNetworkServiceRef		net_service	= NULL;
53__private_extern__ SCNetworkProtocolRef		net_protocol	= NULL;
54__private_extern__ SCNetworkSetRef		net_set		= NULL;
55
56__private_extern__ CFNumberRef			CFNumberRef_0	= NULL;
57__private_extern__ CFNumberRef			CFNumberRef_1	= NULL;
58
59
60/* -------------------- */
61
62
63__private_extern__
64CF_RETURNS_RETAINED CFNumberRef
65_copy_number(const char *arg)
66{
67	int	val;
68
69	if (sscanf(arg, "%d", &val) != 1) {
70		return NULL;
71	}
72
73	return CFNumberCreate(NULL, kCFNumberIntType, &val);
74}
75
76
77/* -------------------- */
78
79
80__private_extern__
81CFIndex
82_find_option(const char *option, optionsRef options, const int nOptions)
83{
84	CFIndex	i;
85
86	for (i = 0; i < nOptions; i++) {
87		if (strcasecmp(option, options[i].option) == 0) {
88			return i;
89		}
90	}
91
92	return kCFNotFound;
93}
94
95
96__private_extern__
97CFIndex
98_find_selection(CFStringRef choice, selections choices[], unsigned int *flags)
99{
100	CFIndex	i;
101
102	i = 0;
103	while (choices[i].selection != NULL) {
104		if (CFStringCompare(choice,
105				    choices[i].selection,
106				    kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
107			if (flags != NULL) {
108				*flags = choices[i].flags;
109			}
110			return i;
111		}
112		i++;
113	}
114
115	return kCFNotFound;
116}
117
118
119__private_extern__
120Boolean
121_process_options(optionsRef options, int nOptions, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
122{
123	while (argc > 0) {
124		CFIndex	optionIndex	= kCFNotFound;
125
126		optionIndex = _find_option(argv[0], options, nOptions);
127		if (optionIndex == kCFNotFound) {
128			SCPrint(TRUE, stdout, CFSTR("set what?\n"));
129			return FALSE;
130		}
131		argv++;
132		argc--;
133
134		switch (options[optionIndex].type) {
135			case isOther :
136				// all option processing is managed by the "handler"
137				break;
138			case isHelp :
139				SCPrint(TRUE, stdout, CFSTR("%s\n"), options[optionIndex].info);
140				return FALSE;
141			case isChooseOne : {
142				CFStringRef	choice;
143				selections	*choices	= (selections *)options[optionIndex].info;
144				unsigned int	flags;
145				CFIndex		i;
146
147				if (argc < 1) {
148					SCPrint(TRUE, stdout,
149						CFSTR("%s not specified\n"),
150						options[optionIndex].description != NULL ? options[optionIndex].description : "selection");
151					return FALSE;
152				}
153
154				choice = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
155				i = _find_selection(choice, choices, &flags);
156				CFRelease(choice);
157
158				if (i != kCFNotFound) {
159					if (choices[i].flags & selectionNotAvailable) {
160						SCPrint(TRUE, stdout,
161							CFSTR("cannot select %s\n"),
162							options[optionIndex].description != NULL ? options[optionIndex].description : "selection");
163							return FALSE;
164					}
165
166					CFDictionarySetValue(newConfiguration,
167							     *(options[optionIndex].key),
168							     *(choices[i].key));
169				} else {
170					SCPrint(TRUE, stdout,
171						CFSTR("invalid %s\n"),
172						options[optionIndex].description != NULL ? options[optionIndex].description : "selection");
173					return FALSE;
174				}
175
176				argv++;
177				argc--;
178				break;
179			}
180			case isChooseMultiple :
181				if (argc < 1) {
182					SCPrint(TRUE, stdout,
183						CFSTR("%s(s) not specified\n"),
184						options[optionIndex].description != NULL ? options[optionIndex].description : "selection");
185					return FALSE;
186				}
187
188				if (strlen(argv[0]) > 0) {
189					CFIndex			i;
190					CFIndex			n;
191					CFMutableArrayRef	chosen;
192					CFStringRef		str;
193					CFArrayRef		str_array;
194
195					str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
196					str_array = CFStringCreateArrayBySeparatingStrings(NULL, str, CFSTR(","));
197					CFRelease(str);
198
199					chosen = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
200
201					n = CFArrayGetCount(str_array);
202					for (i = 0; i < n; i++) {
203						CFStringRef	choice;
204						selections	*choices	= (selections *)options[optionIndex].info;
205						unsigned int	flags;
206						CFIndex		j;
207
208						choice = CFArrayGetValueAtIndex(str_array, i);
209						j = _find_selection(choice, choices, &flags);
210
211						if (j != kCFNotFound) {
212							if (choices[j].flags & selectionNotAvailable) {
213								SCPrint(TRUE, stdout,
214									CFSTR("cannot select %s\n"),
215									options[optionIndex].description != NULL ? options[optionIndex].description : "selection");
216								CFArrayRemoveAllValues(chosen);
217								break;
218							}
219
220							CFArrayAppendValue(chosen, *(choices[j].key));
221						} else {
222							SCPrint(TRUE, stdout,
223								CFSTR("invalid %s\n"),
224								options[optionIndex].description != NULL ? options[optionIndex].description : "selection");
225							CFArrayRemoveAllValues(chosen);
226							break;
227						}
228					}
229					CFRelease(str_array);
230
231					if (CFArrayGetCount(chosen) > 0) {
232						CFDictionarySetValue(newConfiguration, *(options[optionIndex].key), chosen);
233					} else {
234						CFDictionaryRemoveValue(newConfiguration, *(options[optionIndex].key));
235					}
236					CFRelease(chosen);
237				} else {
238					CFDictionaryRemoveValue(newConfiguration, *(options[optionIndex].key));
239				}
240
241				argv++;
242				argc--;
243				break;
244			case isBoolean :
245				if (argc < 1) {
246					SCPrint(TRUE, stdout,
247						CFSTR("%s not specified\n"),
248						options[optionIndex].description != NULL ? options[optionIndex].description : "enable/disable");
249					return FALSE;
250				}
251
252				if        ((strcasecmp(argv[0], "disable") == 0) ||
253					   (strcasecmp(argv[0], "no"     ) == 0) ||
254					   (strcasecmp(argv[0], "off"    ) == 0) ||
255					   (strcasecmp(argv[0], "0"      ) == 0)) {
256					CFDictionarySetValue(newConfiguration, *(options[optionIndex].key), CFNumberRef_0);
257				} else if ((strcasecmp(argv[0], "enable") == 0) ||
258					   (strcasecmp(argv[0], "yes"   ) == 0) ||
259					   (strcasecmp(argv[0], "on"   ) == 0) ||
260					   (strcasecmp(argv[0], "1"     ) == 0)) {
261					CFDictionarySetValue(newConfiguration, *(options[optionIndex].key), CFNumberRef_1);
262				} else {
263					SCPrint(TRUE, stdout, CFSTR("invalid value\n"));
264					return FALSE;
265				}
266
267				argv++;
268				argc--;
269				break;
270			case isNumber :
271				if (argc < 1) {
272					SCPrint(TRUE, stdout,
273						CFSTR("%s not specified\n"),
274						options[optionIndex].description != NULL ? options[optionIndex].description : "value");
275					return FALSE;
276				}
277
278				if (strlen(argv[0]) > 0) {
279					CFNumberRef	num;
280
281					num = _copy_number(argv[0]);
282					if (num != NULL) {
283						CFDictionarySetValue(newConfiguration, *(options[optionIndex].key), num);
284						CFRelease(num);
285					} else {
286						SCPrint(TRUE, stdout, CFSTR("invalid value\n"));
287						return FALSE;
288					}
289				} else {
290					CFDictionaryRemoveValue(newConfiguration, *(options[optionIndex].key));
291				}
292
293				argv++;
294				argc--;
295				break;
296			case isString :
297				if (argc < 1) {
298					SCPrint(TRUE, stdout,
299						CFSTR("%s not specified\n"),
300						options[optionIndex].description != NULL ? options[optionIndex].description : "value");
301					return FALSE;
302				}
303
304				if (strlen(argv[0]) > 0) {
305					CFStringRef	str;
306
307					str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
308					CFDictionarySetValue(newConfiguration, *(options[optionIndex].key), str);
309					CFRelease(str);
310				} else {
311					CFDictionaryRemoveValue(newConfiguration, *(options[optionIndex].key));
312				}
313
314				argv++;
315				argc--;
316				break;
317			case isStringArray :
318				if (argc < 1) {
319					SCPrint(TRUE, stdout,
320						CFSTR("%s(s) not specified\n"),
321						options[optionIndex].description != NULL ? options[optionIndex].description : "value");
322					return FALSE;
323				}
324
325				if (strlen(argv[0]) > 0) {
326					CFStringRef	str;
327					CFArrayRef	str_array;
328
329					str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
330					str_array = CFStringCreateArrayBySeparatingStrings(NULL, str, CFSTR(","));
331					CFRelease(str);
332
333					CFDictionarySetValue(newConfiguration, *(options[optionIndex].key), str_array);
334					CFRelease(str_array);
335				} else {
336					CFDictionaryRemoveValue(newConfiguration, *(options[optionIndex].key));
337				}
338
339				argv++;
340				argc--;
341				break;
342		}
343
344		if (options[optionIndex].handler != NULL) {
345			CFStringRef	key;
346			int		nArgs;
347
348			key = options[optionIndex].key != NULL ? *(options[optionIndex].key) : NULL;
349			nArgs = (*options[optionIndex].handler)(key,
350								options[optionIndex].description,
351								options[optionIndex].info,
352								argc,
353								argv,
354								newConfiguration);
355			if (nArgs < 0) {
356				return FALSE;
357			}
358
359			argv += nArgs;
360			argc -= nArgs;
361		}
362	}
363
364	return TRUE;
365}
366
367
368/* -------------------- */
369
370
371#define	N_QUICK	32
372
373__private_extern__
374void
375_show_entity(CFDictionaryRef entity, CFStringRef prefix)
376{
377	CFArrayRef		array;
378	const void *		keys_q[N_QUICK];
379	const void **		keys	= keys_q;
380	CFIndex			i;
381	CFIndex			n;
382	CFMutableArrayRef	sorted;
383
384	n = CFDictionaryGetCount(entity);
385	if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) {
386		keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0);
387	}
388	CFDictionaryGetKeysAndValues(entity, keys, NULL);
389
390	array  = CFArrayCreate(NULL, keys, n, &kCFTypeArrayCallBacks);
391	sorted = CFArrayCreateMutableCopy(NULL, n, array);
392	if (n > 1) {
393		CFArraySortValues(sorted,
394				  CFRangeMake(0, n),
395				  (CFComparatorFunction)CFStringCompare,
396				  NULL);
397	}
398
399	for (i = 0; i < n; i++) {
400		CFStringRef	key;
401		CFTypeRef	value;
402
403		key   = CFArrayGetValueAtIndex(sorted, i);
404		value = CFDictionaryGetValue(entity, key);
405		if (isA_CFArray(value)) {
406			CFIndex		i;
407			CFIndex		n	= CFArrayGetCount(value);
408
409			SCPrint(TRUE, stdout, CFSTR("%@    %@ = ("), prefix, key);
410			for (i = 0; i < n; i++) {
411				CFTypeRef	val;
412
413				val = CFArrayGetValueAtIndex(value, i);
414				SCPrint(TRUE, stdout,
415					CFSTR("%s%@"),
416					(i > 0) ? ", " : "",
417					val);
418			}
419			SCPrint(TRUE, stdout, CFSTR(")\n"));
420		} else {
421			SCPrint(TRUE, stdout, CFSTR("%@    %@ = %@\n"), prefix, key, value);
422		}
423	}
424
425	CFRelease(sorted);
426	CFRelease(array);
427	if (keys != keys_q) {
428		CFAllocatorDeallocate(NULL, keys);
429	}
430
431	return;
432}
433
434
435/* -------------------- */
436
437
438static void
439_net_close()
440{
441	if (net_interface != NULL) {
442		CFRelease(net_interface);
443		net_interface = NULL;
444	}
445
446	if (net_service != NULL) {
447		CFRelease(net_service);
448		net_service = NULL;
449	}
450
451	if (net_protocol != NULL) {
452		CFRelease(net_protocol);
453		net_protocol = NULL;
454	}
455
456	if (net_set != NULL) {
457		CFRelease(net_set);
458		net_set = NULL;
459	}
460
461	if (interfaces != NULL) {
462		CFRelease(interfaces);
463		interfaces = NULL;
464	}
465
466	if (services != NULL) {
467		CFRelease(services);
468		services = NULL;
469	}
470
471	if (protocols != NULL) {
472		CFRelease(protocols);
473		protocols = NULL;
474	}
475
476	if (sets != NULL) {
477		CFRelease(sets);
478		sets = NULL;
479	}
480
481	if (new_interfaces != NULL) {
482		CFRelease(new_interfaces);
483		new_interfaces = NULL;
484	}
485
486	return;
487}
488
489
490__private_extern__
491void
492do_net_init()
493{
494	int	one	= 1;
495	int	zero	= 0;
496
497	CFNumberRef_0 = CFNumberCreate(NULL, kCFNumberIntType, &zero);
498	CFNumberRef_1 = CFNumberCreate(NULL, kCFNumberIntType, &one);
499
500	return;
501}
502
503
504__private_extern__
505void
506do_net_open(int argc, char **argv)
507{
508	Boolean		ok;
509	CFStringRef	prefsID	= NULL;
510
511	if (prefs != NULL) {
512		if (_prefs_commitRequired(argc, argv, "close")) {
513			return;
514		}
515
516		_net_close();
517		_prefs_close();
518	}
519
520	if (argc > 0) {
521		prefsID = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
522	}
523
524	ok = _prefs_open(CFSTR("scutil --net"), prefsID);
525	if (prefsID != NULL) CFRelease(prefsID);
526	if (!ok) {
527		SCPrint(TRUE,
528			stdout,
529			CFSTR("Could not open prefs: %s\n"),
530			SCErrorString(SCError()));
531		return;
532	}
533
534	net_set = SCNetworkSetCopyCurrent(prefs);
535	if (net_set != NULL) {
536		CFStringRef	setName;
537
538		setName = SCNetworkSetGetName(net_set);
539		if (setName != NULL) {
540			SCPrint(TRUE, stdout, CFSTR("set \"%@\" selected\n"), setName);
541		} else {
542			SCPrint(TRUE, stdout,
543				CFSTR("set ID \"%@\" selected\n"),
544				SCNetworkSetGetSetID(net_set));
545		}
546	}
547
548	return;
549}
550
551
552__private_extern__
553void
554do_net_commit(int argc, char **argv)
555{
556	if (!SCPreferencesCommitChanges(prefs)) {
557		SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
558		return;
559	}
560
561	_prefs_changed = FALSE;
562	return;
563}
564
565
566__private_extern__
567void
568do_net_apply(int argc, char **argv)
569{
570	if (!SCPreferencesApplyChanges(prefs)) {
571		SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
572	}
573	return;
574}
575
576
577__private_extern__
578void
579do_net_close(int argc, char **argv)
580{
581	if (_prefs_commitRequired(argc, argv, "close")) {
582		return;
583	}
584
585	_net_close();
586	_prefs_close();
587
588	return;
589}
590
591
592__private_extern__
593void
594do_net_quit(int argc, char **argv)
595{
596	if (_prefs_commitRequired(argc, argv, "quit")) {
597		return;
598	}
599
600	_net_close();
601	_prefs_close();
602
603	termRequested = TRUE;
604	return;
605}
606
607
608/* -------------------- */
609
610
611typedef void (*net_func) (int argc, char **argv);
612
613static const struct {
614	char		*key;
615	net_func	create;
616	net_func	disable;
617	net_func	enable;
618	net_func	select;
619	net_func	set;
620	net_func	show;
621	net_func	remove;
622} net_keys[] = {
623
624	{ "interfaces", NULL            , NULL            , NULL            ,
625			NULL            , NULL            , show_interfaces ,
626			NULL                                                },
627
628	{ "interface",  create_interface, NULL            , NULL            ,
629			select_interface, set_interface   , show_interface  ,
630			NULL                                                },
631
632	{ "services",   NULL            , NULL            , NULL            ,
633			NULL            , NULL            , show_services   ,
634			NULL                                                },
635
636	{ "service",    create_service  , disable_service , enable_service  ,
637			select_service  , set_service     , show_service    ,
638			remove_service                                      },
639
640	{ "protocols",  NULL            , NULL            , NULL            ,
641			NULL            , NULL            , show_protocols  ,
642			NULL                                                },
643
644	{ "protocol",   create_protocol , disable_protocol, enable_protocol ,
645			select_protocol , set_protocol    , show_protocol   ,
646			remove_protocol                                     },
647
648	{ "sets",       NULL            , NULL            , NULL            ,
649			NULL            , NULL            , show_sets       ,
650			NULL                                                },
651
652	{ "set",        create_set      , NULL            , NULL            ,
653			select_set      , set_set         , show_set        ,
654			remove_set                                          }
655
656};
657#define	N_NET_KEYS	(sizeof(net_keys) / sizeof(net_keys[0]))
658
659
660static int
661findNetKey(char *key)
662{
663	int	i;
664
665	for (i = 0; i < (int)N_NET_KEYS; i++) {
666		if (strcmp(key, net_keys[i].key) == 0) {
667			return i;
668		}
669	}
670
671	return -1;
672}
673
674
675/* -------------------- */
676
677
678__private_extern__
679void
680do_net_create(int argc, char **argv)
681{
682	char	*key;
683	int	i;
684
685	key = argv[0];
686	argv++;
687	argc--;
688
689	i = findNetKey(key);
690	if (i < 0) {
691		SCPrint(TRUE, stderr, CFSTR("create what?\n"));
692		return;
693	}
694
695	if (net_keys[i].create == NULL) {
696		SCPrint(TRUE, stderr, CFSTR("create what?\n"));
697		return;
698	}
699
700	(*net_keys[i].create)(argc, argv);
701	return;
702}
703
704
705__private_extern__
706void
707do_net_disable(int argc, char **argv)
708{
709	char	*key;
710	int	i;
711
712	key = argv[0];
713	argv++;
714	argc--;
715
716	i = findNetKey(key);
717	if (i < 0) {
718		SCPrint(TRUE, stderr, CFSTR("disable what?\n"));
719		return;
720	}
721
722	if (net_keys[i].disable == NULL) {
723		SCPrint(TRUE, stderr, CFSTR("disable what?\n"));
724		return;
725	}
726
727	(*net_keys[i].disable)(argc, argv);
728	return;
729}
730
731
732__private_extern__
733void
734do_net_enable(int argc, char **argv)
735{
736	char	*key;
737	int	i;
738
739	key = argv[0];
740	argv++;
741	argc--;
742
743	i = findNetKey(key);
744	if (i < 0) {
745		SCPrint(TRUE, stderr, CFSTR("enable what?\n"));
746		return;
747	}
748
749	if (net_keys[i].enable == NULL) {
750		SCPrint(TRUE, stderr, CFSTR("enable what?\n"));
751		return;
752	}
753
754	(*net_keys[i].enable)(argc, argv);
755	return;
756}
757
758
759__private_extern__
760void
761do_net_remove(int argc, char **argv)
762{
763	char	*key;
764	int	i;
765
766	key = argv[0];
767	argv++;
768	argc--;
769
770	i = findNetKey(key);
771	if (i < 0) {
772		SCPrint(TRUE, stderr, CFSTR("remove what?\n"));
773		return;
774	}
775
776	if (net_keys[i].remove == NULL) {
777		SCPrint(TRUE, stderr, CFSTR("remove what?\n"));
778		return;
779	}
780
781	(*net_keys[i].remove)(argc, argv);
782	return;
783}
784
785
786__private_extern__
787void
788do_net_select(int argc, char **argv)
789{
790	char	*key;
791	int	i;
792
793	key = argv[0];
794	argv++;
795	argc--;
796
797	i = findNetKey(key);
798	if (i < 0) {
799		SCPrint(TRUE, stderr, CFSTR("select what?\n"));
800		return;
801	}
802
803	if (*net_keys[i].select == NULL) {
804		SCPrint(TRUE, stderr, CFSTR("select what?\n"));
805		return;
806	}
807
808	(*net_keys[i].select)(argc, argv);
809	return;
810}
811
812
813__private_extern__
814void
815do_net_set(int argc, char **argv)
816{
817	char	*key;
818	int	i;
819
820	key = argv[0];
821	argv++;
822	argc--;
823
824	i = findNetKey(key);
825	if (i < 0) {
826		SCPrint(TRUE, stderr, CFSTR("set what?\n"));
827		return;
828	}
829
830	(*net_keys[i].set)(argc, argv);
831	return;
832}
833
834
835__private_extern__
836void
837do_net_show(int argc, char **argv)
838{
839	char	*key;
840	int	i;
841
842	key = argv[0];
843	argv++;
844	argc--;
845
846	i = findNetKey(key);
847	if (i < 0) {
848		SCPrint(TRUE, stderr, CFSTR("show what?\n"));
849		return;
850	}
851
852	(*net_keys[i].show)(argc, argv);
853	return;
854}
855
856
857__private_extern__
858void
859do_net_update(int argc, char **argv)
860{
861	SCNetworkSetRef	set;
862	Boolean		setCreated	= FALSE;
863	Boolean		setUpdated	= FALSE;
864
865	if (prefs == NULL) {
866		SCPrint(TRUE, stdout, CFSTR("network configuration not open\n"));
867		return;
868	}
869
870	if (net_set != NULL) {
871		set = CFRetain(net_set);
872	} else {
873		set = SCNetworkSetCopyCurrent(prefs);
874		if (set == NULL) {
875			CFBundleRef	bundle;
876			Boolean		ok;
877			CFArrayRef	sets;
878			CFStringRef	setName	= NULL;
879
880			sets = SCNetworkSetCopyAll(prefs);
881			if (sets != NULL) {
882				CFIndex	n;
883
884				n = CFArrayGetCount(sets);
885				CFRelease(sets);
886				sets = NULL;
887				if (n > 0) {
888					SCPrint(TRUE, stdout, CFSTR("no current set\n"));
889					return;
890				}
891			}
892
893			bundle = _SC_CFBundleGet();
894			if (bundle != NULL) {
895				setName = CFBundleCopyLocalizedString(bundle,
896								      CFSTR("DEFAULT_SET_NAME"),
897								      CFSTR("Automatic"),
898								      NULL);
899			}
900			if (setName == NULL) {
901				setName = CFSTR("Automatic");
902				CFRetain(setName);
903			}
904
905			set = SCNetworkSetCreate(prefs);
906			if (set == NULL) {
907				SCPrint(TRUE, stdout,
908					CFSTR("could not initialize \"%@\": %s\n"),
909					setName,
910					SCErrorString(SCError()));
911				CFRelease(setName);
912				return;
913			}
914
915			(void) SCNetworkSetSetName(set, setName);
916
917			ok = SCNetworkSetSetCurrent(set);
918			if (!ok) {
919				SCPrint(TRUE, stdout,
920					CFSTR("could not initialize \"%@\": %s\n"),
921					setName,
922					SCErrorString(SCError()));
923				(void) SCNetworkSetRemove(set);
924				CFRelease(setName);
925				CFRelease(set);
926				return;
927			}
928
929			if (net_set != NULL) CFRelease(net_set);
930			net_set = set;
931
932			setCreated = TRUE;
933
934			CFRelease(setName);
935			CFRetain(set);
936		}
937	}
938
939	setUpdated = SCNetworkSetEstablishDefaultConfiguration(set);
940	if (setUpdated) {
941		CFStringRef	setName;
942
943		_prefs_changed = TRUE;
944
945		setName = SCNetworkSetGetName(set);
946		if (setName != NULL) {
947			SCPrint(TRUE, stdout,
948				CFSTR("set \"%@\" (%@) %supdated\n"),
949				setName,
950				SCNetworkSetGetSetID(set),
951				setCreated ? "created, selected, and " : "");
952		} else {
953			SCPrint(TRUE, stdout,
954				CFSTR("set ID \"%@\" %supdated\n"),
955				SCNetworkSetGetSetID(set),
956				setCreated ? "created, selected, and " : "");
957		}
958	}
959
960	CFRelease(set);
961	return;
962}
963
964
965#include "SCPreferencesInternal.h"
966#include <fcntl.h>
967#include <unistd.h>
968__private_extern__
969void
970do_net_snapshot(int argc, char **argv)
971{
972	if (prefs == NULL) {
973		SCPrint(TRUE, stdout, CFSTR("network configuration not open\n"));
974		return;
975	}
976
977	if (prefs != NULL) {
978		SCPreferencesPrivateRef	prefsPrivate	= (SCPreferencesPrivateRef)prefs;
979
980		if (prefsPrivate->prefs != NULL) {
981			int		fd;
982			static int	n_snapshot	= 0;
983			char		*path;
984			CFDataRef	xmlData;
985
986			asprintf(&path, "/tmp/prefs_snapshot_%d", n_snapshot++);
987			(void)unlink(path);
988			fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644);
989			free(path);
990			if (fd == -1) {
991				SCPrint(TRUE, stdout, CFSTR("could not write snapshot: open() failed : %s\n"), strerror(errno));
992				return;
993			}
994
995			xmlData = CFPropertyListCreateData(NULL, prefsPrivate->prefs, kCFPropertyListXMLFormat_v1_0, 0, NULL);
996			if (xmlData != NULL) {
997				(void) write(fd, CFDataGetBytePtr(xmlData), CFDataGetLength(xmlData));
998				CFRelease(xmlData);
999			} else {
1000				SCPrint(TRUE, stdout, CFSTR("could not write snapshot: CFPropertyListCreateData() failed\n"));
1001			}
1002
1003			(void) close(fd);
1004		} else {
1005			SCPrint(TRUE, stdout, CFSTR("prefs have not been accessed\n"));
1006		}
1007	}
1008
1009	return;
1010}
1011