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