]> git.saurik.com Git - apple/configd.git/blame - scutil.tproj/net_interface.c
configd-453.16.tar.gz
[apple/configd.git] / scutil.tproj / net_interface.c
CommitLineData
dbf6a266 1/*
6bb65964 2 * Copyright (c) 2004-2011 Apple Inc. All rights reserved.
dbf6a266
A
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
17d3ee29 32#include <TargetConditionals.h>
dbf6a266
A
33#include "scutil.h"
34#include "net.h"
edebe297 35#include "prefs.h"
dbf6a266
A
36
37#include <SystemConfiguration/LinkConfiguration.h>
38
39
17d3ee29
A
40#if TARGET_OS_EMBEDDED
41#define INLINE_PASSWORDS_USE_CFSTRING
42#endif // TARGET_OS_EMBEDDED
43
44
a40a14f8
A
45#pragma mark -
46#pragma mark Interface management
dbf6a266
A
47
48
49static CFArrayRef
50_copy_interfaces()
51{
52 CFMutableArrayRef interfaces;
53 CFArrayRef real_interfaces;
54
6bb65964 55 real_interfaces = _SCNetworkInterfaceCopyAllWithPreferences(prefs);
dbf6a266
A
56 if (real_interfaces == NULL) {
57 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
58 return NULL;
59 }
60
61 interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
62
63 // include real interfaces
64 CFArrayAppendArray(interfaces,
65 real_interfaces,
66 CFRangeMake(0, CFArrayGetCount(real_interfaces)));
67 CFRelease(real_interfaces);
68
69 // include pseudo interfaces
6bb65964 70 CFArrayAppendValue(interfaces, kSCNetworkInterfaceLoopback);
dbf6a266
A
71 CFArrayAppendValue(interfaces, kSCNetworkInterfaceIPv4);
72
73 // include interfaces that we have created
74 if (new_interfaces != NULL) {
75 CFArrayAppendArray(interfaces,
76 new_interfaces,
77 CFRangeMake(0, CFArrayGetCount(new_interfaces)));
78 }
79
80 return (CFArrayRef)interfaces;
81}
82
83
84__private_extern__
85SCNetworkInterfaceRef
a40a14f8 86_find_interface(int argc, char **argv, int *nArgs)
dbf6a266
A
87{
88 Boolean allowIndex = TRUE;
89 CFIndex i;
a40a14f8 90 CFArrayRef myInterfaces = interfaces;
dbf6a266
A
91 CFIndex n;
92 CFStringRef select_name = NULL;
93 SCNetworkInterfaceRef selected = NULL;
94
a40a14f8
A
95 if (argc < 1) {
96 SCPrint(TRUE, stdout, CFSTR("no interface specified\n"));
97 return NULL;
98 }
99
100 if (nArgs != NULL) *nArgs = 1;
101
102 if (strcasecmp(argv[0], "$child") == 0) {
dbf6a266
A
103 if (net_interface == NULL) {
104 SCPrint(TRUE, stdout, CFSTR("interface not selected\n"));
105 goto done;
106 }
107
108 selected = SCNetworkInterfaceGetInterface(net_interface);
109 if(selected == NULL) {
110 SCPrint(TRUE, stdout, CFSTR("no child interface\n"));
111 }
112
113 goto done;
a40a14f8 114 } else if (strcasecmp(argv[0], "$service") == 0) {
dbf6a266
A
115 if (net_service == NULL) {
116 SCPrint(TRUE, stdout, CFSTR("service not selected\n"));
117 goto done;
118 }
119
120 selected = SCNetworkServiceGetInterface(net_service);
121 if(selected == NULL) {
122 SCPrint(TRUE, stdout, CFSTR("no interface for service\n"));
123 }
124
125 goto done;
6bb65964
A
126 }
127
17d3ee29 128#if !TARGET_OS_IPHONE
6bb65964 129 else if (strcasecmp(argv[0], "$bond") == 0) {
a40a14f8
A
130 CFStringRef interfaceType;
131
132 if (net_interface == NULL) {
133 SCPrint(TRUE, stdout, CFSTR("interface not selected\n"));
134 goto done;
135 }
136
137 interfaceType = SCNetworkInterfaceGetInterfaceType(net_interface);
138 if (!CFEqual(interfaceType, kSCNetworkInterfaceTypeBond)) {
139 SCPrint(TRUE, stdout, CFSTR("interface not Bond\n"));
140 goto done;
141 }
142
143 if (argc < 2) {
144 SCPrint(TRUE, stdout, CFSTR("no member interface specified\n"));
145 return NULL;
146 }
147 argv++;
148 argc--;
149 if (nArgs != NULL) *nArgs += 1;
150
151 myInterfaces = SCBondInterfaceGetMemberInterfaces(net_interface);
152 if (myInterfaces == NULL) {
153 SCPrint(TRUE, stdout, CFSTR("no member interfaces\n"));
154 goto done;
155 }
156 allowIndex = FALSE;
6bb65964 157 }
17d3ee29 158#endif // !TARGET_OS_IPHONE
6bb65964
A
159
160 else if (strcasecmp(argv[0], "$bridge") == 0) {
161 CFStringRef interfaceType;
162
163 if (net_interface == NULL) {
164 SCPrint(TRUE, stdout, CFSTR("interface not selected\n"));
165 goto done;
166 }
167
168 interfaceType = SCNetworkInterfaceGetInterfaceType(net_interface);
169 if (!CFEqual(interfaceType, kSCNetworkInterfaceTypeBridge)) {
170 SCPrint(TRUE, stdout, CFSTR("interface not Bridge\n"));
171 goto done;
172 }
173
174 if (argc < 2) {
175 SCPrint(TRUE, stdout, CFSTR("no member interface specified\n"));
176 return NULL;
177 }
178 argv++;
179 argc--;
180 if (nArgs != NULL) *nArgs += 1;
181
182 myInterfaces = SCBridgeInterfaceGetMemberInterfaces(net_interface);
183 if (myInterfaces == NULL) {
184 SCPrint(TRUE, stdout, CFSTR("no member interfaces\n"));
185 goto done;
186 }
187 allowIndex = FALSE;
188 }
189
190 else if (strcasecmp(argv[0], "$vlan") == 0) {
a40a14f8
A
191 CFStringRef interfaceType;
192
193 if (net_interface == NULL) {
194 SCPrint(TRUE, stdout, CFSTR("interface not selected\n"));
195 goto done;
196 }
197
198 interfaceType = SCNetworkInterfaceGetInterfaceType(net_interface);
199 if (!CFEqual(interfaceType, kSCNetworkInterfaceTypeVLAN)) {
200 SCPrint(TRUE, stdout, CFSTR("interface not VLAN\n"));
201 goto done;
202 }
203
204 selected = SCVLANInterfaceGetPhysicalInterface(net_interface);
205 if(selected == NULL) {
206 SCPrint(TRUE, stdout, CFSTR("no physical interface\n"));
207 }
208
209 goto done;
dbf6a266
A
210 }
211
a40a14f8 212 if ((myInterfaces == NULL) && (interfaces == NULL)) {
dbf6a266
A
213 interfaces = _copy_interfaces();
214 if (interfaces == NULL) {
215 return NULL;
216 }
a40a14f8 217 myInterfaces = interfaces;
dbf6a266
A
218 allowIndex = FALSE;
219 }
220
221 // try to select the interface by its display name
222
a40a14f8 223 select_name = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
dbf6a266 224
a40a14f8 225 n = (myInterfaces != NULL) ? CFArrayGetCount(myInterfaces) : 0;
dbf6a266
A
226 for (i = 0; i < n; i++) {
227 SCNetworkInterfaceRef interface;
228 CFStringRef interfaceName;
229
a40a14f8 230 interface = CFArrayGetValueAtIndex(myInterfaces, i);
dbf6a266
A
231 interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(interface);
232 if ((interfaceName != NULL) && CFEqual(select_name, interfaceName)) {
233 if (selected == NULL) {
234 selected = interface;
235 } else {
236 // if multiple interfaces match
237 selected = NULL;
238 SCPrint(TRUE, stdout, CFSTR("multiple interfaces match\n"));
239 goto done;
240 }
241 }
242 }
243
244 if (selected != NULL) {
245 goto done;
246 }
247
248 // try to select the interface by its BSD name
249
250 for (i = 0; i < n; i++) {
251 SCNetworkInterfaceRef interface;
252 CFStringRef bsd_name = NULL;
253
a40a14f8 254 interface = CFArrayGetValueAtIndex(myInterfaces, i);
edebe297
A
255 while ((interface != NULL) && (bsd_name == NULL)) {
256 bsd_name = SCNetworkInterfaceGetBSDName(interface);
257 if (bsd_name == NULL) {
258 interface = SCNetworkInterfaceGetInterface(interface);
259 }
260 }
dbf6a266
A
261
262 if ((bsd_name != NULL) && CFEqual(select_name, bsd_name)) {
263 if (selected == NULL) {
264 selected = interface;
265 } else {
266 // if multiple interfaces match
267 selected = NULL;
268 SCPrint(TRUE, stdout, CFSTR("multiple interfaces match\n"));
269 goto done;
270 }
271 }
272 }
273
274 if (selected != NULL) {
275 goto done;
276 }
277
278 // try to select the interface by its interface type
279
280 for (i = 0; i < n; i++) {
281 SCNetworkInterfaceRef interface;
282 CFStringRef interfaceType;
283
a40a14f8 284 interface = CFArrayGetValueAtIndex(myInterfaces, i);
dbf6a266
A
285 interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
286 if (CFEqual(select_name, interfaceType)) {
287 if (selected == NULL) {
288 selected = interface;
289 } else {
290 // if multiple interfaces match
291 selected = NULL;
292 SCPrint(TRUE, stdout, CFSTR("multiple interfaces match\n"));
293 goto done;
294 }
295 }
296 }
297
298 if (selected != NULL) {
299 goto done;
300 }
301
302 if (allowIndex) {
303 char *end;
a40a14f8 304 char *str = argv[0];
dbf6a266
A
305 long val;
306
307 // try to select the interface by its index
308
309 errno = 0;
310 val = strtol(str, &end, 10);
311 if ((*str != '\0') &&
312 ((*end == '\0') || (*end == '.')) &&
313 (errno == 0)) {
314 if ((val > 0) && (val <= n)) {
a40a14f8 315 selected = CFArrayGetValueAtIndex(myInterfaces, val - 1);
dbf6a266
A
316
317 if (*end == '.') {
318 str = end + 1;
319 val = strtol(str, &end, 10);
320 if ((*str != '\0') && (*end == '\0') && (errno == 0)) {
321 while (val-- > 0) {
322 selected = SCNetworkInterfaceGetInterface(selected);
323 if (selected == NULL) {
324 break;
325 }
326 }
327 }
328 }
329 }
330 }
331 }
332
333 if (selected != NULL) {
334 goto done;
335 }
336
337 SCPrint(TRUE, stdout, CFSTR("no match\n"));
338
339 done :
340
341 if (select_name != NULL) CFRelease(select_name);
342 return selected;
343}
344
345
346/* -------------------- */
347
348
349__private_extern__
350void
351create_interface(int argc, char **argv)
352{
353 SCNetworkInterfaceRef interface;
354 CFStringRef interfaceName;
355 CFStringRef interfaceType;
356 SCNetworkInterfaceRef new_interface;
357
358 if (argc < 1) {
359 SCPrint(TRUE, stdout, CFSTR("what interface type?\n"));
360 return;
361 }
362
363 interfaceType = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
a40a14f8
A
364 argv++;
365 argc--;
dbf6a266 366
a40a14f8
A
367 if (CFEqual(interfaceType, kSCNetworkInterfaceTypeBond)) {
368 SCPrint(TRUE, stdout, CFSTR("bond creation not yet supported\n"));
369 goto done;
370 }
6bb65964
A
371 if (CFEqual(interfaceType, kSCNetworkInterfaceTypeBridge)) {
372 SCPrint(TRUE, stdout, CFSTR("bridge creation not yet supported\n"));
373 goto done;
374 }
dbf6a266 375 if (CFEqual(interfaceType, kSCNetworkInterfaceTypeVLAN)) {
a40a14f8
A
376 SCPrint(TRUE, stdout, CFSTR("vlan creation not yet supported\n"));
377 goto done;
378 }
dbf6a266 379
a40a14f8
A
380 if (argc < 1) {
381 if (net_interface == NULL) {
382 SCPrint(TRUE, stdout, CFSTR("no network interface selected\n"));
383 goto done;
dbf6a266
A
384 }
385
a40a14f8
A
386 interface = net_interface;
387 } else {
388 interface = _find_interface(argc, argv, NULL);
389 }
dbf6a266 390
a40a14f8
A
391 if (interface == NULL) {
392 goto done;
393 }
394
395 new_interface = SCNetworkInterfaceCreateWithInterface(interface, interfaceType);
396 if (new_interface == NULL) {
397 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
398 goto done;
dbf6a266
A
399 }
400
401 if (new_interfaces == NULL) {
402 new_interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
403 }
404 CFArrayAppendValue(new_interfaces, new_interface);
405
406 if (net_interface != NULL) CFRelease(net_interface);
407 net_interface = new_interface;
408
409 interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(net_interface);
410 if (interfaceName == NULL) {
411 interfaceName = SCNetworkInterfaceGetBSDName(net_interface);
412 }
413 if (interfaceName == NULL) {
414 interfaceName = SCNetworkInterfaceGetInterfaceType(net_interface);
415 }
416 SCPrint(TRUE, stdout, CFSTR("interface \"%@\" created and selected\n"), interfaceName);
417
418 done :
419
420 CFRelease(interfaceType);
421 return;
422}
423
424
425/* -------------------- */
426
427
428__private_extern__
429void
430select_interface(int argc, char **argv)
431{
432 SCNetworkInterfaceRef interface;
433
a40a14f8 434 interface = _find_interface(argc, argv, NULL);
dbf6a266
A
435 if (interface != NULL) {
436 CFStringRef interfaceName;
437
438 if (net_interface != NULL) CFRelease(net_interface);
439 net_interface = CFRetain(interface);
440
441 interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(interface);
442 if (interfaceName == NULL) {
443 interfaceName = SCNetworkInterfaceGetBSDName(interface);
444 }
445 if (interfaceName == NULL) {
446 interfaceName = SCNetworkInterfaceGetInterfaceType(interface);
447 }
448
449 SCPrint(TRUE, stdout, CFSTR("interface \"%@\" selected\n"), interfaceName);
450 }
451
452 return;
453}
454
455
456/* -------------------- */
457
458
459__private_extern__
460void
461_show_interface(SCNetworkInterfaceRef interface, CFStringRef prefix, Boolean showChild)
462{
463 CFDictionaryRef configuration;
464 CFStringRef if_bsd_name;
465 CFStringRef if_localized_name;
466 CFStringRef if_mac_address;
467 CFStringRef if_type;
468 CFArrayRef supported;
469
470 if_localized_name = SCNetworkInterfaceGetLocalizedDisplayName(interface);
471 if (if_localized_name != NULL) {
472 SCPrint(TRUE, stdout, CFSTR("%@ name = %@\n"), prefix, if_localized_name);
473 }
474
475 if_bsd_name = SCNetworkInterfaceGetBSDName(interface);
476 if (if_bsd_name != NULL) {
477 SCPrint(TRUE, stdout, CFSTR("%@ interface name = %@\n"), prefix, if_bsd_name);
478 }
479
480 if_type = SCNetworkInterfaceGetInterfaceType(interface);
481 SCPrint(TRUE, stdout, CFSTR("%@ type = %@\n"), prefix, if_type);
482
483 if_mac_address = SCNetworkInterfaceGetHardwareAddressString(interface);
484 if (if_mac_address != NULL) {
485 SCPrint(TRUE, stdout, CFSTR("%@ address = %@\n"), prefix, if_mac_address);
486 }
487
488 configuration = SCNetworkInterfaceGetConfiguration(interface);
489 if ((configuration != NULL) &&
490 CFDictionaryContainsKey(configuration, kSCResvInactive)) {
491 configuration = NULL;
492 }
493
494 if (if_bsd_name != NULL) {
495 CFArrayRef available;
496 CFDictionaryRef active;
6bb65964 497 CFDictionaryRef cap_current;
dbf6a266
A
498 int mtu_cur;
499 int mtu_min;
500 int mtu_max;
501
6bb65964
A
502 cap_current = SCNetworkInterfaceCopyCapability(interface, NULL);
503 if (cap_current != NULL) {
504 CFIndex i;
505 CFArrayRef cap_names;
506 CFMutableArrayRef cap_sorted;
507 const void **keys;
508 CFIndex n;
509
510 n = CFDictionaryGetCount(cap_current);
511 keys = CFAllocatorAllocate(NULL, n * sizeof(CFStringRef), 0);
512 CFDictionaryGetKeysAndValues(cap_current, keys, NULL);
513 cap_names = CFArrayCreate(NULL, keys, n, &kCFTypeArrayCallBacks);
514 CFAllocatorDeallocate(NULL, keys);
515
516 cap_sorted = CFArrayCreateMutableCopy(NULL, 0, cap_names);
517 CFRelease(cap_names);
518
519 CFArraySortValues(cap_sorted, CFRangeMake(0, n), (CFComparatorFunction)CFStringCompare, NULL);
520
521 SCPrint(TRUE, stdout, CFSTR("%@ capabilities = "), prefix);
522 for (i = 0; i < n; i++) {
523 CFStringRef cap_name;
524 int cap_val;
525 CFNumberRef val = NULL;
526
527 cap_name = CFArrayGetValueAtIndex(cap_sorted, i);
528 if (configuration != NULL) {
529 val = CFDictionaryGetValue(configuration, cap_name);
530 }
531 if (!isA_CFNumber(val)) {
532 val = CFDictionaryGetValue(cap_current, cap_name);
533 }
534
535 SCPrint(TRUE, stdout, CFSTR("%s%@%c"),
536 (i == 0) ? "" : ",",
537 cap_name,
538 (CFNumberGetValue(val, kCFNumberIntType, &cap_val) &&
539 (cap_val != 0)) ? '+' : '-');
540 }
541 SCPrint(TRUE, stdout, CFSTR("\n"));
542
543 CFRelease(cap_sorted);
544 CFRelease(cap_current);
545 }
546
edebe297 547 if (SCNetworkInterfaceCopyMTU(interface, &mtu_cur, &mtu_min, &mtu_max)) {
dbf6a266
A
548 char isCurrent = '*';
549
550 if (configuration != NULL) {
551 int mtu_req;
552 CFNumberRef num;
553
554 num = CFDictionaryGetValue(configuration, kSCPropNetEthernetMTU);
555 if (isA_CFNumber(num)) {
556 CFNumberGetValue(num, kCFNumberIntType, &mtu_req);
557 if (mtu_cur != mtu_req) {
558 mtu_cur = mtu_req;
559 isCurrent = ' ';
560 }
561 }
562 }
563
a40a14f8 564 SCPrint(TRUE, stdout, CFSTR("%@ mtu %c = %d (%d < n < %d)\n"),
dbf6a266
A
565 prefix,
566 isCurrent,
567 mtu_cur,
568 mtu_min,
569 mtu_max);
570 }
571
edebe297 572 if (SCNetworkInterfaceCopyMediaOptions(interface, NULL, &active, &available, TRUE)) {
dbf6a266
A
573 char isCurrent = ' ';
574 CFArrayRef options = NULL;
575 CFArrayRef options_req = NULL;
576 CFStringRef subtype = NULL;
577 CFStringRef subtype_req = NULL;
578
579 if (configuration != NULL) {
580 subtype_req = CFDictionaryGetValue(configuration, kSCPropNetEthernetMediaSubType);
581 options_req = CFDictionaryGetValue(configuration, kSCPropNetEthernetMediaOptions);
582 }
583
584 if (subtype_req == NULL) {
585 subtype_req = CFSTR("autoselect");
586 }
587
588 if (active != NULL) {
589 subtype = CFDictionaryGetValue(active, kSCPropNetEthernetMediaSubType);
590 options = CFDictionaryGetValue(active, kSCPropNetEthernetMediaOptions);
591 }
592
593 if (subtype != NULL) {
594 if (((subtype_req != NULL) &&
595 CFEqual(subtype, subtype_req)) &&
596 ((options == options_req) ||
597 ((options != NULL) &&
598 (options_req != NULL) &&
599 CFEqual(options, options_req)))
600 ) {
601 isCurrent = '*';
602 } else if ((subtype_req == NULL) ||
603 ((subtype_req != NULL) &&
604 CFEqual(subtype_req, CFSTR("autoselect")))) {
605 // if requested subtype not specified or "autoselect"
606 isCurrent = '*';
607 }
608 }
609
610 if (subtype_req != NULL) {
611 SCPrint(TRUE, stdout, CFSTR("%@ media %c = %@"),
612 prefix,
613 isCurrent,
614 subtype_req);
615
616 if ((options_req != NULL) &&
617 (CFArrayGetCount(options_req) > 0)) {
618 CFStringRef options_str;
619
620 options_str = CFStringCreateByCombiningStrings(NULL, options_req, CFSTR(","));
621 SCPrint(TRUE, stdout, CFSTR(" <%@>"), options_str);
622 CFRelease(options_str);
623 }
624
625 SCPrint(TRUE, stdout, CFSTR("\n"));
626 }
627
628 SCPrint(TRUE, stdout, CFSTR("\n"));
629
630 if (available != NULL) {
631 CFIndex i;
632 CFIndex n_subtypes;
633 CFArrayRef subtypes;
634
edebe297 635 subtypes = SCNetworkInterfaceCopyMediaSubTypes(available);
dbf6a266
A
636 n_subtypes = (subtypes != NULL) ? CFArrayGetCount(subtypes) : 0;
637 for (i = 0; i < n_subtypes; i++) {
638 CFIndex j;
639 CFIndex n_subtype_options;
640 CFStringRef subtype;
641 CFArrayRef subtype_options;
642
643 subtype = CFArrayGetValueAtIndex(subtypes, i);
edebe297 644 subtype_options = SCNetworkInterfaceCopyMediaSubTypeOptions(available, subtype);
dbf6a266
A
645 n_subtype_options = (subtype_options != NULL) ? CFArrayGetCount(subtype_options) : 0;
646 for (j = 0; j < n_subtype_options; j++) {
647 char isCurrent = ' ';
648 CFArrayRef options;
649
650 options = CFArrayGetValueAtIndex(subtype_options, j);
651
652 if (((subtype_req != NULL) &&
653 CFEqual(subtype, subtype_req)) &&
654 ((options == options_req) ||
655 ((options != NULL) &&
656 (options_req != NULL) &&
657 CFEqual(options, options_req)))
658 ) {
659 isCurrent = '*';
660 }
661
662 SCPrint(TRUE, stdout, CFSTR("%@ %s %c = %@"),
663 prefix,
664 ((i == 0) && (j == 0)) ? "supported media" : " ",
665 isCurrent,
666 subtype);
667
668 if ((options != NULL) &&
669 (CFArrayGetCount(options) > 0)) {
670 CFStringRef options_str;
671
672 options_str = CFStringCreateByCombiningStrings(NULL, options, CFSTR(","));
673 SCPrint(TRUE, stdout, CFSTR(" <%@>"), options_str);
674 CFRelease(options_str);
675 }
676
677 SCPrint(TRUE, stdout, CFSTR("\n"));
678 }
6bb65964 679 if (subtype_options != NULL) CFRelease(subtype_options);
dbf6a266 680 }
a40a14f8 681 if (subtypes != NULL) CFRelease(subtypes);
dbf6a266
A
682 }
683 } else {
684 SCPrint(TRUE, stdout, CFSTR("\n"));
685 }
686 }
687
688 supported = SCNetworkInterfaceGetSupportedInterfaceTypes(interface);
689 SCPrint(TRUE, stdout, CFSTR("%@ supported interfaces = "), prefix);
690 if (supported != NULL) {
691 CFIndex i;
692 CFIndex n = CFArrayGetCount(supported);
693
694 for (i = 0; i < n; i++) {
695 SCPrint(TRUE, stdout, CFSTR("%s%@"),
696 (i == 0) ? "" : ", ",
697 CFArrayGetValueAtIndex(supported, i));
698 }
699 }
700 SCPrint(TRUE, stdout, CFSTR("\n"));
701
702 supported = SCNetworkInterfaceGetSupportedProtocolTypes(interface);
703 SCPrint(TRUE, stdout, CFSTR("%@ supported protocols = "), prefix);
704 if (supported != NULL) {
705 CFIndex i;
706 CFIndex n = CFArrayGetCount(supported);
707
708 for (i = 0; i < n; i++) {
709 SCPrint(TRUE, stdout, CFSTR("%s%@"),
710 (i == 0) ? "" : ", ",
711 CFArrayGetValueAtIndex(supported, i));
712 }
713 }
714 SCPrint(TRUE, stdout, CFSTR("\n"));
715
716 if (configuration != NULL) {
717 CFMutableDictionaryRef effective;
718
719 effective = CFDictionaryCreateMutableCopy(NULL, 0, configuration);
720
721 // remove known (and already reported) interface configuration keys
722 if (CFDictionaryContainsKey(effective, kSCResvInactive)) {
723 CFDictionaryRemoveAllValues(effective);
724 }
725 CFDictionaryRemoveValue(effective, kSCPropNetEthernetMTU);
726 CFDictionaryRemoveValue(effective, kSCPropNetEthernetMediaSubType);
727 CFDictionaryRemoveValue(effective, kSCPropNetEthernetMediaOptions);
728
729 if (CFDictionaryGetCount(effective) > 0) {
730 SCPrint(TRUE, stdout, CFSTR("\n%@ per-interface configuration\n"), prefix);
edebe297 731 _show_entity(effective, prefix);
dbf6a266
A
732 }
733
734 CFRelease(effective);
735 }
736
a40a14f8
A
737 if (CFEqual(if_type, kSCNetworkInterfaceTypePPP)) {
738 SCNetworkInterfaceRef childInterface;
739
740 childInterface = SCNetworkInterfaceGetInterface(interface);
741 if (childInterface != NULL) {
742 CFStringRef childInterfaceType;
743
744 childInterfaceType = SCNetworkInterfaceGetInterfaceType(childInterface);
745 if (CFEqual(childInterfaceType, kSCNetworkInterfaceTypeL2TP)) {
746 CFDictionaryRef ipsec_configuration;
747
748 ipsec_configuration = SCNetworkInterfaceGetExtendedConfiguration(interface, kSCEntNetIPSec);
749 if (isA_CFDictionary(ipsec_configuration) &&
750 (CFDictionaryGetCount(ipsec_configuration) > 0)) {
751 SCPrint(TRUE, stdout, CFSTR("\n%@ per-interface IPSec configuration\n"), prefix);
752 _show_entity(ipsec_configuration, prefix);
753 }
754 }
755 }
756 }
757
dbf6a266
A
758 if (_sc_debug) {
759 SCPrint(TRUE, stdout, CFSTR("\n%@\n"), interface);
760 }
761
762 interface = SCNetworkInterfaceGetInterface(interface);
763 if (interface != NULL) {
764 CFStringRef newPrefix;
765
766 newPrefix = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@ "), prefix);
767 SCPrint(TRUE, stdout, CFSTR("\n%@child interface\n"), newPrefix);
768 _show_interface(interface, newPrefix, showChild);
769 CFRelease(newPrefix);
770 }
771
772 return;
773}
774
775
776/* -------------------- */
777
778
d6c893b2 779static Boolean
edebe297 780validateMediaOptions(SCNetworkInterfaceRef interface, CFMutableDictionaryRef newConfiguration)
d6c893b2
A
781{
782 Boolean ok = TRUE;
783 CFNumberRef mtu;
784 CFArrayRef options;
785 CFStringRef subtype;
786
787 mtu = CFDictionaryGetValue(newConfiguration, kSCPropNetEthernetMTU);
788 if (isA_CFNumber(mtu)) {
789 int mtu_max;
790 int mtu_min;
791 int mtu_val;
792
edebe297 793 if (!SCNetworkInterfaceCopyMTU(interface, NULL, &mtu_min, &mtu_max)) {
d6c893b2
A
794 SCPrint(TRUE, stdout, CFSTR("cannot set MTU\n"));
795 return FALSE;
796 }
797
798 if (!CFNumberGetValue(mtu, kCFNumberIntType, &mtu_val) ||
799 (mtu_val < mtu_min) ||
800 (mtu_val > mtu_max)) {
801 SCPrint(TRUE, stdout, CFSTR("mtu out of range\n"));
802 return FALSE;
803 }
804 }
805
806 subtype = CFDictionaryGetValue(newConfiguration, kSCPropNetEthernetMediaSubType);
807 options = CFDictionaryGetValue(newConfiguration, kSCPropNetEthernetMediaOptions);
808
809 if (subtype != NULL) {
810 CFArrayRef available = NULL;
811 CFArrayRef config_options = options;
812 CFArrayRef subtypes = NULL;
813 CFArrayRef subtype_options = NULL;
814
815 ok = FALSE;
816
817 if (options == NULL) {
818 config_options = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks);
819 }
820
edebe297 821 if (!SCNetworkInterfaceCopyMediaOptions(interface, NULL, NULL, &available, FALSE)) {
d6c893b2
A
822 SCPrint(TRUE, stdout, CFSTR("media type / options not available\n"));
823 goto checked;
824 }
825
826 if (available == NULL) {
827 goto checked;
828 }
829
edebe297 830 subtypes = SCNetworkInterfaceCopyMediaSubTypes(available);
d6c893b2
A
831 if ((subtypes == NULL) ||
832 !CFArrayContainsValue(subtypes,
833 CFRangeMake(0, CFArrayGetCount(subtypes)),
834 subtype)) {
835 SCPrint(TRUE, stdout, CFSTR("media type not valid\n"));
836 goto checked;
837 }
838
edebe297 839 subtype_options = SCNetworkInterfaceCopyMediaSubTypeOptions(available, subtype);
d6c893b2
A
840 if ((subtype_options == NULL) ||
841 !CFArrayContainsValue(subtype_options,
842 CFRangeMake(0, CFArrayGetCount(subtype_options)),
843 config_options)) {
844 SCPrint(TRUE, stdout, CFSTR("media options not valid for \"%@\"\n"), subtype);
845 goto checked;
846 }
847
848 if (options == NULL) {
849 CFDictionarySetValue(newConfiguration, kSCPropNetEthernetMediaOptions, config_options);
850 }
851
852 ok = TRUE;
853
854 checked :
855
856 if (available != NULL) CFRelease(available);
857 if (subtypes != NULL) CFRelease(subtypes);
858 if (subtype_options != NULL) CFRelease(subtype_options);
859 if (options == NULL) CFRelease(config_options);
860 } else {
861 if (options != NULL) {
862 SCPrint(TRUE, stdout, CFSTR("media type and options must both be specified\n"));
863 return FALSE;
864 }
865 }
866
867 return ok;
868}
869
870
871/* -------------------- */
872
873
dbf6a266
A
874__private_extern__
875void
876show_interfaces(int argc, char **argv)
877{
878 CFIndex i;
879 CFIndex n;
880
881 if (interfaces != NULL) CFRelease(interfaces);
882 interfaces = _copy_interfaces();
883 if (interfaces == NULL) {
884 return;
885 }
886
887 n = CFArrayGetCount(interfaces);
888 for (i = 0; i < n; i++) {
889 CFIndex childIndex = 0;
890 SCNetworkInterfaceRef interface;
891
892 interface = CFArrayGetValueAtIndex(interfaces, i);
893 do {
894 CFStringRef interfaceName;
895 char isSelected;
896
897 interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(interface);
898 if (interfaceName == NULL) {
899 interfaceName = SCNetworkInterfaceGetBSDName(interface);
900 }
901 if (interfaceName == NULL) {
902 interfaceName = SCNetworkInterfaceGetInterfaceType(interface);
903 }
904
905 isSelected = ' ';
906 if ((net_interface != NULL) && CFEqual(interface, net_interface)) {
907 isSelected = '>';
908 }
909
910 if (childIndex == 0) {
911 SCPrint(TRUE, stdout, CFSTR("%c%2d: %@\n"),
912 isSelected,
913 i + 1,
914 interfaceName);
915 } else {
916 SCPrint(TRUE, stdout, CFSTR("%c%2d.%d: %@\n"),
917 isSelected,
918 i + 1,
919 childIndex,
920 interfaceName);
921 }
922
923 interface = SCNetworkInterfaceGetInterface(interface);
924 childIndex++;
925 } while (interface != NULL);
926 }
927
928 return;
929}
930
931
6bb65964 932/* -------------------- */
a40a14f8
A
933
934
17d3ee29
A
935static int
936__doRank(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
937{
938 SCNetworkInterfaceRef interface;
939 CFStringRef interfaceName;
940 Boolean ok = FALSE;
941 SCNetworkServicePrimaryRank rank = kSCNetworkServicePrimaryRankDefault;
942 SCDynamicStoreRef store;
943
944 if (argc < 1) {
945 SCPrint(TRUE, stdout,
946 CFSTR("%s not specified\n"),
947 description != NULL ? description : "rank");
948 return -1;
949 }
950
951 if (strlen(argv[0]) == 0) {
952 rank = kSCNetworkServicePrimaryRankDefault;
953 } else if ((strcasecmp(argv[0], "First") == 0)) {
954 rank = kSCNetworkServicePrimaryRankFirst;
955 } else if ((strcasecmp(argv[0], "Last") == 0)) {
956 rank = kSCNetworkServicePrimaryRankLast;
957 } else if ((strcasecmp(argv[0], "Never") == 0)) {
958 rank = kSCNetworkServicePrimaryRankNever;
959 } else {
960 SCPrint(TRUE, stdout, CFSTR("invalid rank\n"));
961 return -1;
962 }
963
964 interfaceName = SCNetworkInterfaceGetBSDName(net_interface);
965 if (interfaceName == NULL) {
966 SCPrint(TRUE, stdout, CFSTR("no BSD interface\n"));
967 return FALSE;
968 }
969
970 store = SCDynamicStoreCreate(NULL, CFSTR("scutil --net"), NULL, NULL);
971 interface = _SCNetworkInterfaceCopyActive(store, interfaceName);
972 CFRelease(store);
973 if (interface == NULL) {
974 SCPrint(TRUE, stdout, CFSTR("No active interface\n"));
975 return -1;
976 }
977
978 ok = SCNetworkInterfaceSetPrimaryRank(interface, rank);
979 CFRelease(interface);
980 if (!ok) {
981 SCPrint(TRUE, stdout, CFSTR("could not update per-interface rank\n"));
982 return -1;
983 }
984
985 return 1;
986}
987
988
989/* -------------------- */
990
991
6bb65964
A
992static void
993_replaceOne(const void *key, const void *value, void *context)
994{
995 CFMutableDictionaryRef newConfiguration = (CFMutableDictionaryRef)context;
996
997 CFDictionarySetValue(newConfiguration, key, value);
998 return;
999}
1000
1001
1002static void
1003updateInterfaceConfiguration(CFMutableDictionaryRef newConfiguration)
1004{
1005 CFDictionaryRef configuration;
1006
1007 CFDictionaryRemoveAllValues(newConfiguration);
1008
1009 configuration = SCNetworkInterfaceGetConfiguration(net_interface);
1010 if (configuration != NULL) {
1011 CFDictionaryApplyFunction(configuration, _replaceOne, (void *)newConfiguration);
1012 }
1013
1014 return;
1015}
1016
1017
1018#pragma mark -
1019#pragma mark Bond options
dbf6a266
A
1020
1021
edebe297
A
1022static options bondOptions[] = {
1023 { "mtu" , NULL, isNumber , &kSCPropNetEthernetMTU , NULL, NULL },
6bb65964
A
1024 // xxx { "+device" , ... },
1025 // xxx { "-device" , ... },
edebe297
A
1026
1027 { "?" , NULL , isHelp , NULL , NULL,
6bb65964
A
1028 "\nBond configuration commands\n\n"
1029 " set interface [mtu n] [media type] [mediaopts opts]\n"
edebe297
A
1030 }
1031};
1032#define N_BOND_OPTIONS (sizeof(bondOptions) / sizeof(bondOptions[0]))
1033
1034
dbf6a266
A
1035static Boolean
1036set_interface_bond(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1037{
edebe297
A
1038 CFStringRef interfaceName;
1039 Boolean ok;
1040
1041 interfaceName = SCNetworkInterfaceGetBSDName(net_interface);
1042 if (interfaceName == NULL) {
1043 SCPrint(TRUE, stdout, CFSTR("no BSD interface\n"));
1044 return FALSE;
1045 }
1046
1047 ok = _process_options(bondOptions, N_BOND_OPTIONS, argc, argv, newConfiguration);
1048 if (ok) {
1049 // validate configuration
1050 if (!validateMediaOptions(net_interface, newConfiguration)) {
1051 return FALSE;
1052 }
1053 }
1054
1055 return ok;
dbf6a266
A
1056}
1057
1058
6bb65964
A
1059#pragma mark -
1060#pragma mark Bridge options
1061
1062
1063static options bridgeOptions[] = {
1064 { "mtu" , NULL, isNumber , &kSCPropNetEthernetMTU , NULL, NULL },
1065// xxx { "+device" , ... },
1066// xxx { "-device" , ... },
1067
1068 { "?" , NULL , isHelp , NULL , NULL,
1069 "\nBridge configuration commands\n\n"
1070 " set interface [mtu n] [media type] [mediaopts opts]\n"
1071 }
1072};
1073#define N_BRIDGE_OPTIONS (sizeof(bridgeOptions) / sizeof(bridgeOptions[0]))
1074
1075
1076static Boolean
1077set_interface_bridge(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1078{
1079 CFStringRef interfaceName;
1080 Boolean ok;
1081
1082 interfaceName = SCNetworkInterfaceGetBSDName(net_interface);
1083 if (interfaceName == NULL) {
1084 SCPrint(TRUE, stdout, CFSTR("no BSD interface\n"));
1085 return FALSE;
1086 }
1087
1088 ok = _process_options(bridgeOptions, N_BRIDGE_OPTIONS, argc, argv, newConfiguration);
1089 if (ok) {
1090 // validate configuration
1091 if (!validateMediaOptions(net_interface, newConfiguration)) {
1092 return FALSE;
1093 }
1094 }
1095
1096 return ok;
1097}
a40a14f8
A
1098
1099
1100#pragma mark -
1101#pragma mark AirPort options
dbf6a266
A
1102
1103
d6c893b2
A
1104static options airportOptions[] = {
1105 { "mtu" , NULL, isNumber , &kSCPropNetEthernetMTU , NULL, NULL },
1106 { "media" , NULL, isString , &kSCPropNetEthernetMediaSubType, NULL, NULL },
1107 { "mediaopt" , NULL, isStringArray, &kSCPropNetEthernetMediaOptions, NULL, NULL },
1108
17d3ee29
A
1109 { "rank" , NULL, isOther , NULL , __doRank, NULL },
1110
1111 { "?" , NULL, isHelp , NULL , NULL,
d6c893b2
A
1112 "\nAirPort configuration commands\n\n"
1113 " set interface [mtu n] [media type] [mediaopts opts]\n"
1114 }
1115};
1116#define N_AIRPORT_OPTIONS (sizeof(airportOptions) / sizeof(airportOptions[0]))
1117
1118
dbf6a266
A
1119static Boolean
1120set_interface_airport(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1121{
d6c893b2
A
1122 CFStringRef interfaceName;
1123 Boolean ok;
1124
1125 interfaceName = SCNetworkInterfaceGetBSDName(net_interface);
1126 if (interfaceName == NULL) {
1127 SCPrint(TRUE, stdout, CFSTR("no BSD interface\n"));
1128 return FALSE;
1129 }
1130
1131 ok = _process_options(airportOptions, N_AIRPORT_OPTIONS, argc, argv, newConfiguration);
1132 if (ok) {
1133 // validate configuration
edebe297 1134 if (!validateMediaOptions(net_interface, newConfiguration)) {
d6c893b2
A
1135 return FALSE;
1136 }
1137 }
1138
1139 return ok;
dbf6a266
A
1140}
1141
1142
a40a14f8
A
1143#pragma mark -
1144#pragma mark Ethernet options
dbf6a266
A
1145
1146
6bb65964
A
1147static int
1148__doCapability(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1149{
1150 Boolean ok = FALSE;
1151
1152 if (argc < 1) {
1153 SCPrint(TRUE, stdout,
1154 CFSTR("%s not specified\n"),
1155 description != NULL ? description : "enable/disable");
1156 return -1;
1157 }
1158
1159 if (strlen(argv[0]) == 0) {
1160 ok = SCNetworkInterfaceSetCapability(net_interface, key, NULL);
1161 } else if ((strcasecmp(argv[0], "disable") == 0) ||
1162 (strcasecmp(argv[0], "no" ) == 0) ||
1163 (strcasecmp(argv[0], "off" ) == 0) ||
1164 (strcasecmp(argv[0], "0" ) == 0)) {
1165 ok = SCNetworkInterfaceSetCapability(net_interface, key, CFNumberRef_0);
1166 } else if ((strcasecmp(argv[0], "enable") == 0) ||
1167 (strcasecmp(argv[0], "yes" ) == 0) ||
1168 (strcasecmp(argv[0], "on" ) == 0) ||
1169 (strcasecmp(argv[0], "1" ) == 0)) {
1170 ok = SCNetworkInterfaceSetCapability(net_interface, key, CFNumberRef_1);
1171 } else {
1172 SCPrint(TRUE, stdout, CFSTR("invalid value\n"));
1173 return -1;
1174 }
1175
1176 if (ok) {
1177 updateInterfaceConfiguration(newConfiguration);
1178 } else {
1179 SCPrint(TRUE, stdout,
1180 CFSTR("%@ not updated: %s\n"),
1181 key,
1182 SCErrorString(SCError()));
1183 return -1;
1184 }
1185
1186 return 1;
1187}
1188
1189
dbf6a266
A
1190static options ethernetOptions[] = {
1191 { "mtu" , NULL, isNumber , &kSCPropNetEthernetMTU , NULL, NULL },
1192 { "media" , NULL, isString , &kSCPropNetEthernetMediaSubType, NULL, NULL },
1193 { "mediaopt" , NULL, isStringArray, &kSCPropNetEthernetMediaOptions, NULL, NULL },
1194
6bb65964
A
1195 { "av" , NULL, isOther , &kSCPropNetEthernetCapabilityAV , __doCapability, NULL },
1196 { "lro" , NULL, isOther , &kSCPropNetEthernetCapabilityLRO , __doCapability, NULL },
1197 { "rxcsum" , NULL, isOther , &kSCPropNetEthernetCapabilityRXCSUM, __doCapability, NULL },
1198 { "tso" , NULL, isOther , &kSCPropNetEthernetCapabilityTSO , __doCapability, NULL },
1199 { "txcsum" , NULL, isOther , &kSCPropNetEthernetCapabilityTXCSUM, __doCapability, NULL },
1200
17d3ee29
A
1201 { "rank" , NULL, isOther , NULL , __doRank, NULL },
1202
1203 { "?" , NULL, isHelp , NULL , NULL,
dbf6a266
A
1204 "\nEthernet configuration commands\n\n"
1205 " set interface [mtu n] [media type] [mediaopts opts]\n"
1206 }
1207};
1208#define N_ETHERNET_OPTIONS (sizeof(ethernetOptions) / sizeof(ethernetOptions[0]))
1209
1210
1211static Boolean
1212set_interface_ethernet(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1213{
1214 CFStringRef interfaceName;
1215 Boolean ok;
1216
1217 interfaceName = SCNetworkInterfaceGetBSDName(net_interface);
1218 if (interfaceName == NULL) {
1219 SCPrint(TRUE, stdout, CFSTR("no BSD interface\n"));
1220 return FALSE;
1221 }
1222
1223 ok = _process_options(ethernetOptions, N_ETHERNET_OPTIONS, argc, argv, newConfiguration);
1224 if (ok) {
dbf6a266 1225 // validate configuration
edebe297 1226 if (!validateMediaOptions(net_interface, newConfiguration)) {
d6c893b2 1227 return FALSE;
dbf6a266 1228 }
d6c893b2 1229 }
dbf6a266 1230
d6c893b2
A
1231 return ok;
1232}
dbf6a266 1233
dbf6a266 1234
a40a14f8
A
1235#pragma mark -
1236#pragma mark IPSec options
1237
1238
a40a14f8
A
1239static int
1240__doIPSecSharedSecret(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1241{
6bb65964
A
1242 CFStringRef encryptionType;
1243
a40a14f8
A
1244 if (argc < 1) {
1245 SCPrint(TRUE, stdout, CFSTR("IPSec shared secret not specified\n"));
1246 return -1;
1247 }
1248
6bb65964 1249 encryptionType = CFDictionaryGetValue(newConfiguration, kSCPropNetIPSecSharedSecretEncryption);
a40a14f8 1250 if (strlen(argv[0]) > 0) {
a40a14f8 1251 if (encryptionType == NULL) {
17d3ee29
A
1252#ifdef INLINE_PASSWORDS_USE_CFSTRING
1253 CFStringRef pw;
1254
1255 pw = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
1256#else // INLINE_PASSWORDS_USE_CFSTRING
a40a14f8
A
1257 CFIndex n;
1258 CFMutableDataRef pw;
1259 CFStringRef str;
1260
1261 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
1262 n = CFStringGetLength(str);
1263 pw = CFDataCreateMutable(NULL, n * sizeof(UniChar));
1264 CFDataSetLength(pw, n * sizeof(UniChar));
17d3ee29 1265 /* ALIGN: CF aligns to at least >8 bytes */
a40a14f8
A
1266 CFStringGetCharacters(str,
1267 CFRangeMake(0, n),
17d3ee29 1268 (UniChar *)(void *)CFDataGetMutableBytePtr(pw));
a40a14f8 1269 CFRelease(str);
17d3ee29 1270#endif // INLINE_PASSWORDS_USE_CFSTRING
a40a14f8
A
1271
1272 CFDictionarySetValue(newConfiguration, key, pw);
1273 CFRelease(pw);
1274 } else if (CFEqual(encryptionType, kSCValNetIPSecSharedSecretEncryptionKeychain)) {
1275 Boolean ok;
1276 CFDataRef pw;
1277 CFStringRef str;
1278
1279 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
1280 pw = CFStringCreateExternalRepresentation(NULL, str, kCFStringEncodingUTF8, 0);
1281 ok = SCNetworkInterfaceSetPassword(net_interface,
1282 kSCNetworkInterfacePasswordTypeIPSecSharedSecret,
1283 pw,
1284 NULL);
1285 CFRelease(pw);
1286 CFRelease(str);
1287 if (ok) {
1288 updateInterfaceConfiguration(newConfiguration);
1289 } else {
1290 return -1;
1291 }
1292 } else {
1293 SCPrint(TRUE, stdout, CFSTR("IPSec shared secret type \"%@\" not supported\n"), encryptionType);
1294 return -1;
1295 }
1296 } else {
6bb65964
A
1297 if (encryptionType == NULL) {
1298 CFDictionaryRemoveValue(newConfiguration, key);
1299 } else if (CFEqual(encryptionType, kSCValNetIPSecSharedSecretEncryptionKeychain)) {
1300 Boolean ok;
1301 ok = SCNetworkInterfaceRemovePassword(net_interface, kSCNetworkInterfacePasswordTypeIPSecSharedSecret);
1302 if (ok) {
1303 updateInterfaceConfiguration(newConfiguration);
1304 } else {
1305 return -1;
1306 }
1307 } else {
1308 SCPrint(TRUE, stdout, CFSTR("IPSec shared secret type \"%@\" not supported\n"), encryptionType);
1309 return -1;
1310 }
a40a14f8
A
1311 }
1312
1313 return 1;
1314}
1315
1316
1317static int
1318__doIPSecSharedSecretType(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1319{
1320 if (argc < 1) {
1321 SCPrint(TRUE, stdout, CFSTR("IPSec shared secret type mode not specified\n"));
1322 return -1;
1323 }
1324
1325 if (strlen(argv[0]) > 0) {
1326 if (strcasecmp(argv[0], "keychain") == 0) {
1327 CFDictionarySetValue(newConfiguration, key, kSCValNetIPSecSharedSecretEncryptionKeychain);
1328 } else {
1329 SCPrint(TRUE, stdout, CFSTR("invalid shared secret type\n"));
1330 return -1;
1331 }
1332 } else {
1333 CFDictionaryRemoveValue(newConfiguration, key);
1334 }
1335
1336 // encryption type changed, reset shared secret
1337 CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPSecSharedSecret);
1338
1339 return 1;
1340}
1341
1342
1343static int
1344__doIPSecXAuthPassword(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1345{
6bb65964
A
1346 CFStringRef encryptionType;
1347
a40a14f8
A
1348 if (argc < 1) {
1349 SCPrint(TRUE, stdout, CFSTR("IPSec XAuth password not specified\n"));
1350 return -1;
1351 }
1352
6bb65964 1353 encryptionType = CFDictionaryGetValue(newConfiguration, kSCPropNetIPSecXAuthPasswordEncryption);
a40a14f8 1354 if (strlen(argv[0]) > 0) {
a40a14f8 1355 if (encryptionType == NULL) {
17d3ee29
A
1356#ifdef INLINE_PASSWORDS_USE_CFSTRING
1357 CFStringRef pw;
1358
1359 pw = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
1360#else // INLINE_PASSWORDS_USE_CFSTRING
a40a14f8
A
1361 CFIndex n;
1362 CFMutableDataRef pw;
1363 CFStringRef str;
1364
1365 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
1366 n = CFStringGetLength(str);
1367 pw = CFDataCreateMutable(NULL, n * sizeof(UniChar));
1368 CFDataSetLength(pw, n * sizeof(UniChar));
17d3ee29 1369 /* ALIGN: CF aligns to at least >8 byte boundries */
a40a14f8
A
1370 CFStringGetCharacters(str,
1371 CFRangeMake(0, n),
17d3ee29 1372 (UniChar *)(void *)CFDataGetMutableBytePtr(pw));
a40a14f8 1373 CFRelease(str);
17d3ee29 1374#endif // INLINE_PASSWORDS_USE_CFSTRING
a40a14f8
A
1375
1376 CFDictionarySetValue(newConfiguration, key, pw);
1377 CFRelease(pw);
1378 } else if (CFEqual(encryptionType, kSCValNetIPSecXAuthPasswordEncryptionKeychain)) {
1379 Boolean ok;
1380 CFDataRef pw;
1381 CFStringRef str;
1382
1383 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
1384 pw = CFStringCreateExternalRepresentation(NULL, str, kCFStringEncodingUTF8, 0);
1385 ok = SCNetworkInterfaceSetPassword(net_interface,
1386 kSCNetworkInterfacePasswordTypeIPSecXAuth,
1387 pw,
1388 NULL);
1389 CFRelease(pw);
1390 CFRelease(str);
1391 if (ok) {
1392 updateInterfaceConfiguration(newConfiguration);
1393 } else {
1394 return -1;
1395 }
1396 } else {
1397 SCPrint(TRUE, stdout, CFSTR("IPSec XAuthPassword type \"%@\" not supported\n"), encryptionType);
1398 return -1;
1399 }
1400 } else {
6bb65964
A
1401 if (encryptionType == NULL) {
1402 CFDictionaryRemoveValue(newConfiguration, key);
1403 } else if (CFEqual(encryptionType, kSCValNetIPSecXAuthPasswordEncryptionKeychain)) {
1404 Boolean ok;
1405
1406 ok = SCNetworkInterfaceRemovePassword(net_interface, kSCNetworkInterfacePasswordTypeIPSecXAuth);
1407 if (ok) {
1408 updateInterfaceConfiguration(newConfiguration);
1409 } else {
1410 return -1;
1411 }
1412 } else {
1413 SCPrint(TRUE, stdout, CFSTR("IPSec XAuthPassword type \"%@\" not supported\n"), encryptionType);
1414 return -1;
1415 }
a40a14f8
A
1416 }
1417
1418 return 1;
1419}
1420
1421
1422static int
1423__doIPSecXAuthPasswordType(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1424{
1425 if (argc < 1) {
1426 SCPrint(TRUE, stdout, CFSTR("IPSec XAuth password type mode not specified\n"));
1427 return -1;
1428 }
1429
1430 if (strlen(argv[0]) > 0) {
1431 if (strcasecmp(argv[0], "keychain") == 0) {
1432 CFDictionarySetValue(newConfiguration, key, kSCValNetIPSecXAuthPasswordEncryptionKeychain);
1433 } else {
1434 SCPrint(TRUE, stdout, CFSTR("invalid XAuth password type\n"));
1435 return -1;
1436 }
1437 } else {
1438 CFDictionaryRemoveValue(newConfiguration, key);
1439 }
1440
1441 // encryption type changed, reset XAuthPassword
1442 CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPSecXAuthPassword);
1443
1444 return 1;
1445}
1446
1447
17d3ee29 1448static CF_RETURNS_RETAINED CFStringRef
a40a14f8
A
1449__cleanupDomainName(CFStringRef domain)
1450{
1451 CFMutableStringRef newDomain;
1452
1453 newDomain = CFStringCreateMutableCopy(NULL, 0, domain);
1454 CFStringTrimWhitespace(newDomain);
1455 CFStringTrim(newDomain, CFSTR("."));
1456 if (CFStringGetLength(newDomain) == 0) {
1457 CFRelease(newDomain);
1458 newDomain = NULL;
1459 }
1460
1461 return newDomain;
1462}
1463
1464
1465static int
1466__doOnDemandDomains(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1467{
1468 CFMutableArrayRef domains;
1469
1470 if (argc < 1) {
1471 SCPrint(TRUE, stdout, CFSTR("OnDemand domain name(s) not specified\n"));
1472 return -1;
1473 }
1474
1475 domains = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1476
1477 if (strlen(argv[0]) > 0) {
1478 CFArrayRef array;
1479 CFStringRef str;
1480
1481 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
1482 array = CFStringCreateArrayBySeparatingStrings(NULL, str, CFSTR(","));
1483 CFRelease(str);
1484
1485 if (array != NULL) {
1486 CFIndex i;
1487 CFIndex n = CFArrayGetCount(array);
1488
1489 for (i = 0; i < n; i++) {
1490 CFStringRef domain;
1491
1492 domain = __cleanupDomainName(CFArrayGetValueAtIndex(array, i));
1493 if (domain != NULL) {
1494 CFArrayAppendValue(domains, domain);
1495 CFRelease(domain);
1496 } else {
1497 CFRelease(array);
1498 CFRelease(domains);
1499 SCPrint(TRUE, stdout, CFSTR("invalid OnDemand domain name\n"));
1500 return -1;
1501 }
1502 }
1503 CFRelease(array);
1504 }
1505 }
1506
1507 if (CFArrayGetCount(domains) > 0) {
1508 CFDictionarySetValue(newConfiguration, key, domains);
1509 } else {
1510 CFDictionaryRemoveValue(newConfiguration, key);
1511 }
1512
1513 CFRelease(domains);
1514 return 1;
1515}
1516
1517
1518static options ipsecOnDemandOptions[] = {
1519 { "OnDemandMatchDomainsAlways" , "domain", isOther , &kSCPropNetIPSecOnDemandMatchDomainsAlways , __doOnDemandDomains, NULL },
1520 { "always" , "domain", isOther , &kSCPropNetIPSecOnDemandMatchDomainsAlways , __doOnDemandDomains, NULL },
1521 { "OnDemandMatchDomainsOnRetry", "domain", isOther , &kSCPropNetIPSecOnDemandMatchDomainsOnRetry, __doOnDemandDomains, NULL },
1522 { "retry" , "domain", isOther , &kSCPropNetIPSecOnDemandMatchDomainsOnRetry, __doOnDemandDomains, NULL },
1523 { "OnDemandMatchDomainsNever" , "domain", isOther , &kSCPropNetIPSecOnDemandMatchDomainsNever , __doOnDemandDomains, NULL },
1524 { "never" , "domain", isOther , &kSCPropNetIPSecOnDemandMatchDomainsNever , __doOnDemandDomains, NULL },
1525
1526 { "?" , NULL , isHelp , NULL , NULL ,
1527 "\nOnDemandMatch configuration commands\n\n"
1528 " set interface OnDemandMatch always domain-name[,domain-name]\n"
1529 " set interface OnDemandMatch retry domain-name[,domain-name]\n"
1530 " set interface OnDemandMatch never domain-name[,domain-name]\n"
1531 }
1532};
1533#define N_IPSEC_ONDEMAND_OPTIONS (sizeof(ipsecOnDemandOptions) / sizeof(ipsecOnDemandOptions[0]))
1534
1535
1536static int
1537__doIPSecOnDemandMatch(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1538{
1539 Boolean ok;
1540
1541 if (argc < 1) {
1542 SCPrint(TRUE, stdout, CFSTR("set what?\n"));
1543 return -1;
1544 }
1545
1546 ok = _process_options(ipsecOnDemandOptions, N_IPSEC_ONDEMAND_OPTIONS, argc, argv, newConfiguration);
1547 if (!ok) {
1548 goto done;
1549 }
1550
1551 done :
1552
1553 return argc;
1554}
1555
1556
1557static selections ipsecAuthenticationMethodSelections[] = {
1558 { CFSTR("SharedSecret"), &kSCValNetIPSecAuthenticationMethodSharedSecret, 0 },
1559 { CFSTR("Certificate") , &kSCValNetIPSecAuthenticationMethodCertificate , 0 },
1560 { CFSTR("Hybrid") , &kSCValNetIPSecAuthenticationMethodHybrid , 0 },
1561 { NULL , NULL , 0 }
1562};
1563
1564
1565static selections ipsecLocalIdentifierTypeSelections[] = {
1566 { CFSTR("KeyID") , &kSCValNetIPSecLocalIdentifierTypeKeyID , 0 },
1567 { NULL , NULL , 0 }
1568};
1569
1570
1571static options ipsecOptions[] = {
1572 { "AuthenticationMethod" , NULL, isChooseOne , &kSCPropNetIPSecAuthenticationMethod , NULL , (void *)ipsecAuthenticationMethodSelections },
1573 { "LocalIdentifier" , NULL, isString , &kSCPropNetIPSecLocalIdentifier , NULL , NULL },
1574 { "group" , NULL, isString , &kSCPropNetIPSecLocalIdentifier , NULL , NULL },
1575 { "LocalIdentifierType" , NULL, isChooseOne , &kSCPropNetIPSecLocalIdentifierType , NULL , (void *)ipsecLocalIdentifierTypeSelections },
1576 { "RemoteAddress" , NULL, isString , &kSCPropNetIPSecRemoteAddress , NULL , NULL },
1577 { "SharedSecret" , NULL, isOther , &kSCPropNetIPSecSharedSecret , __doIPSecSharedSecret , NULL },
1578 { "SharedSecretEncryption" , NULL, isOther , &kSCPropNetIPSecSharedSecretEncryption , __doIPSecSharedSecretType , NULL },
1579
1580 // --- XAuth: ---
1581 { "XAuthEnabled" , NULL, isBoolean , &kSCPropNetIPSecXAuthEnabled , NULL , NULL },
1582 { "XAuthName" , NULL, isString , &kSCPropNetIPSecXAuthName , NULL , NULL },
1583 { "XAuthPassword" , NULL, isOther , &kSCPropNetIPSecXAuthPassword , __doIPSecXAuthPassword , NULL },
1584 { "XAuthPasswordEncryption", NULL, isOther , &kSCPropNetIPSecXAuthPasswordEncryption, __doIPSecXAuthPasswordType, NULL },
1585
1586 // --- OnDemand: ---
1587 { "OnDemandEnabled" , NULL, isBoolean , &kSCPropNetIPSecOnDemandEnabled , NULL , NULL },
1588 { "OnDemandMatch" , NULL, isOther , NULL , __doIPSecOnDemandMatch , NULL },
1589
1590 { "?" , NULL , isHelp , NULL , NULL,
1591 "\nIPSec configuration commands\n\n"
1592 " set interface [AuthenticationMethod {SharedSecret|Certificate|Hybrid}]\n"
1593 " set interface [LocalIdentifier group]\n"
1594 " set interface [LocalIdentifierType {KeyID}]\n"
1595 " set interface [RemoteAddress name-or-address]\n"
1596 " set interface [SharedSecret secret]\n"
1597 " set interface [SharedSecretEncryption {Keychain}]\n"
1598 " set interface [XAuthEnabled {enable|disable}]\n"
1599 " set interface [XAuthPassword password]\n"
1600 " set interface [XAuthPasswordEncryption {Keychain}]\n"
1601 " set interface [OnDemandEnabled {enable|disable}]\n"
1602 " set interface [OnDemandMatch <match-options>]\n"
1603 }
1604};
1605#define N_IPSEC_OPTIONS (sizeof(ipsecOptions) / sizeof(ipsecOptions[0]))
1606
1607
1608static Boolean
1609set_interface_ipsec(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1610{
1611 Boolean ok;
1612
1613 ok = _process_options(ipsecOptions, N_IPSEC_OPTIONS, argc, argv, newConfiguration);
1614 return ok;
1615}
1616
1617
1618#pragma mark -
1619#pragma mark FireWire options
dbf6a266 1620
dbf6a266 1621
d6c893b2
A
1622static options firewireOptions[] = {
1623 { "mtu" , NULL, isNumber , &kSCPropNetEthernetMTU , NULL, NULL },
1624 { "media" , NULL, isString , &kSCPropNetEthernetMediaSubType, NULL, NULL },
1625 { "mediaopt" , NULL, isStringArray, &kSCPropNetEthernetMediaOptions, NULL, NULL },
dbf6a266 1626
d6c893b2
A
1627 { "?" , NULL , isHelp , NULL , NULL,
1628 "\nFireWire configuration commands\n\n"
1629 " set interface [mtu n] [media type] [mediaopts opts]\n"
1630 }
1631};
1632#define N_FIREWIRE_OPTIONS (sizeof(firewireOptions) / sizeof(firewireOptions[0]))
dbf6a266 1633
dbf6a266 1634
d6c893b2
A
1635static Boolean
1636set_interface_firewire(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1637{
1638 CFStringRef interfaceName;
1639 Boolean ok;
dbf6a266 1640
d6c893b2
A
1641 interfaceName = SCNetworkInterfaceGetBSDName(net_interface);
1642 if (interfaceName == NULL) {
1643 SCPrint(TRUE, stdout, CFSTR("no BSD interface\n"));
1644 return FALSE;
1645 }
dbf6a266 1646
d6c893b2
A
1647 ok = _process_options(firewireOptions, N_FIREWIRE_OPTIONS, argc, argv, newConfiguration);
1648 if (ok) {
1649 // validate configuration
edebe297 1650 if (!validateMediaOptions(net_interface, newConfiguration)) {
d6c893b2 1651 return FALSE;
dbf6a266
A
1652 }
1653 }
1654
1655 return ok;
1656}
1657
1658
a40a14f8
A
1659#pragma mark -
1660#pragma mark Modem options
dbf6a266
A
1661
1662
1663static selections modemDialSelections[] = {
1664 { CFSTR("ignore"), &kSCValNetModemDialModeIgnoreDialTone , 0 },
1665 { CFSTR("manual"), &kSCValNetModemDialModeManual , 0 },
1666 { CFSTR("wait") , &kSCValNetModemDialModeWaitForDialTone, 0 },
1667 { NULL , NULL , 0 }
1668};
1669
1670static options modemOptions[] = {
1671 { "ConnectionScript" , "script", isString , &kSCPropNetModemConnectionScript , NULL, NULL },
1672 { "DialMode" , "mode" , isChooseOne, &kSCPropNetModemDialMode , NULL, (void *)modemDialSelections },
1673 { "CallWaiting" , NULL , isBoolean , &kSCPropNetModemHoldEnabled , NULL, NULL },
1674 { "CallWaitingAlert" , NULL , isBoolean , &kSCPropNetModemHoldCallWaitingAudibleAlert, NULL, NULL },
1675 { "CallWaitingDisconnectOnAnswer", NULL , isBoolean , &kSCPropNetModemHoldDisconnectOnAnswer , NULL, NULL },
1676 { "DataCompression" , NULL , isBoolean , &kSCPropNetModemDataCompression , NULL, NULL },
1677 { "ErrorCorrection" , NULL , isBoolean , &kSCPropNetModemErrorCorrection , NULL, NULL },
1678 { "HoldReminder" , NULL , isBoolean , &kSCPropNetModemHoldReminder , NULL, NULL },
1679 { "HoldReminderTime" , "time" , isNumber , &kSCPropNetModemHoldReminderTime , NULL, NULL },
1680 { "PulseDial" , NULL , isBoolean , &kSCPropNetModemPulseDial , NULL, NULL },
1681 { "Speaker" , NULL , isBoolean , &kSCPropNetModemSpeaker , NULL, NULL },
1682
1683 { "?" , NULL , isHelp , NULL , NULL,
1684 "\nModem configuration commands\n\n"
1685 " set interface [ConnectionScript connection-script]\n"
1686 " set interface [CallWaiting {enable|disable}]\n"
1687 " set interface [CallWaitingAlert {enable|disable}]\n"
1688 " set interface [CallWaitingDisconnectOnAnswer {enable|disable}]\n"
1689 " set interface [DialMode {ignore|wait}]\n"
1690 " set interface [DataCompression {enable|disable}]\n"
1691 " set interface [ErrorCorrection {enable|disable}]\n"
1692 " set interface [HoldReminder {enable|disable}]\n"
1693 " set interface [HoldReminderTime n]\n"
1694 " set interface [PulseDial {enable|disable}]\n"
a40a14f8 1695 " set interface [Speaker {enable|disable}]\n"
dbf6a266
A
1696 }
1697};
1698#define N_MODEM_OPTIONS (sizeof(modemOptions) / sizeof(modemOptions[0]))
1699
1700
1701static Boolean
1702set_interface_modem(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1703{
1704 Boolean ok;
1705
1706 ok = _process_options(modemOptions, N_MODEM_OPTIONS, argc, argv, newConfiguration);
1707 return ok;
1708}
1709
1710
a40a14f8
A
1711#pragma mark -
1712#pragma mark PPP options
dbf6a266
A
1713
1714
1715static int
1716__doPPPAuthPW(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1717{
6bb65964
A
1718 CFStringRef encryptionType;
1719
dbf6a266
A
1720 if (argc < 1) {
1721 SCPrint(TRUE, stdout, CFSTR("PPP password not specified\n"));
1722 return -1;
1723 }
1724
6bb65964 1725 encryptionType = CFDictionaryGetValue(newConfiguration, kSCPropNetPPPAuthPasswordEncryption);
dbf6a266 1726 if (strlen(argv[0]) > 0) {
dbf6a266 1727 if (encryptionType == NULL) {
17d3ee29
A
1728#ifdef INLINE_PASSWORDS_USE_CFSTRING
1729 CFStringRef pw;
1730
1731 pw = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
1732#else // INLINE_PASSWORDS_USE_CFSTRING
dbf6a266
A
1733 CFIndex n;
1734 CFMutableDataRef pw;
1735 CFStringRef str;
1736
1737 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
1738 n = CFStringGetLength(str);
1739 pw = CFDataCreateMutable(NULL, n * sizeof(UniChar));
1740 CFDataSetLength(pw, n * sizeof(UniChar));
17d3ee29 1741 /* ALIGN: CF aligns to at least >8 byte boundries */
dbf6a266
A
1742 CFStringGetCharacters(str,
1743 CFRangeMake(0, n),
17d3ee29 1744 (UniChar *)(void *)CFDataGetMutableBytePtr(pw));
dbf6a266 1745 CFRelease(str);
17d3ee29 1746#endif // INLINE_PASSWORDS_USE_CFSTRING
dbf6a266
A
1747
1748 CFDictionarySetValue(newConfiguration, key, pw);
1749 CFRelease(pw);
6bb65964
A
1750 } else if (CFEqual(encryptionType, kSCValNetPPPAuthPasswordEncryptionKeychain)) {
1751 Boolean ok;
1752 CFDataRef pw;
1753 CFStringRef str;
1754
1755 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
1756 pw = CFStringCreateExternalRepresentation(NULL, str, kCFStringEncodingUTF8, 0);
1757 ok = SCNetworkInterfaceSetPassword(net_interface,
1758 kSCNetworkInterfacePasswordTypePPP,
1759 pw,
1760 NULL);
1761 CFRelease(pw);
1762 CFRelease(str);
1763 if (ok) {
1764 updateInterfaceConfiguration(newConfiguration);
1765 } else {
1766 return -1;
1767 }
dbf6a266
A
1768 } else {
1769 SCPrint(TRUE, stdout, CFSTR("PPP password type \"%@\" not supported\n"), encryptionType);
1770 return -1;
1771 }
1772 } else {
6bb65964
A
1773 if (encryptionType == NULL) {
1774 CFDictionaryRemoveValue(newConfiguration, key);
1775 } else if (CFEqual(encryptionType, kSCValNetPPPAuthPasswordEncryptionKeychain)) {
1776 Boolean ok;
1777
1778 ok = SCNetworkInterfaceRemovePassword(net_interface, kSCNetworkInterfacePasswordTypePPP);
1779 if (ok) {
1780 updateInterfaceConfiguration(newConfiguration);
1781 } else {
1782 return -1;
1783 }
1784 } else {
1785 SCPrint(TRUE, stdout, CFSTR("PPP password type \"%@\" not supported\n"), encryptionType);
1786 return -1;
1787 }
dbf6a266
A
1788 }
1789
1790 return 1;
1791}
1792
1793
1794static int
1795__doPPPAuthPWType(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1796{
1797 if (argc < 1) {
1798 SCPrint(TRUE, stdout, CFSTR("PPP password type mode not specified\n"));
1799 return -1;
1800 }
1801
1802 if (strlen(argv[0]) > 0) {
1803 if (strcasecmp(argv[0], "keychain") == 0) {
1804 CFDictionarySetValue(newConfiguration, key, kSCValNetPPPAuthPasswordEncryptionKeychain);
1805 } else {
1806 SCPrint(TRUE, stdout, CFSTR("invalid password type\n"));
1807 return -1;
1808 }
1809 } else {
1810 CFDictionaryRemoveValue(newConfiguration, key);
1811 }
1812
1813 // encryption type changed, reset password
1814 CFDictionaryRemoveValue(newConfiguration, kSCPropNetPPPAuthPassword);
1815
1816 return 1;
1817}
1818
1819
a40a14f8
A
1820static options l2tp_ipsecOptions[] = {
1821 { "SharedSecret" , NULL, isOther , &kSCPropNetIPSecSharedSecret , __doIPSecSharedSecret , NULL },
1822 { "SharedSecretEncryption", NULL, isOther , &kSCPropNetIPSecSharedSecretEncryption, __doIPSecSharedSecretType, NULL },
1823
1824 { "?" , NULL , isHelp , NULL , NULL,
1825 "\nIPSec configuration commands\n\n"
1826 " set interface ipsec [SharedSecret secret]\n"
1827 " set interface ipsec [SharedSecretEncryption {Keychain}]\n"
1828 }
1829};
1830#define N_L2TP_IPSEC_OPTIONS (sizeof(l2tp_ipsecOptions) / sizeof(l2tp_ipsecOptions[0]))
1831
1832
1833static int
1834__doPPPIPSec(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newPPPConfiguration)
1835{
1836 SCNetworkInterfaceRef childInterface;
1837 CFStringRef childInterfaceType;
1838 CFDictionaryRef configuration;
1839 CFMutableDictionaryRef newConfiguration;
1840 Boolean ok;
1841
1842 if (argc < 1) {
1843 SCPrint(TRUE, stdout, CFSTR("set what?\n"));
1844 return -1;
1845 }
1846
1847 childInterface = SCNetworkInterfaceGetInterface(net_interface);
1848 if (childInterface == NULL) {
1849 SCPrint(TRUE, stdout, CFSTR("this interfaces configuration cannot be changed\n"));
1850 return -1;
1851 }
1852
1853 childInterfaceType = SCNetworkInterfaceGetInterfaceType(childInterface);
1854 if (!CFEqual(childInterfaceType, kSCNetworkInterfaceTypeL2TP)) {
1855 SCPrint(TRUE, stdout, CFSTR("this interfaces configuration cannot be changed\n"));
1856 return -1;
1857 }
1858
1859 configuration = SCNetworkInterfaceGetExtendedConfiguration(net_interface, kSCEntNetIPSec);
1860 if (configuration == NULL) {
1861 newConfiguration = CFDictionaryCreateMutable(NULL,
1862 0,
1863 &kCFTypeDictionaryKeyCallBacks,
1864 &kCFTypeDictionaryValueCallBacks);
1865 } else {
1866 newConfiguration = CFDictionaryCreateMutableCopy(NULL, 0, configuration);
1867 CFDictionaryRemoveValue(newConfiguration, kSCResvInactive);
1868 }
1869
1870 ok = _process_options(l2tp_ipsecOptions, N_L2TP_IPSEC_OPTIONS, argc, argv, newConfiguration);
1871 if (!ok) {
1872 goto done;
1873 }
1874
1875 if (((configuration == NULL) && (CFDictionaryGetCount(newConfiguration) > 0)) ||
1876 ((configuration != NULL) && !CFEqual(configuration, newConfiguration))) {
1877 if (!SCNetworkInterfaceSetExtendedConfiguration(net_interface, kSCEntNetIPSec, newConfiguration)) {
1878 if (SCError() == kSCStatusNoKey) {
1879 SCPrint(TRUE, stdout, CFSTR("could not update per-service interface configuration\n"));
1880 } else {
1881 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
1882 }
1883 goto done;
1884 }
1885
1886 _prefs_changed = TRUE;
1887 }
1888
1889 done :
1890
1891 if (newConfiguration != NULL) CFRelease(newConfiguration);
1892 return argc;
1893}
1894
1895
1896#ifdef NOTYET
1897static options pppOnDemandOptions[] = {
1898 { "OnDemandMatchDomainsAlways" , "domain", isOther , &kSCPropNetPPPOnDemandMatchDomainsAlways , __doOnDemandDomains, NULL },
1899 { "always" , "domain", isOther , &kSCPropNetPPPOnDemandMatchDomainsAlways , __doOnDemandDomains, NULL },
1900 { "OnDemandMatchDomainsOnRetry", "domain", isOther , &kSCPropNetPPPOnDemandMatchDomainsOnRetry, __doOnDemandDomains, NULL },
1901 { "retry" , "domain", isOther , &kSCPropNetPPPOnDemandMatchDomainsOnRetry, __doOnDemandDomains, NULL },
1902 { "OnDemandMatchDomainsNever" , "domain", isOther , &kSCPropNetPPPOnDemandMatchDomainsNever , __doOnDemandDomains, NULL },
1903 { "never" , "domain", isOther , &kSCPropNetPPPOnDemandMatchDomainsNever , __doOnDemandDomains, NULL },
1904
1905 { "?" , NULL , isHelp , NULL , NULL ,
1906 "\nOnDemandMatch configuration commands\n\n"
1907 " set interface OnDemand always domain-name[,domain-name]\n"
1908 " set interface OnDemand retry domain-name[,domain-name]\n"
1909 " set interface OnDemand never domain-name[,domain-name]\n"
1910 }
1911};
1912#define N_PPP_ONDEMAND_OPTIONS (sizeof(pppOnDemandOptions) / sizeof(pppOnDemandOptions[0]))
1913
1914
1915static int
1916__doPPPOnDemandMatch(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1917{
1918 Boolean ok;
1919
1920 if (argc < 1) {
1921 SCPrint(TRUE, stdout, CFSTR("set what?\n"));
1922 return -1;
1923 }
1924
1925 ok = _process_options(pppOnDemandOptions, N_PPP_ONDEMAND_OPTIONS, argc, argv, newConfiguration);
1926 if (!ok) {
1927 goto done;
1928 }
1929
1930 done :
1931
1932 return argc;
1933}
1934#endif // NOTYET
1935
1936
dbf6a266
A
1937static selections authPromptSelections[] = {
1938 { CFSTR("before"), &kSCValNetPPPAuthPromptBefore, 0 },
1939 { CFSTR("after") , &kSCValNetPPPAuthPromptAfter , 0 },
1940 { NULL , NULL , 0 }
1941};
1942
1943
1944static selections authProtocolSelections[] = {
1945 { CFSTR("CHAP") , &kSCValNetPPPAuthProtocolCHAP , 0 },
1946 { CFSTR("EAP") , &kSCValNetPPPAuthProtocolEAP , 0 },
1947 { CFSTR("MSCHAP1"), &kSCValNetPPPAuthProtocolMSCHAP1, 0 },
1948 { CFSTR("MSCHAP2"), &kSCValNetPPPAuthProtocolMSCHAP2, 0 },
1949 { CFSTR("PAP") , &kSCValNetPPPAuthProtocolPAP , 0 },
1950 { NULL , NULL , 0 }
1951};
1952
1953
1954static options pppOptions[] = {
a40a14f8
A
1955 { "ACSP" , NULL , isBoolean , &kSCPropNetPPPACSPEnabled , NULL , NULL },
1956 { "ConnectTime" , "?time" , isNumber , &kSCPropNetPPPConnectTime , NULL , NULL },
1957 { "DialOnDemand" , NULL , isBoolean , &kSCPropNetPPPDialOnDemand , NULL , NULL },
1958 { "DisconnectOnFastUserSwitch", NULL , isBoolean , &kSCPropNetPPPDisconnectOnFastUserSwitch, NULL , NULL },
1959 { "DisconnectOnIdle" , NULL , isBoolean , &kSCPropNetPPPDisconnectOnIdle , NULL , NULL },
1960 { "DisconnectOnIdleTimer" , "timeout" , isNumber , &kSCPropNetPPPDisconnectOnIdleTimer , NULL , NULL },
1961 { "DisconnectOnLogout" , NULL , isBoolean , &kSCPropNetPPPDisconnectOnLogout , NULL , NULL },
1962 { "DisconnectOnSleep" , NULL , isBoolean , &kSCPropNetPPPDisconnectOnSleep , NULL , NULL },
1963 { "DisconnectTime" , "?time" , isNumber , &kSCPropNetPPPDisconnectTime , NULL , NULL },
1964 { "IdleReminder" , NULL , isBoolean , &kSCPropNetPPPIdleReminder , NULL , NULL },
1965 { "IdleReminderTimer" , "time" , isNumber , &kSCPropNetPPPIdleReminderTimer , NULL , NULL },
1966 { "Logfile" , "path" , isString , &kSCPropNetPPPLogfile , NULL , NULL },
1967 { "Plugins" , "plugin" , isStringArray , &kSCPropNetPPPPlugins , NULL , NULL },
1968 { "RetryConnectTime" , "time" , isNumber , &kSCPropNetPPPRetryConnectTime , NULL , NULL },
1969 { "SessionTimer" , "time" , isNumber , &kSCPropNetPPPSessionTimer , NULL , NULL },
1970 { "UseSessionTimer" , NULL , isBoolean , &kSCPropNetPPPUseSessionTimer , NULL , NULL },
1971 { "VerboseLogging" , NULL , isBoolean , &kSCPropNetPPPVerboseLogging , NULL , NULL },
dbf6a266
A
1972
1973 // --- Auth: ---
a40a14f8
A
1974 { "AuthEAPPlugins" , "plugin" , isStringArray , &kSCPropNetPPPAuthEAPPlugins , NULL , NULL },
1975 { "AuthName" , "account" , isString , &kSCPropNetPPPAuthName , NULL , NULL },
1976 { "Account" , "account" , isString , &kSCPropNetPPPAuthName , NULL , NULL },
1977 { "AuthPassword" , "password" , isOther , &kSCPropNetPPPAuthPassword , __doPPPAuthPW , NULL },
1978 { "Password" , "password" , isOther , &kSCPropNetPPPAuthPassword , __doPPPAuthPW , NULL },
1979 { "AuthPasswordEncryption" , "type" , isOther , &kSCPropNetPPPAuthPasswordEncryption , __doPPPAuthPWType , NULL },
1980 { "AuthPrompt" , "before/after", isChooseOne , &kSCPropNetPPPAuthPrompt , NULL , (void *)authPromptSelections },
1981 { "AuthProtocol" , "protocol" , isChooseMultiple , &kSCPropNetPPPAuthProtocol , NULL , (void *)authProtocolSelections },
dbf6a266
A
1982
1983 // --- Comm: ---
a40a14f8
A
1984 { "CommRemoteAddress" , "phone#" , isString , &kSCPropNetPPPCommRemoteAddress , NULL , NULL },
1985 { "CommAlternateRemoteAddress", "phone#" , isString , &kSCPropNetPPPCommAlternateRemoteAddress, NULL , NULL },
1986 { "CommConnectDelay" , "time" , isNumber , &kSCPropNetPPPCommConnectDelay , NULL , NULL },
1987 { "CommDisplayTerminalWindow" , NULL , isBoolean , &kSCPropNetPPPCommDisplayTerminalWindow , NULL , NULL },
1988 { "CommRedialCount" , "retry count" , isNumber , &kSCPropNetPPPCommRedialCount , NULL , NULL },
1989 { "CommRedialEnabled" , NULL , isBoolean , &kSCPropNetPPPCommRedialEnabled , NULL , NULL },
1990 { "CommRedialInterval" , "retry delay" , isNumber , &kSCPropNetPPPCommRedialInterval , NULL , NULL },
1991 { "CommTerminalScript" , "script" , isString , &kSCPropNetPPPCommTerminalScript , NULL , NULL },
1992 { "CommUseTerminalScript" , NULL , isBoolean , &kSCPropNetPPPCommUseTerminalScript , NULL , NULL },
dbf6a266
A
1993
1994 // --- CCP: ---
a40a14f8
A
1995 { "CCPEnabled" , NULL , isBoolean , &kSCPropNetPPPCCPEnabled , NULL , NULL },
1996 { "CCPMPPE40Enabled" , NULL , isBoolean , &kSCPropNetPPPCCPMPPE40Enabled , NULL , NULL },
1997 { "CCPMPPE128Enabled" , NULL , isBoolean , &kSCPropNetPPPCCPMPPE128Enabled , NULL , NULL },
dbf6a266
A
1998
1999 // --- IPCP: ---
a40a14f8
A
2000 { "IPCPCompressionVJ" , NULL , isBoolean , &kSCPropNetPPPIPCPCompressionVJ , NULL , NULL },
2001 { "IPCPUsePeerDNS" , NULL , isBoolean , &kSCPropNetPPPIPCPUsePeerDNS , NULL , NULL },
dbf6a266
A
2002
2003 // --- LCP: ---
a40a14f8
A
2004 { "LCPEchoEnabled" , NULL , isBoolean , &kSCPropNetPPPLCPEchoEnabled , NULL , NULL },
2005 { "LCPEchoFailure" , NULL , isNumber , &kSCPropNetPPPLCPEchoFailure , NULL , NULL },
2006 { "LCPEchoInterval" , NULL , isNumber , &kSCPropNetPPPLCPEchoInterval , NULL , NULL },
2007 { "LCPCompressionACField" , NULL , isBoolean , &kSCPropNetPPPLCPCompressionACField , NULL , NULL },
2008 { "LCPCompressionPField" , NULL , isBoolean , &kSCPropNetPPPLCPCompressionPField , NULL , NULL },
2009 { "LCPMRU" , NULL , isNumber , &kSCPropNetPPPLCPMRU , NULL , NULL },
2010 { "LCPMTU" , NULL , isNumber , &kSCPropNetPPPLCPMTU , NULL , NULL },
2011 { "LCPReceiveACCM" , NULL , isNumber , &kSCPropNetPPPLCPReceiveACCM , NULL , NULL },
2012 { "LCPTransmitACCM" , NULL , isNumber , &kSCPropNetPPPLCPTransmitACCM , NULL , NULL },
2013
2014 // --- IPSec: ---
2015 { "IPSec" , NULL , isOther , NULL , __doPPPIPSec , NULL },
2016
2017#ifdef NOTYET
2018 // --- OnDemand: ---
2019 { "OnDemandEnabled" , NULL , isBoolean , &kSCPropNetPPPOnDemandEnabled , NULL , NULL },
2020 { "OnDemandMatch" , NULL , isOther , NULL , __doPPPOnDemandMatch, NULL },
2021#endif // NOTYET
dbf6a266
A
2022
2023 // --- Help ---
a40a14f8 2024 { "?" , NULL , isHelp , NULL , NULL ,
dbf6a266
A
2025 "\nPPP configuration commands\n\n"
2026 " set interface [Account account]\n"
2027 " set interface [Password password]\n"
2028 " set interface [Number telephone-number]\n"
2029 " set interface [AlternateNumber telephone-number]\n"
2030 " set interface [IdleReminder {enable|disable}]\n"
2031 " set interface [IdleReminderTimer time-in-seconds]\n"
2032 " set interface [DisconnectOnIdle {enable|disable}]\n"
2033 " set interface [DisconnectOnIdleTimer time-in-seconds]\n"
a40a14f8
A
2034 " set interface [DisconnectOnLogout {enable|disable}]\n"
2035 " set interface [IPSec <ipsec-options>]\n"
2036#ifdef NOTYET
2037 " set interface [OnDemandEnabled {enable|disable}]\n"
2038 " set interface [OnDemandMatch <match-options>]\n"
2039#endif // NOTYET
dbf6a266
A
2040 }
2041};
2042#define N_PPP_OPTIONS (sizeof(pppOptions) / sizeof(pppOptions[0]))
2043
2044
2045static Boolean
2046set_interface_ppp(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
2047{
2048 Boolean ok;
2049
2050 ok = _process_options(pppOptions, N_PPP_OPTIONS, argc, argv, newConfiguration);
2051 return ok;
2052}
2053
2054
a40a14f8
A
2055#pragma mark -
2056#pragma mark VLAN options
2057
2058
dbf6a266
A
2059static Boolean
2060set_interface_vlan(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
2061{
2062// xxxxx ("device", "tag")
2063SCPrint(TRUE, stdout, CFSTR("vlan interface management not yet supported\n"));
2064 return FALSE;
2065}
2066
2067
6bb65964
A
2068#pragma mark -
2069#pragma mark VPN options
2070
2071
2072static int
2073__doVPNAuthPW(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
2074{
2075 CFStringRef encryptionType;
2076
2077 if (argc < 1) {
2078 SCPrint(TRUE, stdout, CFSTR("VPN password not specified\n"));
2079 return -1;
2080 }
2081
2082 encryptionType = CFDictionaryGetValue(newConfiguration, kSCPropNetVPNAuthPasswordEncryption);
2083 if (strlen(argv[0]) > 0) {
2084 if (encryptionType == NULL) {
17d3ee29
A
2085#ifdef INLINE_PASSWORDS_USE_CFSTRING
2086 CFStringRef pw;
2087
2088 pw = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
2089#else // INLINE_PASSWORDS_USE_CFSTRING
6bb65964
A
2090 CFIndex n;
2091 CFMutableDataRef pw;
2092 CFStringRef str;
2093
2094 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
2095 n = CFStringGetLength(str);
2096 pw = CFDataCreateMutable(NULL, n * sizeof(UniChar));
2097 CFDataSetLength(pw, n * sizeof(UniChar));
2098 CFStringGetCharacters(str,
2099 CFRangeMake(0, n),
17d3ee29 2100 (UniChar *)(void *)CFDataGetMutableBytePtr(pw));
6bb65964 2101 CFRelease(str);
17d3ee29 2102#endif // INLINE_PASSWORDS_USE_CFSTRING
6bb65964
A
2103
2104 CFDictionarySetValue(newConfiguration, key, pw);
2105 CFRelease(pw);
2106 } else if (CFEqual(encryptionType, kSCValNetVPNAuthPasswordEncryptionKeychain)) {
2107 Boolean ok;
2108 CFDataRef pw;
2109 CFStringRef str;
2110
2111 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
2112 pw = CFStringCreateExternalRepresentation(NULL, str, kCFStringEncodingUTF8, 0);
2113 ok = SCNetworkInterfaceSetPassword(net_interface,
2114 kSCNetworkInterfacePasswordTypeVPN,
2115 pw,
2116 NULL);
2117 CFRelease(pw);
2118 CFRelease(str);
2119 if (ok) {
2120 updateInterfaceConfiguration(newConfiguration);
2121 } else {
2122 return -1;
2123 }
2124 } else {
2125 SCPrint(TRUE, stdout, CFSTR("VPN password type \"%@\" not supported\n"), encryptionType);
2126 return -1;
2127 }
2128 } else {
2129 if (encryptionType == NULL) {
2130 CFDictionaryRemoveValue(newConfiguration, key);
2131 } else if (CFEqual(encryptionType, kSCValNetVPNAuthPasswordEncryptionKeychain)) {
2132 Boolean ok;
2133
2134 ok = SCNetworkInterfaceRemovePassword(net_interface, kSCNetworkInterfacePasswordTypeVPN);
2135 if (ok) {
2136 updateInterfaceConfiguration(newConfiguration);
2137 } else {
2138 return -1;
2139 }
2140 } else {
2141 SCPrint(TRUE, stdout, CFSTR("PPP password type \"%@\" not supported\n"), encryptionType);
2142 return -1;
2143 }
2144 }
2145
2146 return 1;
2147}
2148
2149
2150static int
2151__doVPNAuthPWType(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
2152{
2153 if (argc < 1) {
2154 SCPrint(TRUE, stdout, CFSTR("VPN password type mode not specified\n"));
2155 return -1;
2156 }
2157
2158 if (strlen(argv[0]) > 0) {
2159 if (strcasecmp(argv[0], "keychain") == 0) {
2160 CFDictionarySetValue(newConfiguration, key, kSCValNetVPNAuthPasswordEncryptionKeychain);
2161 } else if (strcasecmp(argv[0], "prompt") == 0) {
2162 CFDictionarySetValue(newConfiguration, key, kSCValNetVPNAuthPasswordEncryptionPrompt);
2163 } else {
2164 SCPrint(TRUE, stdout, CFSTR("invalid password type\n"));
2165 return -1;
2166 }
2167 } else {
2168 CFDictionaryRemoveValue(newConfiguration, key);
2169 }
2170
2171 // encryption type changed, reset password
2172 CFDictionaryRemoveValue(newConfiguration, kSCPropNetVPNAuthPassword);
2173
2174 return 1;
2175}
2176
2177
2178static selections vpnAuthenticationMethodSelections[] = {
2179 { CFSTR("Password") , &kSCValNetVPNAuthenticationMethodPassword , 0 },
2180 { CFSTR("Certificate") , &kSCValNetVPNAuthenticationMethodCertificate , 0 },
2181 { NULL , NULL , 0 }
2182};
2183
2184
2185static options vpnOptions[] = {
2186 { "AuthName" , "account" , isString , &kSCPropNetVPNAuthName , NULL , NULL },
2187 { "Account" , "account" , isString , &kSCPropNetVPNAuthName , NULL , NULL },
2188 { "AuthPassword" , "password" , isOther , &kSCPropNetVPNAuthPassword , __doVPNAuthPW , NULL },
2189 { "Password" , "password" , isOther , &kSCPropNetVPNAuthPassword , __doVPNAuthPW , NULL },
2190 { "AuthPasswordEncryption" , "type" , isOther , &kSCPropNetVPNAuthPasswordEncryption , __doVPNAuthPWType , NULL },
2191 { "AuthenticationMethod" , NULL , isChooseOne , &kSCPropNetVPNAuthenticationMethod , NULL , (void *)vpnAuthenticationMethodSelections },
2192 { "ConnectTime" , "?time" , isNumber , &kSCPropNetVPNConnectTime , NULL , NULL },
2193 { "DisconnectOnFastUserSwitch", NULL , isBoolean , &kSCPropNetVPNDisconnectOnFastUserSwitch, NULL , NULL },
2194 { "DisconnectOnIdle" , NULL , isBoolean , &kSCPropNetVPNDisconnectOnIdle , NULL , NULL },
2195 { "DisconnectOnIdleTimer" , "timeout" , isNumber , &kSCPropNetVPNDisconnectOnIdleTimer , NULL , NULL },
2196 { "DisconnectOnLogout" , NULL , isBoolean , &kSCPropNetVPNDisconnectOnLogout , NULL , NULL },
2197 { "DisconnectOnSleep" , NULL , isBoolean , &kSCPropNetVPNDisconnectOnSleep , NULL , NULL },
2198 { "Logfile" , "path" , isString , &kSCPropNetVPNLogfile , NULL , NULL },
2199 { "MTU" , NULL , isNumber , &kSCPropNetVPNMTU , NULL , NULL },
2200 { "RemoteAddress" , "server" , isString , &kSCPropNetVPNRemoteAddress , NULL , NULL },
2201 { "Server" , "server" , isString , &kSCPropNetVPNRemoteAddress , NULL , NULL },
2202 { "VerboseLogging" , NULL , isBoolean , &kSCPropNetVPNVerboseLogging , NULL , NULL },
2203
2204 // --- Help ---
2205 { "?" , NULL , isHelp , NULL , NULL ,
2206 "\nVPN configuration commands\n\n"
2207 " set interface [Server server]\n"
2208 " set interface [Account account]\n"
2209 " set interface [Password password]\n"
2210 }
2211};
2212#define N_VPN_OPTIONS (sizeof(vpnOptions) / sizeof(vpnOptions[0]))
2213
2214
2215static Boolean
2216set_interface_vpn(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
2217{
2218 Boolean ok;
2219
2220 ok = _process_options(vpnOptions, N_VPN_OPTIONS, argc, argv, newConfiguration);
2221 return ok;
2222}
a40a14f8
A
2223
2224
2225#pragma mark -
2226#pragma mark [more] Interface management
dbf6a266
A
2227
2228
2229__private_extern__
2230void
2231set_interface(int argc, char **argv)
2232{
2233 CFDictionaryRef configuration;
2234 CFStringRef interfaceType;
2235 CFMutableDictionaryRef newConfiguration = NULL;
2236 Boolean ok = FALSE;
2237
2238 if (net_interface == NULL) {
2239 SCPrint(TRUE, stdout, CFSTR("interface not selected\n"));
2240 return;
2241 }
2242
2243 if (argc < 1) {
2244 SCPrint(TRUE, stdout, CFSTR("set what?\n"));
2245 return;
2246 }
2247
2248 configuration = SCNetworkInterfaceGetConfiguration(net_interface);
a40a14f8
A
2249 if (configuration != NULL) {
2250 configuration = CFDictionaryCreateCopy(NULL, configuration);
2251 newConfiguration = CFDictionaryCreateMutableCopy(NULL, 0, configuration);
2252 CFDictionaryRemoveValue(newConfiguration, kSCResvInactive);
2253 } else {
dbf6a266
A
2254 newConfiguration = CFDictionaryCreateMutable(NULL,
2255 0,
2256 &kCFTypeDictionaryKeyCallBacks,
2257 &kCFTypeDictionaryValueCallBacks);
dbf6a266
A
2258 }
2259
2260 interfaceType = SCNetworkInterfaceGetInterfaceType(net_interface);
2261
a40a14f8 2262 if (CFEqual(interfaceType, kSCNetworkInterfaceTypeEthernet)) {
dbf6a266 2263 ok = set_interface_ethernet(argc, argv, newConfiguration);
d6c893b2
A
2264 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeFireWire)) {
2265 ok = set_interface_firewire(argc, argv, newConfiguration);
a40a14f8
A
2266 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeIPSec)) {
2267 ok = set_interface_ipsec(argc, argv, newConfiguration);
dbf6a266
A
2268 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeModem)) {
2269 ok = set_interface_modem(argc, argv, newConfiguration);
2270 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeIEEE80211)) {
2271 ok = set_interface_airport(argc, argv, newConfiguration);
2272 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) {
2273 ok = set_interface_ppp(argc, argv, newConfiguration);
a40a14f8
A
2274 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeBond)) {
2275 ok = set_interface_bond(argc, argv, newConfiguration);
6bb65964
A
2276 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeBridge)) {
2277 ok = set_interface_bridge(argc, argv, newConfiguration);
dbf6a266
A
2278 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeVLAN)) {
2279 ok = set_interface_vlan(argc, argv, newConfiguration);
6bb65964
A
2280 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeVPN)) {
2281 ok = set_interface_vpn(argc, argv, newConfiguration);
dbf6a266
A
2282 } else {
2283 SCPrint(TRUE, stdout, CFSTR("this interfaces configuration cannot be changed\n"));
2284 }
2285
2286 if (!ok) {
2287 goto done;
2288 }
2289
2290 if (((configuration == NULL) && (CFDictionaryGetCount(newConfiguration) > 0)) ||
2291 ((configuration != NULL) && !CFEqual(configuration, newConfiguration))) {
2292 if (!SCNetworkInterfaceSetConfiguration(net_interface, newConfiguration)) {
2293 if (SCError() == kSCStatusNoKey) {
2294 SCPrint(TRUE, stdout, CFSTR("could not update per-service interface configuration\n"));
2295 } else {
2296 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
2297 }
2298 goto done;
2299 }
2300
edebe297 2301 _prefs_changed = TRUE;
dbf6a266
A
2302 }
2303
2304 done :
2305
a40a14f8 2306 if (configuration != NULL) CFRelease(configuration);
dbf6a266
A
2307 if (newConfiguration != NULL) CFRelease(newConfiguration);
2308 return;
2309}
2310
2311
2312/* -------------------- */
2313
2314
2315__private_extern__
2316void
2317show_interface(int argc, char **argv)
2318{
2319 SCNetworkInterfaceRef interface;
2320
a40a14f8
A
2321 if (argc >= 1) {
2322 interface = _find_interface(argc, argv, NULL);
dbf6a266
A
2323 } else {
2324 if (net_interface != NULL) {
2325 interface = net_interface;
2326 } else {
2327 SCPrint(TRUE, stdout, CFSTR("interface not selected\n"));
2328 return;
2329 }
2330 }
2331
2332 if (interface != NULL) {
2333 _show_interface(interface, CFSTR(""), TRUE);
2334 }
2335
2336 return;
2337}
2338
2339
2340/* -------------------- */
2341
2342
2343__private_extern__
17d3ee29 2344CF_RETURNS_RETAINED CFStringRef
dbf6a266
A
2345_interface_description(SCNetworkInterfaceRef interface)
2346{
2347 CFMutableStringRef description;
2348 CFStringRef if_bsd_name;
2349 CFStringRef if_type;
2350
2351 description = CFStringCreateMutable(NULL, 0);
2352
2353 if_type = SCNetworkInterfaceGetInterfaceType(interface);
2354 CFStringAppend(description, if_type);
2355
2356 if_bsd_name = SCNetworkInterfaceGetBSDName(interface);
2357 if (if_bsd_name != NULL) {
2358 CFStringAppendFormat(description, NULL, CFSTR(" (%@)"), if_bsd_name);
2359 }
2360
2361 interface = SCNetworkInterfaceGetInterface(interface);
2362 while ((interface != NULL) &&
2363 !CFEqual(interface, kSCNetworkInterfaceIPv4)) {
2364 CFStringRef childDescription;
2365
2366 childDescription = _interface_description(interface);
2367 CFStringAppendFormat(description, NULL, CFSTR(" / %@"), childDescription);
2368 CFRelease(childDescription);
2369
2370 interface = SCNetworkInterfaceGetInterface(interface);
2371 }
2372
2373 return description;
2374}