2 * Copyright (c) 2004-2007, 2009-2011 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 * Modification History
27 * August 5, 2004 Allan Nathanson <ajn@apple.com>
36 #include "net_interface.h"
37 #include "net_protocol.h"
38 #include "net_service.h"
44 __private_extern__ CFMutableArrayRef new_interfaces
= NULL
;
46 __private_extern__ CFArrayRef interfaces
= NULL
;
47 __private_extern__ CFArrayRef services
= NULL
;
48 __private_extern__ CFArrayRef protocols
= NULL
;
49 __private_extern__ CFArrayRef sets
= NULL
;
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
;
56 __private_extern__ CFNumberRef CFNumberRef_0
= NULL
;
57 __private_extern__ CFNumberRef CFNumberRef_1
= NULL
;
60 /* -------------------- */
64 CF_RETURNS_RETAINED CFNumberRef
65 _copy_number(const char *arg
)
69 if (sscanf(arg
, "%d", &val
) != 1) {
73 return CFNumberCreate(NULL
, kCFNumberIntType
, &val
);
77 /* -------------------- */
82 _find_option(const char *option
, optionsRef options
, const int nOptions
)
86 for (i
= 0; i
< nOptions
; i
++) {
87 if (strcasecmp(option
, options
[i
].option
) == 0) {
98 _find_selection(CFStringRef choice
, selections choices
[], unsigned int *flags
)
103 while (choices
[i
].selection
!= NULL
) {
104 if (CFStringCompare(choice
,
105 choices
[i
].selection
,
106 kCFCompareCaseInsensitive
) == kCFCompareEqualTo
) {
108 *flags
= choices
[i
].flags
;
121 _process_options(optionsRef options
, int nOptions
, int argc
, char **argv
, CFMutableDictionaryRef newConfiguration
)
124 CFIndex optionIndex
= kCFNotFound
;
126 optionIndex
= _find_option(argv
[0], options
, nOptions
);
127 if (optionIndex
== kCFNotFound
) {
128 SCPrint(TRUE
, stdout
, CFSTR("set what?\n"));
134 switch (options
[optionIndex
].type
) {
136 // all option processing is managed by the "handler"
139 SCPrint(TRUE
, stdout
, CFSTR("%s\n"), options
[optionIndex
].info
);
143 selections
*choices
= (selections
*)options
[optionIndex
].info
;
148 SCPrint(TRUE
, stdout
,
149 CFSTR("%s not specified\n"),
150 options
[optionIndex
].description
!= NULL
? options
[optionIndex
].description
: "selection");
154 choice
= CFStringCreateWithCString(NULL
, argv
[0], kCFStringEncodingUTF8
);
155 i
= _find_selection(choice
, choices
, &flags
);
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");
166 CFDictionarySetValue(newConfiguration
,
167 *(options
[optionIndex
].key
),
170 SCPrint(TRUE
, stdout
,
171 CFSTR("invalid %s\n"),
172 options
[optionIndex
].description
!= NULL
? options
[optionIndex
].description
: "selection");
180 case isChooseMultiple
:
182 SCPrint(TRUE
, stdout
,
183 CFSTR("%s(s) not specified\n"),
184 options
[optionIndex
].description
!= NULL
? options
[optionIndex
].description
: "selection");
188 if (strlen(argv
[0]) > 0) {
191 CFMutableArrayRef chosen
;
193 CFArrayRef str_array
;
195 str
= CFStringCreateWithCString(NULL
, argv
[0], kCFStringEncodingUTF8
);
196 str_array
= CFStringCreateArrayBySeparatingStrings(NULL
, str
, CFSTR(","));
199 chosen
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
201 n
= CFArrayGetCount(str_array
);
202 for (i
= 0; i
< n
; i
++) {
204 selections
*choices
= (selections
*)options
[optionIndex
].info
;
208 choice
= CFArrayGetValueAtIndex(str_array
, i
);
209 j
= _find_selection(choice
, choices
, &flags
);
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
);
220 CFArrayAppendValue(chosen
, *(choices
[j
].key
));
222 SCPrint(TRUE
, stdout
,
223 CFSTR("invalid %s\n"),
224 options
[optionIndex
].description
!= NULL
? options
[optionIndex
].description
: "selection");
225 CFArrayRemoveAllValues(chosen
);
229 CFRelease(str_array
);
231 if (CFArrayGetCount(chosen
) > 0) {
232 CFDictionarySetValue(newConfiguration
, *(options
[optionIndex
].key
), chosen
);
234 CFDictionaryRemoveValue(newConfiguration
, *(options
[optionIndex
].key
));
238 CFDictionaryRemoveValue(newConfiguration
, *(options
[optionIndex
].key
));
246 SCPrint(TRUE
, stdout
,
247 CFSTR("%s not specified\n"),
248 options
[optionIndex
].description
!= NULL
? options
[optionIndex
].description
: "enable/disable");
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
);
263 SCPrint(TRUE
, stdout
, CFSTR("invalid value\n"));
272 SCPrint(TRUE
, stdout
,
273 CFSTR("%s not specified\n"),
274 options
[optionIndex
].description
!= NULL
? options
[optionIndex
].description
: "value");
278 if (strlen(argv
[0]) > 0) {
281 num
= _copy_number(argv
[0]);
283 CFDictionarySetValue(newConfiguration
, *(options
[optionIndex
].key
), num
);
286 SCPrint(TRUE
, stdout
, CFSTR("invalid value\n"));
290 CFDictionaryRemoveValue(newConfiguration
, *(options
[optionIndex
].key
));
298 SCPrint(TRUE
, stdout
,
299 CFSTR("%s not specified\n"),
300 options
[optionIndex
].description
!= NULL
? options
[optionIndex
].description
: "value");
304 if (strlen(argv
[0]) > 0) {
307 str
= CFStringCreateWithCString(NULL
, argv
[0], kCFStringEncodingUTF8
);
308 CFDictionarySetValue(newConfiguration
, *(options
[optionIndex
].key
), str
);
311 CFDictionaryRemoveValue(newConfiguration
, *(options
[optionIndex
].key
));
319 SCPrint(TRUE
, stdout
,
320 CFSTR("%s(s) not specified\n"),
321 options
[optionIndex
].description
!= NULL
? options
[optionIndex
].description
: "value");
325 if (strlen(argv
[0]) > 0) {
327 CFArrayRef str_array
;
329 str
= CFStringCreateWithCString(NULL
, argv
[0], kCFStringEncodingUTF8
);
330 str_array
= CFStringCreateArrayBySeparatingStrings(NULL
, str
, CFSTR(","));
333 CFDictionarySetValue(newConfiguration
, *(options
[optionIndex
].key
), str_array
);
334 CFRelease(str_array
);
336 CFDictionaryRemoveValue(newConfiguration
, *(options
[optionIndex
].key
));
344 if (options
[optionIndex
].handler
!= NULL
) {
348 key
= options
[optionIndex
].key
!= NULL
? *(options
[optionIndex
].key
) : NULL
;
349 nArgs
= (*options
[optionIndex
].handler
)(key
,
350 options
[optionIndex
].description
,
351 options
[optionIndex
].info
,
368 /* -------------------- */
375 _show_entity(CFDictionaryRef entity
, CFStringRef prefix
)
378 const void * keys_q
[N_QUICK
];
379 const void ** keys
= keys_q
;
382 CFMutableArrayRef sorted
;
384 n
= CFDictionaryGetCount(entity
);
385 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
386 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
388 CFDictionaryGetKeysAndValues(entity
, keys
, NULL
);
390 array
= CFArrayCreate(NULL
, keys
, n
, &kCFTypeArrayCallBacks
);
391 sorted
= CFArrayCreateMutableCopy(NULL
, n
, array
);
393 CFArraySortValues(sorted
,
395 (CFComparatorFunction
)CFStringCompare
,
399 for (i
= 0; i
< n
; i
++) {
403 key
= CFArrayGetValueAtIndex(sorted
, i
);
404 value
= CFDictionaryGetValue(entity
, key
);
405 if (isA_CFArray(value
)) {
407 CFIndex n
= CFArrayGetCount(value
);
409 SCPrint(TRUE
, stdout
, CFSTR("%@ %@ = ("), prefix
, key
);
410 for (i
= 0; i
< n
; i
++) {
413 val
= CFArrayGetValueAtIndex(value
, i
);
414 SCPrint(TRUE
, stdout
,
419 SCPrint(TRUE
, stdout
, CFSTR(")\n"));
421 SCPrint(TRUE
, stdout
, CFSTR("%@ %@ = %@\n"), prefix
, key
, value
);
427 if (keys
!= keys_q
) {
428 CFAllocatorDeallocate(NULL
, keys
);
435 /* -------------------- */
441 if (net_interface
!= NULL
) {
442 CFRelease(net_interface
);
443 net_interface
= NULL
;
446 if (net_service
!= NULL
) {
447 CFRelease(net_service
);
451 if (net_protocol
!= NULL
) {
452 CFRelease(net_protocol
);
456 if (net_set
!= NULL
) {
461 if (interfaces
!= NULL
) {
462 CFRelease(interfaces
);
466 if (services
!= NULL
) {
471 if (protocols
!= NULL
) {
472 CFRelease(protocols
);
481 if (new_interfaces
!= NULL
) {
482 CFRelease(new_interfaces
);
483 new_interfaces
= NULL
;
497 CFNumberRef_0
= CFNumberCreate(NULL
, kCFNumberIntType
, &zero
);
498 CFNumberRef_1
= CFNumberCreate(NULL
, kCFNumberIntType
, &one
);
506 do_net_open(int argc
, char **argv
)
509 CFStringRef prefsID
= NULL
;
512 if (_prefs_commitRequired(argc
, argv
, "close")) {
521 prefsID
= CFStringCreateWithCString(NULL
, argv
[0], kCFStringEncodingUTF8
);
524 ok
= _prefs_open(CFSTR("scutil --net"), prefsID
);
525 if (prefsID
!= NULL
) CFRelease(prefsID
);
529 CFSTR("Could not open prefs: %s\n"),
530 SCErrorString(SCError()));
534 net_set
= SCNetworkSetCopyCurrent(prefs
);
535 if (net_set
!= NULL
) {
538 setName
= SCNetworkSetGetName(net_set
);
539 if (setName
!= NULL
) {
540 SCPrint(TRUE
, stdout
, CFSTR("set \"%@\" selected\n"), setName
);
542 SCPrint(TRUE
, stdout
,
543 CFSTR("set ID \"%@\" selected\n"),
544 SCNetworkSetGetSetID(net_set
));
554 do_net_commit(int argc
, char **argv
)
556 if (!SCPreferencesCommitChanges(prefs
)) {
557 SCPrint(TRUE
, stdout
, CFSTR("%s\n"), SCErrorString(SCError()));
561 _prefs_changed
= FALSE
;
568 do_net_apply(int argc
, char **argv
)
570 if (!SCPreferencesApplyChanges(prefs
)) {
571 SCPrint(TRUE
, stdout
, CFSTR("%s\n"), SCErrorString(SCError()));
579 do_net_close(int argc
, char **argv
)
581 if (_prefs_commitRequired(argc
, argv
, "close")) {
594 do_net_quit(int argc
, char **argv
)
596 if (_prefs_commitRequired(argc
, argv
, "quit")) {
603 termRequested
= TRUE
;
608 /* -------------------- */
611 typedef void (*net_func
) (int argc
, char **argv
);
613 static const struct {
624 { "interfaces", NULL
, NULL
, NULL
,
625 NULL
, NULL
, show_interfaces
,
628 { "interface", create_interface
, NULL
, NULL
,
629 select_interface
, set_interface
, show_interface
,
632 { "services", NULL
, NULL
, NULL
,
633 NULL
, NULL
, show_services
,
636 { "service", create_service
, disable_service
, enable_service
,
637 select_service
, set_service
, show_service
,
640 { "protocols", NULL
, NULL
, NULL
,
641 NULL
, NULL
, show_protocols
,
644 { "protocol", create_protocol
, disable_protocol
, enable_protocol
,
645 select_protocol
, set_protocol
, show_protocol
,
648 { "sets", NULL
, NULL
, NULL
,
649 NULL
, NULL
, show_sets
,
652 { "set", create_set
, NULL
, NULL
,
653 select_set
, set_set
, show_set
,
657 #define N_NET_KEYS (sizeof(net_keys) / sizeof(net_keys[0]))
661 findNetKey(char *key
)
665 for (i
= 0; i
< (int)N_NET_KEYS
; i
++) {
666 if (strcmp(key
, net_keys
[i
].key
) == 0) {
675 /* -------------------- */
680 do_net_create(int argc
, char **argv
)
691 SCPrint(TRUE
, stderr
, CFSTR("create what?\n"));
695 if (net_keys
[i
].create
== NULL
) {
696 SCPrint(TRUE
, stderr
, CFSTR("create what?\n"));
700 (*net_keys
[i
].create
)(argc
, argv
);
707 do_net_disable(int argc
, char **argv
)
718 SCPrint(TRUE
, stderr
, CFSTR("disable what?\n"));
722 if (net_keys
[i
].disable
== NULL
) {
723 SCPrint(TRUE
, stderr
, CFSTR("disable what?\n"));
727 (*net_keys
[i
].disable
)(argc
, argv
);
734 do_net_enable(int argc
, char **argv
)
745 SCPrint(TRUE
, stderr
, CFSTR("enable what?\n"));
749 if (net_keys
[i
].enable
== NULL
) {
750 SCPrint(TRUE
, stderr
, CFSTR("enable what?\n"));
754 (*net_keys
[i
].enable
)(argc
, argv
);
761 do_net_remove(int argc
, char **argv
)
772 SCPrint(TRUE
, stderr
, CFSTR("remove what?\n"));
776 if (net_keys
[i
].remove
== NULL
) {
777 SCPrint(TRUE
, stderr
, CFSTR("remove what?\n"));
781 (*net_keys
[i
].remove
)(argc
, argv
);
788 do_net_select(int argc
, char **argv
)
799 SCPrint(TRUE
, stderr
, CFSTR("select what?\n"));
803 if (*net_keys
[i
].select
== NULL
) {
804 SCPrint(TRUE
, stderr
, CFSTR("select what?\n"));
808 (*net_keys
[i
].select
)(argc
, argv
);
815 do_net_set(int argc
, char **argv
)
826 SCPrint(TRUE
, stderr
, CFSTR("set what?\n"));
830 (*net_keys
[i
].set
)(argc
, argv
);
837 do_net_show(int argc
, char **argv
)
848 SCPrint(TRUE
, stderr
, CFSTR("show what?\n"));
852 (*net_keys
[i
].show
)(argc
, argv
);
859 do_net_update(int argc
, char **argv
)
862 Boolean setCreated
= FALSE
;
863 Boolean setUpdated
= FALSE
;
866 SCPrint(TRUE
, stdout
, CFSTR("network configuration not open\n"));
870 if (net_set
!= NULL
) {
871 set
= CFRetain(net_set
);
873 set
= SCNetworkSetCopyCurrent(prefs
);
878 CFStringRef setName
= NULL
;
880 sets
= SCNetworkSetCopyAll(prefs
);
884 n
= CFArrayGetCount(sets
);
888 SCPrint(TRUE
, stdout
, CFSTR("no current set\n"));
893 bundle
= _SC_CFBundleGet();
894 if (bundle
!= NULL
) {
895 setName
= CFBundleCopyLocalizedString(bundle
,
896 CFSTR("DEFAULT_SET_NAME"),
900 if (setName
== NULL
) {
901 setName
= CFSTR("Automatic");
905 set
= SCNetworkSetCreate(prefs
);
907 SCPrint(TRUE
, stdout
,
908 CFSTR("could not initialize \"%@\": %s\n"),
910 SCErrorString(SCError()));
915 (void) SCNetworkSetSetName(set
, setName
);
917 ok
= SCNetworkSetSetCurrent(set
);
919 SCPrint(TRUE
, stdout
,
920 CFSTR("could not initialize \"%@\": %s\n"),
922 SCErrorString(SCError()));
923 (void) SCNetworkSetRemove(set
);
929 if (net_set
!= NULL
) CFRelease(net_set
);
939 setUpdated
= SCNetworkSetEstablishDefaultConfiguration(set
);
943 _prefs_changed
= TRUE
;
945 setName
= SCNetworkSetGetName(set
);
946 if (setName
!= NULL
) {
947 SCPrint(TRUE
, stdout
,
948 CFSTR("set \"%@\" (%@) %supdated\n"),
950 SCNetworkSetGetSetID(set
),
951 setCreated
? "created, selected, and " : "");
953 SCPrint(TRUE
, stdout
,
954 CFSTR("set ID \"%@\" %supdated\n"),
955 SCNetworkSetGetSetID(set
),
956 setCreated
? "created, selected, and " : "");
965 #include "SCPreferencesInternal.h"
970 do_net_snapshot(int argc
, char **argv
)
973 SCPrint(TRUE
, stdout
, CFSTR("network configuration not open\n"));
978 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
980 if (prefsPrivate
->prefs
!= NULL
) {
982 static int n_snapshot
= 0;
986 asprintf(&path
, "/tmp/prefs_snapshot_%d", n_snapshot
++);
988 fd
= open(path
, O_WRONLY
|O_CREAT
|O_TRUNC
|O_EXCL
, 0644);
991 SCPrint(TRUE
, stdout
, CFSTR("could not write snapshot: open() failed : %s\n"), strerror(errno
));
995 xmlData
= CFPropertyListCreateData(NULL
, prefsPrivate
->prefs
, kCFPropertyListXMLFormat_v1_0
, 0, NULL
);
996 if (xmlData
!= NULL
) {
997 (void) write(fd
, CFDataGetBytePtr(xmlData
), CFDataGetLength(xmlData
));
1000 SCPrint(TRUE
, stdout
, CFSTR("could not write snapshot: CFPropertyListCreateData() failed\n"));
1005 SCPrint(TRUE
, stdout
, CFSTR("prefs have not been accessed\n"));