2 * Copyright (c) 2004 Apple Computer, 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>
35 #include "net_interface.h"
36 #include "net_protocol.h"
37 #include "net_service.h"
43 __private_extern__ Boolean net_changed
= FALSE
;
45 __private_extern__ CFMutableArrayRef new_interfaces
= NULL
;
47 __private_extern__ CFArrayRef interfaces
= NULL
;
48 __private_extern__ CFArrayRef services
= NULL
;
49 __private_extern__ CFArrayRef protocols
= NULL
;
50 __private_extern__ CFArrayRef sets
= NULL
;
52 __private_extern__ SCNetworkInterfaceRef net_interface
= NULL
;
53 __private_extern__ SCNetworkServiceRef net_service
= NULL
;
54 __private_extern__ SCNetworkProtocolRef net_protocol
= NULL
;
55 __private_extern__ SCNetworkSetRef net_set
= NULL
;
57 __private_extern__ CFNumberRef CFNumberRef_0
= NULL
;
58 __private_extern__ CFNumberRef CFNumberRef_1
= NULL
;
61 /* -------------------- */
66 _copy_number(const char *arg
)
70 if (sscanf(arg
, "%d", &val
) != 1) {
74 return CFNumberCreate(NULL
, kCFNumberIntType
, &val
);
78 /* -------------------- */
83 _find_option(const char *option
, optionsRef options
, const int nOptions
)
87 for (i
= 0; i
< nOptions
; i
++) {
88 if (strcasecmp(option
, options
[i
].option
) == 0) {
99 _find_selection(CFStringRef choice
, selections choices
[], unsigned int *flags
)
104 while (choices
[i
].selection
!= NULL
) {
105 if (CFStringCompare(choice
,
106 choices
[i
].selection
,
107 kCFCompareCaseInsensitive
) == kCFCompareEqualTo
) {
109 *flags
= choices
[i
].flags
;
122 _process_options(optionsRef options
, int nOptions
, int argc
, char **argv
, CFMutableDictionaryRef newConfiguration
)
125 CFIndex optionIndex
= kCFNotFound
;
127 optionIndex
= _find_option(argv
[0], options
, nOptions
);
128 if (optionIndex
== kCFNotFound
) {
129 SCPrint(TRUE
, stdout
, CFSTR("set what?\n"));
135 switch (options
[optionIndex
].type
) {
137 // all option processing is managed by the "handler"
140 SCPrint(TRUE
, stdout
, CFSTR("%s\n"), options
[optionIndex
].info
);
144 selections
*choices
= (selections
*)options
[optionIndex
].info
;
149 SCPrint(TRUE
, stdout
,
150 CFSTR("%s not specified\n"),
151 options
[optionIndex
].description
!= NULL
? options
[optionIndex
].description
: "selection");
155 choice
= CFStringCreateWithCString(NULL
, argv
[0], kCFStringEncodingUTF8
);
156 i
= _find_selection(choice
, choices
, &flags
);
159 if (i
!= kCFNotFound
) {
160 if (choices
[i
].flags
& selectionNotAvailable
) {
161 SCPrint(TRUE
, stdout
,
162 CFSTR("cannot select %s\n"),
163 options
[optionIndex
].description
!= NULL
? options
[optionIndex
].description
: "selection");
167 CFDictionarySetValue(newConfiguration
,
168 *(options
[optionIndex
].key
),
171 SCPrint(TRUE
, stdout
,
172 CFSTR("invalid %s\n"),
173 options
[optionIndex
].description
!= NULL
? options
[optionIndex
].description
: "selection");
181 case isChooseMultiple
:
183 SCPrint(TRUE
, stdout
,
184 CFSTR("%s(s) not specified\n"),
185 options
[optionIndex
].description
!= NULL
? options
[optionIndex
].description
: "selection");
189 if (strlen(argv
[0]) > 0) {
192 CFMutableArrayRef chosen
;
194 CFArrayRef str_array
;
196 str
= CFStringCreateWithCString(NULL
, argv
[0], kCFStringEncodingUTF8
);
197 str_array
= CFStringCreateArrayBySeparatingStrings(NULL
, str
, CFSTR(","));
200 chosen
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
202 n
= CFArrayGetCount(str_array
);
203 for (i
= 0; i
< n
; i
++) {
205 selections
*choices
= (selections
*)options
[optionIndex
].info
;
209 choice
= CFArrayGetValueAtIndex(str_array
, i
);
210 j
= _find_selection(choice
, choices
, &flags
);
212 if (j
!= kCFNotFound
) {
213 if (choices
[j
].flags
& selectionNotAvailable
) {
214 SCPrint(TRUE
, stdout
,
215 CFSTR("cannot select %s\n"),
216 options
[optionIndex
].description
!= NULL
? options
[optionIndex
].description
: "selection");
217 CFArrayRemoveAllValues(chosen
);
221 CFArrayAppendValue(chosen
, *(choices
[j
].key
));
223 SCPrint(TRUE
, stdout
,
224 CFSTR("invalid %s\n"),
225 options
[optionIndex
].description
!= NULL
? options
[optionIndex
].description
: "selection");
226 CFArrayRemoveAllValues(chosen
);
230 CFRelease(str_array
);
232 if (CFArrayGetCount(chosen
) > 0) {
233 CFDictionarySetValue(newConfiguration
, *(options
[optionIndex
].key
), chosen
);
235 CFDictionaryRemoveValue(newConfiguration
, *(options
[optionIndex
].key
));
239 CFDictionaryRemoveValue(newConfiguration
, *(options
[optionIndex
].key
));
247 SCPrint(TRUE
, stdout
,
248 CFSTR("%s not specified\n"),
249 options
[optionIndex
].description
!= NULL
? options
[optionIndex
].description
: "enable/disable");
253 if ((strcasecmp(argv
[0], "disable") == 0) ||
254 (strcasecmp(argv
[0], "0" ) == 0)) {
255 CFDictionarySetValue(newConfiguration
, *(options
[optionIndex
].key
), CFNumberRef_0
);
256 } else if ((strcasecmp(argv
[0], "enable") == 0) ||
257 (strcasecmp(argv
[0], "1" ) == 0)) {
258 CFDictionarySetValue(newConfiguration
, *(options
[optionIndex
].key
), CFNumberRef_1
);
260 SCPrint(TRUE
, stdout
, CFSTR("invalid value\n"));
269 SCPrint(TRUE
, stdout
,
270 CFSTR("%s not specified\n"),
271 options
[optionIndex
].description
!= NULL
? options
[optionIndex
].description
: "value");
275 if (strlen(argv
[0]) > 0) {
278 num
= _copy_number(argv
[0]);
280 CFDictionarySetValue(newConfiguration
, *(options
[optionIndex
].key
), num
);
283 SCPrint(TRUE
, stdout
, CFSTR("invalid value\n"));
287 CFDictionaryRemoveValue(newConfiguration
, *(options
[optionIndex
].key
));
295 SCPrint(TRUE
, stdout
,
296 CFSTR("%s not specified\n"),
297 options
[optionIndex
].description
!= NULL
? options
[optionIndex
].description
: "value");
301 if (strlen(argv
[0]) > 0) {
304 str
= CFStringCreateWithCString(NULL
, argv
[0], kCFStringEncodingUTF8
);
305 CFDictionarySetValue(newConfiguration
, *(options
[optionIndex
].key
), str
);
308 CFDictionaryRemoveValue(newConfiguration
, *(options
[optionIndex
].key
));
316 SCPrint(TRUE
, stdout
,
317 CFSTR("%s(s) not specified\n"),
318 options
[optionIndex
].description
!= NULL
? options
[optionIndex
].description
: "value");
322 if (strlen(argv
[0]) > 0) {
324 CFArrayRef str_array
;
326 str
= CFStringCreateWithCString(NULL
, argv
[0], kCFStringEncodingUTF8
);
327 str_array
= CFStringCreateArrayBySeparatingStrings(NULL
, str
, CFSTR(","));
330 CFDictionarySetValue(newConfiguration
, *(options
[optionIndex
].key
), str_array
);
331 CFRelease(str_array
);
333 CFDictionaryRemoveValue(newConfiguration
, *(options
[optionIndex
].key
));
341 if (options
[optionIndex
].handler
!= NULL
) {
345 key
= options
[optionIndex
].key
!= NULL
? *(options
[optionIndex
].key
) : NULL
;
346 nArgs
= (*options
[optionIndex
].handler
)(key
,
347 options
[optionIndex
].description
,
348 options
[optionIndex
].info
,
365 /* -------------------- */
372 _show_entity(CFDictionaryRef entity
, CFStringRef prefix
)
375 const void * keys_q
[N_QUICK
];
376 const void ** keys
= keys_q
;
379 CFMutableArrayRef sorted
;
381 n
= CFDictionaryGetCount(entity
);
382 if (n
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
383 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFTypeRef
), 0);
385 CFDictionaryGetKeysAndValues(entity
, keys
, NULL
);
387 array
= CFArrayCreate(NULL
, keys
, n
, &kCFTypeArrayCallBacks
);
388 sorted
= CFArrayCreateMutableCopy(NULL
, n
, array
);
390 CFArraySortValues(sorted
,
392 (CFComparatorFunction
)CFStringCompare
,
396 for (i
= 0; i
< n
; i
++) {
400 key
= CFArrayGetValueAtIndex(sorted
, i
);
401 value
= CFDictionaryGetValue(entity
, key
);
402 if (isA_CFArray(value
)) {
405 str
= CFStringCreateByCombiningStrings(NULL
, value
, CFSTR(", "));
406 SCPrint(TRUE
, stdout
, CFSTR("%@ %@ = (%@)\n"), prefix
, key
, str
);
409 SCPrint(TRUE
, stdout
, CFSTR("%@ %@ = %@\n"), prefix
, key
, value
);
415 if (keys
!= keys_q
) {
416 CFAllocatorDeallocate(NULL
, keys
);
423 /* -------------------- */
427 commitRequired(int argc
, char **argv
, const char *command
)
430 if ((currentInput
!= NULL
) &&
431 isatty(fileno(currentInput
->fp
)) &&
432 ((argc
< 1) || (strcmp(argv
[0], "!") != 0))
434 SCPrint(TRUE
, stdout
,
435 CFSTR("configuration changes have not been committed\n"
436 "use \"commit\" to save changes"));
437 if (command
!= NULL
) {
438 SCPrint(TRUE
, stdout
,
439 CFSTR(" or \"%s !\" to abandon changes"),
442 SCPrint(TRUE
, stdout
, CFSTR("\n"));
446 SCPrint(TRUE
, stdout
, CFSTR("configuration changes abandoned\n"));
460 CFNumberRef_0
= CFNumberCreate(NULL
, kCFNumberIntType
, &zero
);
461 CFNumberRef_1
= CFNumberCreate(NULL
, kCFNumberIntType
, &one
);
469 do_net_open(int argc
, char **argv
)
471 CFStringRef prefsID
= NULL
;
474 if (commitRequired(argc
, argv
, "close")) {
477 do_net_close(0, NULL
);
481 prefsID
= CFStringCreateWithCString(NULL
, argv
[0], kCFStringEncodingUTF8
);
484 prefs
= SCPreferencesCreate(NULL
, CFSTR("scutil --net"), prefsID
);
485 if (prefsID
!= NULL
) CFRelease(prefsID
);
488 SCPrint(TRUE
, stdout
, CFSTR("%s\n"), SCErrorString(SCError()));
494 net_set
= SCNetworkSetCopyCurrent(prefs
);
495 if (net_set
!= NULL
) {
498 setName
= SCNetworkSetGetName(net_set
);
499 if (setName
!= NULL
) {
500 SCPrint(TRUE
, stdout
, CFSTR("set \"%@\" selected\n"), setName
);
502 SCPrint(TRUE
, stdout
,
503 CFSTR("set ID \"%@\" selected\n"),
504 SCNetworkSetGetSetID(net_set
));
514 do_net_commit(int argc
, char **argv
)
516 if (!SCPreferencesCommitChanges(prefs
)) {
517 SCPrint(TRUE
, stdout
, CFSTR("%s\n"), SCErrorString(SCError()));
529 do_net_apply(int argc
, char **argv
)
531 if (!SCPreferencesApplyChanges(prefs
)) {
532 SCPrint(TRUE
, stdout
, CFSTR("%s\n"), SCErrorString(SCError()));
540 do_net_close(int argc
, char **argv
)
542 if (commitRequired(argc
, argv
, "close")) {
546 if (net_interface
!= NULL
) {
547 CFRelease(net_interface
);
548 net_interface
= NULL
;
551 if (net_service
!= NULL
) {
552 CFRelease(net_service
);
556 if (net_protocol
!= NULL
) {
557 CFRelease(net_protocol
);
561 if (net_set
!= NULL
) {
566 if (interfaces
!= NULL
) {
567 CFRelease(interfaces
);
571 if (services
!= NULL
) {
576 if (protocols
!= NULL
) {
577 CFRelease(protocols
);
586 if (new_interfaces
!= NULL
) {
587 CFRelease(new_interfaces
);
588 new_interfaces
= NULL
;
604 do_net_quit(int argc
, char **argv
)
606 if (commitRequired(argc
, argv
, "quit")) {
610 termRequested
= TRUE
;
615 /* -------------------- */
618 typedef void (*net_func
) (int argc
, char **argv
);
620 static const struct {
631 { "interfaces", NULL
, NULL
, NULL
,
632 NULL
, NULL
, show_interfaces
,
635 { "interface", create_interface
, NULL
, NULL
,
636 select_interface
, set_interface
, show_interface
,
639 { "services", NULL
, NULL
, NULL
,
640 NULL
, NULL
, show_services
,
643 { "service", create_service
, disable_service
, enable_service
,
644 select_service
, set_service
, show_service
,
647 { "protocols", NULL
, NULL
, NULL
,
648 NULL
, NULL
, show_protocols
,
651 { "protocol", create_protocol
, disable_protocol
, enable_protocol
,
652 select_protocol
, set_protocol
, show_protocol
,
655 { "sets", NULL
, NULL
, NULL
,
656 NULL
, NULL
, show_sets
,
659 { "set", create_set
, NULL
, NULL
,
660 select_set
, set_set
, show_set
,
664 #define N_NET_KEYS (sizeof(net_keys) / sizeof(net_keys[0]))
668 findNetKey(char *key
)
672 for (i
= 0; i
< (int)N_NET_KEYS
; i
++) {
673 if (strcmp(key
, net_keys
[i
].key
) == 0) {
682 /* -------------------- */
687 do_net_create(int argc
, char **argv
)
698 SCPrint(TRUE
, stderr
, CFSTR("create what?\n"));
702 if (*net_keys
[i
].create
== NULL
) {
703 SCPrint(TRUE
, stderr
, CFSTR("create what?\n"));
706 (*net_keys
[i
].create
)(argc
, argv
);
713 do_net_disable(int argc
, char **argv
)
724 SCPrint(TRUE
, stderr
, CFSTR("disable what?\n"));
728 if (*net_keys
[i
].disable
== NULL
) {
729 SCPrint(TRUE
, stderr
, CFSTR("disable what?\n"));
732 (*net_keys
[i
].disable
)(argc
, argv
);
739 do_net_enable(int argc
, char **argv
)
750 SCPrint(TRUE
, stderr
, CFSTR("enable what?\n"));
754 if (*net_keys
[i
].enable
== NULL
) {
755 SCPrint(TRUE
, stderr
, CFSTR("enable what?\n"));
758 (*net_keys
[i
].enable
)(argc
, argv
);
765 do_net_remove(int argc
, char **argv
)
776 SCPrint(TRUE
, stderr
, CFSTR("remove what?\n"));
780 if (*net_keys
[i
].remove
== NULL
) {
781 SCPrint(TRUE
, stderr
, CFSTR("remove what?\n"));
784 (*net_keys
[i
].remove
)(argc
, argv
);
791 do_net_select(int argc
, char **argv
)
802 SCPrint(TRUE
, stderr
, CFSTR("select what?\n"));
806 if (*net_keys
[i
].select
== NULL
) {
807 SCPrint(TRUE
, stderr
, CFSTR("select what?\n"));
810 (*net_keys
[i
].select
)(argc
, argv
);
817 do_net_set(int argc
, char **argv
)
828 SCPrint(TRUE
, stderr
, CFSTR("set what?\n"));
832 (*net_keys
[i
].set
)(argc
, argv
);
839 do_net_show(int argc
, char **argv
)
850 SCPrint(TRUE
, stderr
, CFSTR("show what?\n"));
854 (*net_keys
[i
].show
)(argc
, argv
);
859 #include "SCPreferencesInternal.h"
864 do_net_snapshot(int argc
, char **argv
)
867 SCPrint(TRUE
, stdout
, CFSTR("network configuration not open\n"));
872 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
874 if (prefsPrivate
->prefs
!= NULL
) {
876 static int n_snapshot
= 0;
880 asprintf(&path
, "/tmp/prefs_snapshot_%d", n_snapshot
++);
881 fd
= open(path
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0644);
884 xmlData
= CFPropertyListCreateXMLData(NULL
, prefsPrivate
->prefs
);
885 if (xmlData
!= NULL
) {
886 (void) write(fd
, CFDataGetBytePtr(xmlData
), CFDataGetLength(xmlData
));
889 SCLog(TRUE
, LOG_ERR
, CFSTR("CFPropertyListCreateXMLData() failed"));
894 SCPrint(TRUE
, stdout
, CFSTR("prefs have not been accessed\n"));