]> git.saurik.com Git - apple/configd.git/blob - scutil.tproj/net_interface.c
configd-204.tar.gz
[apple/configd.git] / scutil.tproj / net_interface.c
1 /*
2 * Copyright (c) 2004-2006 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 /*
25 * Modification History
26 *
27 * August 5, 2004 Allan Nathanson <ajn@apple.com>
28 * - initial revision
29 */
30
31
32 #include "scutil.h"
33 #include "net.h"
34 #include "prefs.h"
35
36 #include <SystemConfiguration/LinkConfiguration.h>
37
38
39 /* -------------------- */
40
41
42 static CFArrayRef
43 _copy_interfaces()
44 {
45 CFMutableArrayRef interfaces;
46 CFArrayRef real_interfaces;
47
48 real_interfaces = SCNetworkInterfaceCopyAll();
49 if (real_interfaces == NULL) {
50 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
51 return NULL;
52 }
53
54 interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
55
56 // include real interfaces
57 CFArrayAppendArray(interfaces,
58 real_interfaces,
59 CFRangeMake(0, CFArrayGetCount(real_interfaces)));
60 CFRelease(real_interfaces);
61
62 // include pseudo interfaces
63 CFArrayAppendValue(interfaces, kSCNetworkInterfaceIPv4);
64
65 // include interfaces that we have created
66 if (new_interfaces != NULL) {
67 CFArrayAppendArray(interfaces,
68 new_interfaces,
69 CFRangeMake(0, CFArrayGetCount(new_interfaces)));
70 }
71
72 return (CFArrayRef)interfaces;
73 }
74
75
76 __private_extern__
77 SCNetworkInterfaceRef
78 _find_interface(char *match)
79 {
80 Boolean allowIndex = TRUE;
81 CFIndex i;
82 CFIndex n;
83 CFStringRef select_name = NULL;
84 SCNetworkInterfaceRef selected = NULL;
85
86 if (strcasecmp(match, "$child") == 0) {
87 if (net_interface == NULL) {
88 SCPrint(TRUE, stdout, CFSTR("interface not selected\n"));
89 goto done;
90 }
91
92 selected = SCNetworkInterfaceGetInterface(net_interface);
93 if(selected == NULL) {
94 SCPrint(TRUE, stdout, CFSTR("no child interface\n"));
95 }
96
97 goto done;
98 } else if (strcasecmp(match, "$service") == 0) {
99 if (net_service == NULL) {
100 SCPrint(TRUE, stdout, CFSTR("service not selected\n"));
101 goto done;
102 }
103
104 selected = SCNetworkServiceGetInterface(net_service);
105 if(selected == NULL) {
106 SCPrint(TRUE, stdout, CFSTR("no interface for service\n"));
107 }
108
109 goto done;
110 }
111
112 if (interfaces == NULL) {
113 interfaces = _copy_interfaces();
114 if (interfaces == NULL) {
115 return NULL;
116 }
117 allowIndex = FALSE;
118 }
119
120 // try to select the interface by its display name
121
122 select_name = CFStringCreateWithCString(NULL, match, kCFStringEncodingUTF8);
123
124 n = CFArrayGetCount(interfaces);
125 for (i = 0; i < n; i++) {
126 SCNetworkInterfaceRef interface;
127 CFStringRef interfaceName;
128
129 interface = CFArrayGetValueAtIndex(interfaces, i);
130 interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(interface);
131 if ((interfaceName != NULL) && CFEqual(select_name, interfaceName)) {
132 if (selected == NULL) {
133 selected = interface;
134 } else {
135 // if multiple interfaces match
136 selected = NULL;
137 SCPrint(TRUE, stdout, CFSTR("multiple interfaces match\n"));
138 goto done;
139 }
140 }
141 }
142
143 if (selected != NULL) {
144 goto done;
145 }
146
147 // try to select the interface by its BSD name
148
149 for (i = 0; i < n; i++) {
150 SCNetworkInterfaceRef interface;
151 CFStringRef bsd_name = NULL;
152
153 interface = CFArrayGetValueAtIndex(interfaces, i);
154 while ((interface != NULL) && (bsd_name == NULL)) {
155 bsd_name = SCNetworkInterfaceGetBSDName(interface);
156 if (bsd_name == NULL) {
157 interface = SCNetworkInterfaceGetInterface(interface);
158 }
159 }
160
161 if ((bsd_name != NULL) && CFEqual(select_name, bsd_name)) {
162 if (selected == NULL) {
163 selected = interface;
164 } else {
165 // if multiple interfaces match
166 selected = NULL;
167 SCPrint(TRUE, stdout, CFSTR("multiple interfaces match\n"));
168 goto done;
169 }
170 }
171 }
172
173 if (selected != NULL) {
174 goto done;
175 }
176
177 // try to select the interface by its interface type
178
179 for (i = 0; i < n; i++) {
180 SCNetworkInterfaceRef interface;
181 CFStringRef interfaceType;
182
183 interface = CFArrayGetValueAtIndex(interfaces, i);
184 interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
185 if (CFEqual(select_name, interfaceType)) {
186 if (selected == NULL) {
187 selected = interface;
188 } else {
189 // if multiple interfaces match
190 selected = NULL;
191 SCPrint(TRUE, stdout, CFSTR("multiple interfaces match\n"));
192 goto done;
193 }
194 }
195 }
196
197 if (selected != NULL) {
198 goto done;
199 }
200
201 if (allowIndex) {
202 char *end;
203 char *str = match;
204 long val;
205
206 // try to select the interface by its index
207
208 errno = 0;
209 val = strtol(str, &end, 10);
210 if ((*str != '\0') &&
211 ((*end == '\0') || (*end == '.')) &&
212 (errno == 0)) {
213 if ((val > 0) && (val <= n)) {
214 selected = CFArrayGetValueAtIndex(interfaces, val - 1);
215
216 if (*end == '.') {
217 str = end + 1;
218 val = strtol(str, &end, 10);
219 if ((*str != '\0') && (*end == '\0') && (errno == 0)) {
220 while (val-- > 0) {
221 selected = SCNetworkInterfaceGetInterface(selected);
222 if (selected == NULL) {
223 break;
224 }
225 }
226 }
227 }
228 }
229 }
230 }
231
232 if (selected != NULL) {
233 goto done;
234 }
235
236 SCPrint(TRUE, stdout, CFSTR("no match\n"));
237
238 done :
239
240 if (select_name != NULL) CFRelease(select_name);
241 return selected;
242 }
243
244
245 /* -------------------- */
246
247
248 __private_extern__
249 void
250 create_interface(int argc, char **argv)
251 {
252 SCNetworkInterfaceRef interface;
253 CFStringRef interfaceName;
254 CFStringRef interfaceType;
255 SCNetworkInterfaceRef new_interface;
256
257 if (argc < 1) {
258 SCPrint(TRUE, stdout, CFSTR("what interface type?\n"));
259 return;
260 }
261
262 interfaceType = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
263
264 if (CFEqual(interfaceType, kSCNetworkInterfaceTypeVLAN)) {
265 // xxxxx
266 SCPrint(TRUE, stdout, CFSTR("vlan creation not yet supported\n"));
267 goto done;
268 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeBond)) {
269 // xxxxx
270 SCPrint(TRUE, stdout, CFSTR("bond creation not yet supported\n"));
271 goto done;
272 } else {
273 if (argc < 2) {
274 if (net_interface == NULL) {
275 SCPrint(TRUE, stdout, CFSTR("no network interface selected\n"));
276 goto done;
277 }
278
279 interface = net_interface;
280 } else {
281 interface = _find_interface(argv[1]);
282 }
283
284 if (interface == NULL) {
285 return;
286 }
287
288 new_interface = SCNetworkInterfaceCreateWithInterface(interface, interfaceType);
289 if (new_interface == NULL) {
290 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
291 goto done;
292 }
293 }
294
295 if (new_interfaces == NULL) {
296 new_interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
297 }
298 CFArrayAppendValue(new_interfaces, new_interface);
299
300 if (net_interface != NULL) CFRelease(net_interface);
301 net_interface = new_interface;
302
303 interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(net_interface);
304 if (interfaceName == NULL) {
305 interfaceName = SCNetworkInterfaceGetBSDName(net_interface);
306 }
307 if (interfaceName == NULL) {
308 interfaceName = SCNetworkInterfaceGetInterfaceType(net_interface);
309 }
310 SCPrint(TRUE, stdout, CFSTR("interface \"%@\" created and selected\n"), interfaceName);
311
312 done :
313
314 CFRelease(interfaceType);
315 return;
316 }
317
318
319 /* -------------------- */
320
321
322 __private_extern__
323 void
324 select_interface(int argc, char **argv)
325 {
326 SCNetworkInterfaceRef interface;
327
328 interface = _find_interface(argv[0]);
329
330 if (interface != NULL) {
331 CFStringRef interfaceName;
332
333 if (net_interface != NULL) CFRelease(net_interface);
334 net_interface = CFRetain(interface);
335
336 interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(interface);
337 if (interfaceName == NULL) {
338 interfaceName = SCNetworkInterfaceGetBSDName(interface);
339 }
340 if (interfaceName == NULL) {
341 interfaceName = SCNetworkInterfaceGetInterfaceType(interface);
342 }
343
344 SCPrint(TRUE, stdout, CFSTR("interface \"%@\" selected\n"), interfaceName);
345 }
346
347 return;
348 }
349
350
351 /* -------------------- */
352
353
354 __private_extern__
355 void
356 _show_interface(SCNetworkInterfaceRef interface, CFStringRef prefix, Boolean showChild)
357 {
358 CFDictionaryRef configuration;
359 CFStringRef if_bsd_name;
360 CFStringRef if_localized_name;
361 CFStringRef if_mac_address;
362 CFStringRef if_type;
363 CFArrayRef supported;
364
365 if_localized_name = SCNetworkInterfaceGetLocalizedDisplayName(interface);
366 if (if_localized_name != NULL) {
367 SCPrint(TRUE, stdout, CFSTR("%@ name = %@\n"), prefix, if_localized_name);
368 }
369
370 if_bsd_name = SCNetworkInterfaceGetBSDName(interface);
371 if (if_bsd_name != NULL) {
372 SCPrint(TRUE, stdout, CFSTR("%@ interface name = %@\n"), prefix, if_bsd_name);
373 }
374
375 if_type = SCNetworkInterfaceGetInterfaceType(interface);
376 SCPrint(TRUE, stdout, CFSTR("%@ type = %@\n"), prefix, if_type);
377
378 if_mac_address = SCNetworkInterfaceGetHardwareAddressString(interface);
379 if (if_mac_address != NULL) {
380 SCPrint(TRUE, stdout, CFSTR("%@ address = %@\n"), prefix, if_mac_address);
381 }
382
383 configuration = SCNetworkInterfaceGetConfiguration(interface);
384 if ((configuration != NULL) &&
385 CFDictionaryContainsKey(configuration, kSCResvInactive)) {
386 configuration = NULL;
387 }
388
389 if (if_bsd_name != NULL) {
390 CFArrayRef available;
391 CFDictionaryRef active;
392 int mtu_cur;
393 int mtu_min;
394 int mtu_max;
395
396 if (SCNetworkInterfaceCopyMTU(interface, &mtu_cur, &mtu_min, &mtu_max)) {
397 char isCurrent = '*';
398
399 if (configuration != NULL) {
400 int mtu_req;
401 CFNumberRef num;
402
403 num = CFDictionaryGetValue(configuration, kSCPropNetEthernetMTU);
404 if (isA_CFNumber(num)) {
405 CFNumberGetValue(num, kCFNumberIntType, &mtu_req);
406 if (mtu_cur != mtu_req) {
407 mtu_cur = mtu_req;
408 isCurrent = ' ';
409 }
410 }
411 }
412
413 SCPrint(TRUE, stdout, CFSTR("%@ mtu %c = %ld (%ld < n < %ld)\n"),
414 prefix,
415 isCurrent,
416 mtu_cur,
417 mtu_min,
418 mtu_max);
419 }
420
421 if (SCNetworkInterfaceCopyMediaOptions(interface, NULL, &active, &available, TRUE)) {
422 char isCurrent = ' ';
423 CFArrayRef options = NULL;
424 CFArrayRef options_req = NULL;
425 CFStringRef subtype = NULL;
426 CFStringRef subtype_req = NULL;
427
428 if (configuration != NULL) {
429 subtype_req = CFDictionaryGetValue(configuration, kSCPropNetEthernetMediaSubType);
430 options_req = CFDictionaryGetValue(configuration, kSCPropNetEthernetMediaOptions);
431 }
432
433 if (subtype_req == NULL) {
434 subtype_req = CFSTR("autoselect");
435 }
436
437 if (active != NULL) {
438 subtype = CFDictionaryGetValue(active, kSCPropNetEthernetMediaSubType);
439 options = CFDictionaryGetValue(active, kSCPropNetEthernetMediaOptions);
440 }
441
442 if (subtype != NULL) {
443 if (((subtype_req != NULL) &&
444 CFEqual(subtype, subtype_req)) &&
445 ((options == options_req) ||
446 ((options != NULL) &&
447 (options_req != NULL) &&
448 CFEqual(options, options_req)))
449 ) {
450 isCurrent = '*';
451 } else if ((subtype_req == NULL) ||
452 ((subtype_req != NULL) &&
453 CFEqual(subtype_req, CFSTR("autoselect")))) {
454 // if requested subtype not specified or "autoselect"
455 isCurrent = '*';
456 }
457 }
458
459 if (subtype_req != NULL) {
460 SCPrint(TRUE, stdout, CFSTR("%@ media %c = %@"),
461 prefix,
462 isCurrent,
463 subtype_req);
464
465 if ((options_req != NULL) &&
466 (CFArrayGetCount(options_req) > 0)) {
467 CFStringRef options_str;
468
469 options_str = CFStringCreateByCombiningStrings(NULL, options_req, CFSTR(","));
470 SCPrint(TRUE, stdout, CFSTR(" <%@>"), options_str);
471 CFRelease(options_str);
472 }
473
474 SCPrint(TRUE, stdout, CFSTR("\n"));
475 }
476
477 SCPrint(TRUE, stdout, CFSTR("\n"));
478
479 if (available != NULL) {
480 CFIndex i;
481 CFIndex n_subtypes;
482 CFArrayRef subtypes;
483
484 subtypes = SCNetworkInterfaceCopyMediaSubTypes(available);
485 n_subtypes = (subtypes != NULL) ? CFArrayGetCount(subtypes) : 0;
486 for (i = 0; i < n_subtypes; i++) {
487 CFIndex j;
488 CFIndex n_subtype_options;
489 CFStringRef subtype;
490 CFArrayRef subtype_options;
491
492 subtype = CFArrayGetValueAtIndex(subtypes, i);
493 subtype_options = SCNetworkInterfaceCopyMediaSubTypeOptions(available, subtype);
494 n_subtype_options = (subtype_options != NULL) ? CFArrayGetCount(subtype_options) : 0;
495 for (j = 0; j < n_subtype_options; j++) {
496 char isCurrent = ' ';
497 CFArrayRef options;
498
499 options = CFArrayGetValueAtIndex(subtype_options, j);
500
501 if (((subtype_req != NULL) &&
502 CFEqual(subtype, subtype_req)) &&
503 ((options == options_req) ||
504 ((options != NULL) &&
505 (options_req != NULL) &&
506 CFEqual(options, options_req)))
507 ) {
508 isCurrent = '*';
509 }
510
511 SCPrint(TRUE, stdout, CFSTR("%@ %s %c = %@"),
512 prefix,
513 ((i == 0) && (j == 0)) ? "supported media" : " ",
514 isCurrent,
515 subtype);
516
517 if ((options != NULL) &&
518 (CFArrayGetCount(options) > 0)) {
519 CFStringRef options_str;
520
521 options_str = CFStringCreateByCombiningStrings(NULL, options, CFSTR(","));
522 SCPrint(TRUE, stdout, CFSTR(" <%@>"), options_str);
523 CFRelease(options_str);
524 }
525
526 SCPrint(TRUE, stdout, CFSTR("\n"));
527 }
528 CFRelease(subtype_options);
529 }
530 }
531 } else {
532 SCPrint(TRUE, stdout, CFSTR("\n"));
533 }
534 }
535
536 supported = SCNetworkInterfaceGetSupportedInterfaceTypes(interface);
537 SCPrint(TRUE, stdout, CFSTR("%@ supported interfaces = "), prefix);
538 if (supported != NULL) {
539 CFIndex i;
540 CFIndex n = CFArrayGetCount(supported);
541
542 for (i = 0; i < n; i++) {
543 SCPrint(TRUE, stdout, CFSTR("%s%@"),
544 (i == 0) ? "" : ", ",
545 CFArrayGetValueAtIndex(supported, i));
546 }
547 }
548 SCPrint(TRUE, stdout, CFSTR("\n"));
549
550 supported = SCNetworkInterfaceGetSupportedProtocolTypes(interface);
551 SCPrint(TRUE, stdout, CFSTR("%@ supported protocols = "), prefix);
552 if (supported != NULL) {
553 CFIndex i;
554 CFIndex n = CFArrayGetCount(supported);
555
556 for (i = 0; i < n; i++) {
557 SCPrint(TRUE, stdout, CFSTR("%s%@"),
558 (i == 0) ? "" : ", ",
559 CFArrayGetValueAtIndex(supported, i));
560 }
561 }
562 SCPrint(TRUE, stdout, CFSTR("\n"));
563
564 if (configuration != NULL) {
565 CFMutableDictionaryRef effective;
566
567 effective = CFDictionaryCreateMutableCopy(NULL, 0, configuration);
568
569 // remove known (and already reported) interface configuration keys
570 if (CFDictionaryContainsKey(effective, kSCResvInactive)) {
571 CFDictionaryRemoveAllValues(effective);
572 }
573 CFDictionaryRemoveValue(effective, kSCPropNetEthernetMTU);
574 CFDictionaryRemoveValue(effective, kSCPropNetEthernetMediaSubType);
575 CFDictionaryRemoveValue(effective, kSCPropNetEthernetMediaOptions);
576
577 if (CFDictionaryGetCount(effective) > 0) {
578 SCPrint(TRUE, stdout, CFSTR("\n%@ per-interface configuration\n"), prefix);
579 _show_entity(effective, prefix);
580 }
581
582 CFRelease(effective);
583 }
584
585 if (_sc_debug) {
586 SCPrint(TRUE, stdout, CFSTR("\n%@\n"), interface);
587 }
588
589 interface = SCNetworkInterfaceGetInterface(interface);
590 if (interface != NULL) {
591 CFStringRef newPrefix;
592
593 newPrefix = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@ "), prefix);
594 SCPrint(TRUE, stdout, CFSTR("\n%@child interface\n"), newPrefix);
595 _show_interface(interface, newPrefix, showChild);
596 CFRelease(newPrefix);
597 }
598
599 return;
600 }
601
602
603 /* -------------------- */
604
605
606 static Boolean
607 validateMediaOptions(SCNetworkInterfaceRef interface, CFMutableDictionaryRef newConfiguration)
608 {
609 Boolean ok = TRUE;
610 CFNumberRef mtu;
611 CFArrayRef options;
612 CFStringRef subtype;
613
614 mtu = CFDictionaryGetValue(newConfiguration, kSCPropNetEthernetMTU);
615 if (isA_CFNumber(mtu)) {
616 int mtu_max;
617 int mtu_min;
618 int mtu_val;
619
620 if (!SCNetworkInterfaceCopyMTU(interface, NULL, &mtu_min, &mtu_max)) {
621 SCPrint(TRUE, stdout, CFSTR("cannot set MTU\n"));
622 return FALSE;
623 }
624
625 if (!CFNumberGetValue(mtu, kCFNumberIntType, &mtu_val) ||
626 (mtu_val < mtu_min) ||
627 (mtu_val > mtu_max)) {
628 SCPrint(TRUE, stdout, CFSTR("mtu out of range\n"));
629 return FALSE;
630 }
631 }
632
633 subtype = CFDictionaryGetValue(newConfiguration, kSCPropNetEthernetMediaSubType);
634 options = CFDictionaryGetValue(newConfiguration, kSCPropNetEthernetMediaOptions);
635
636 if (subtype != NULL) {
637 CFArrayRef available = NULL;
638 CFArrayRef config_options = options;
639 CFArrayRef subtypes = NULL;
640 CFArrayRef subtype_options = NULL;
641
642 ok = FALSE;
643
644 if (options == NULL) {
645 config_options = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks);
646 }
647
648 if (!SCNetworkInterfaceCopyMediaOptions(interface, NULL, NULL, &available, FALSE)) {
649 SCPrint(TRUE, stdout, CFSTR("media type / options not available\n"));
650 goto checked;
651 }
652
653 if (available == NULL) {
654 goto checked;
655 }
656
657 subtypes = SCNetworkInterfaceCopyMediaSubTypes(available);
658 if ((subtypes == NULL) ||
659 !CFArrayContainsValue(subtypes,
660 CFRangeMake(0, CFArrayGetCount(subtypes)),
661 subtype)) {
662 SCPrint(TRUE, stdout, CFSTR("media type not valid\n"));
663 goto checked;
664 }
665
666 subtype_options = SCNetworkInterfaceCopyMediaSubTypeOptions(available, subtype);
667 if ((subtype_options == NULL) ||
668 !CFArrayContainsValue(subtype_options,
669 CFRangeMake(0, CFArrayGetCount(subtype_options)),
670 config_options)) {
671 SCPrint(TRUE, stdout, CFSTR("media options not valid for \"%@\"\n"), subtype);
672 goto checked;
673 }
674
675 if (options == NULL) {
676 CFDictionarySetValue(newConfiguration, kSCPropNetEthernetMediaOptions, config_options);
677 }
678
679 ok = TRUE;
680
681 checked :
682
683 if (available != NULL) CFRelease(available);
684 if (subtypes != NULL) CFRelease(subtypes);
685 if (subtype_options != NULL) CFRelease(subtype_options);
686 if (options == NULL) CFRelease(config_options);
687 } else {
688 if (options != NULL) {
689 SCPrint(TRUE, stdout, CFSTR("media type and options must both be specified\n"));
690 return FALSE;
691 }
692 }
693
694 return ok;
695 }
696
697
698 /* -------------------- */
699
700
701 __private_extern__
702 void
703 show_interfaces(int argc, char **argv)
704 {
705 CFIndex i;
706 CFIndex n;
707
708 if (interfaces != NULL) CFRelease(interfaces);
709 interfaces = _copy_interfaces();
710 if (interfaces == NULL) {
711 return;
712 }
713
714 n = CFArrayGetCount(interfaces);
715 for (i = 0; i < n; i++) {
716 CFIndex childIndex = 0;
717 SCNetworkInterfaceRef interface;
718
719 interface = CFArrayGetValueAtIndex(interfaces, i);
720 do {
721 CFStringRef interfaceName;
722 char isSelected;
723
724 interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(interface);
725 if (interfaceName == NULL) {
726 interfaceName = SCNetworkInterfaceGetBSDName(interface);
727 }
728 if (interfaceName == NULL) {
729 interfaceName = SCNetworkInterfaceGetInterfaceType(interface);
730 }
731
732 isSelected = ' ';
733 if ((net_interface != NULL) && CFEqual(interface, net_interface)) {
734 isSelected = '>';
735 }
736
737 if (childIndex == 0) {
738 SCPrint(TRUE, stdout, CFSTR("%c%2d: %@\n"),
739 isSelected,
740 i + 1,
741 interfaceName);
742 } else {
743 SCPrint(TRUE, stdout, CFSTR("%c%2d.%d: %@\n"),
744 isSelected,
745 i + 1,
746 childIndex,
747 interfaceName);
748 }
749
750 interface = SCNetworkInterfaceGetInterface(interface);
751 childIndex++;
752 } while (interface != NULL);
753 }
754
755 return;
756 }
757
758
759 /* -------------------- */
760
761
762 static options bondOptions[] = {
763 { "mtu" , NULL, isNumber , &kSCPropNetEthernetMTU , NULL, NULL },
764 // xxx { "+device" , ... },
765 // xxx { "-device" , ... },
766
767 { "?" , NULL , isHelp , NULL , NULL,
768 "\nBond configuration commands\n\n"
769 " set interface [mtu n] [media type] [mediaopts opts]\n"
770 }
771 };
772 #define N_BOND_OPTIONS (sizeof(bondOptions) / sizeof(bondOptions[0]))
773
774
775 static Boolean
776 set_interface_bond(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
777 {
778 CFStringRef interfaceName;
779 Boolean ok;
780
781 interfaceName = SCNetworkInterfaceGetBSDName(net_interface);
782 if (interfaceName == NULL) {
783 SCPrint(TRUE, stdout, CFSTR("no BSD interface\n"));
784 return FALSE;
785 }
786
787 ok = _process_options(bondOptions, N_BOND_OPTIONS, argc, argv, newConfiguration);
788 if (ok) {
789 // validate configuration
790 if (!validateMediaOptions(net_interface, newConfiguration)) {
791 return FALSE;
792 }
793 }
794
795 return ok;
796 }
797
798
799 /* -------------------- */
800
801
802 static options airportOptions[] = {
803 { "mtu" , NULL, isNumber , &kSCPropNetEthernetMTU , NULL, NULL },
804 { "media" , NULL, isString , &kSCPropNetEthernetMediaSubType, NULL, NULL },
805 { "mediaopt" , NULL, isStringArray, &kSCPropNetEthernetMediaOptions, NULL, NULL },
806
807 { "?" , NULL , isHelp , NULL , NULL,
808 "\nAirPort configuration commands\n\n"
809 " set interface [mtu n] [media type] [mediaopts opts]\n"
810 }
811 };
812 #define N_AIRPORT_OPTIONS (sizeof(airportOptions) / sizeof(airportOptions[0]))
813
814
815 static Boolean
816 set_interface_airport(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
817 {
818 CFStringRef interfaceName;
819 Boolean ok;
820
821 interfaceName = SCNetworkInterfaceGetBSDName(net_interface);
822 if (interfaceName == NULL) {
823 SCPrint(TRUE, stdout, CFSTR("no BSD interface\n"));
824 return FALSE;
825 }
826
827 ok = _process_options(airportOptions, N_AIRPORT_OPTIONS, argc, argv, newConfiguration);
828 if (ok) {
829 // validate configuration
830 if (!validateMediaOptions(net_interface, newConfiguration)) {
831 return FALSE;
832 }
833 }
834
835 return ok;
836 }
837
838
839 /* -------------------- */
840
841
842 static options ethernetOptions[] = {
843 { "mtu" , NULL, isNumber , &kSCPropNetEthernetMTU , NULL, NULL },
844 { "media" , NULL, isString , &kSCPropNetEthernetMediaSubType, NULL, NULL },
845 { "mediaopt" , NULL, isStringArray, &kSCPropNetEthernetMediaOptions, NULL, NULL },
846
847 { "?" , NULL , isHelp , NULL , NULL,
848 "\nEthernet configuration commands\n\n"
849 " set interface [mtu n] [media type] [mediaopts opts]\n"
850 }
851 };
852 #define N_ETHERNET_OPTIONS (sizeof(ethernetOptions) / sizeof(ethernetOptions[0]))
853
854
855 static Boolean
856 set_interface_ethernet(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
857 {
858 CFStringRef interfaceName;
859 Boolean ok;
860
861 interfaceName = SCNetworkInterfaceGetBSDName(net_interface);
862 if (interfaceName == NULL) {
863 SCPrint(TRUE, stdout, CFSTR("no BSD interface\n"));
864 return FALSE;
865 }
866
867 ok = _process_options(ethernetOptions, N_ETHERNET_OPTIONS, argc, argv, newConfiguration);
868 if (ok) {
869 // validate configuration
870 if (!validateMediaOptions(net_interface, newConfiguration)) {
871 return FALSE;
872 }
873 }
874
875 return ok;
876 }
877
878
879 /* -------------------- */
880
881
882 static options firewireOptions[] = {
883 { "mtu" , NULL, isNumber , &kSCPropNetEthernetMTU , NULL, NULL },
884 { "media" , NULL, isString , &kSCPropNetEthernetMediaSubType, NULL, NULL },
885 { "mediaopt" , NULL, isStringArray, &kSCPropNetEthernetMediaOptions, NULL, NULL },
886
887 { "?" , NULL , isHelp , NULL , NULL,
888 "\nFireWire configuration commands\n\n"
889 " set interface [mtu n] [media type] [mediaopts opts]\n"
890 }
891 };
892 #define N_FIREWIRE_OPTIONS (sizeof(firewireOptions) / sizeof(firewireOptions[0]))
893
894
895 static Boolean
896 set_interface_firewire(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
897 {
898 CFStringRef interfaceName;
899 Boolean ok;
900
901 interfaceName = SCNetworkInterfaceGetBSDName(net_interface);
902 if (interfaceName == NULL) {
903 SCPrint(TRUE, stdout, CFSTR("no BSD interface\n"));
904 return FALSE;
905 }
906
907 ok = _process_options(firewireOptions, N_FIREWIRE_OPTIONS, argc, argv, newConfiguration);
908 if (ok) {
909 // validate configuration
910 if (!validateMediaOptions(net_interface, newConfiguration)) {
911 return FALSE;
912 }
913 }
914
915 return ok;
916 }
917
918
919 /* -------------------- */
920
921
922 static selections modemDialSelections[] = {
923 { CFSTR("ignore"), &kSCValNetModemDialModeIgnoreDialTone , 0 },
924 { CFSTR("manual"), &kSCValNetModemDialModeManual , 0 },
925 { CFSTR("wait") , &kSCValNetModemDialModeWaitForDialTone, 0 },
926 { NULL , NULL , 0 }
927 };
928
929 static options modemOptions[] = {
930 { "ConnectionScript" , "script", isString , &kSCPropNetModemConnectionScript , NULL, NULL },
931 { "DialMode" , "mode" , isChooseOne, &kSCPropNetModemDialMode , NULL, (void *)modemDialSelections },
932 { "CallWaiting" , NULL , isBoolean , &kSCPropNetModemHoldEnabled , NULL, NULL },
933 { "CallWaitingAlert" , NULL , isBoolean , &kSCPropNetModemHoldCallWaitingAudibleAlert, NULL, NULL },
934 { "CallWaitingDisconnectOnAnswer", NULL , isBoolean , &kSCPropNetModemHoldDisconnectOnAnswer , NULL, NULL },
935 { "DataCompression" , NULL , isBoolean , &kSCPropNetModemDataCompression , NULL, NULL },
936 { "ErrorCorrection" , NULL , isBoolean , &kSCPropNetModemErrorCorrection , NULL, NULL },
937 { "HoldReminder" , NULL , isBoolean , &kSCPropNetModemHoldReminder , NULL, NULL },
938 { "HoldReminderTime" , "time" , isNumber , &kSCPropNetModemHoldReminderTime , NULL, NULL },
939 { "PulseDial" , NULL , isBoolean , &kSCPropNetModemPulseDial , NULL, NULL },
940 { "Speaker" , NULL , isBoolean , &kSCPropNetModemSpeaker , NULL, NULL },
941
942 { "?" , NULL , isHelp , NULL , NULL,
943 "\nModem configuration commands\n\n"
944 " set interface [ConnectionScript connection-script]\n"
945 " set interface [CallWaiting {enable|disable}]\n"
946 " set interface [CallWaitingAlert {enable|disable}]\n"
947 " set interface [CallWaitingDisconnectOnAnswer {enable|disable}]\n"
948 " set interface [DialMode {ignore|wait}]\n"
949 " set interface [DataCompression {enable|disable}]\n"
950 " set interface [ErrorCorrection {enable|disable}]\n"
951 " set interface [HoldReminder {enable|disable}]\n"
952 " set interface [HoldReminderTime n]\n"
953 " set interface [PulseDial {enable|disable}]\n"
954 " set interface [Speaker {enable|disable}]"
955 }
956 };
957 #define N_MODEM_OPTIONS (sizeof(modemOptions) / sizeof(modemOptions[0]))
958
959
960 static Boolean
961 set_interface_modem(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
962 {
963 Boolean ok;
964
965 ok = _process_options(modemOptions, N_MODEM_OPTIONS, argc, argv, newConfiguration);
966 return ok;
967 }
968
969
970 /* -------------------- */
971
972
973 static int
974 __doPPPAuthPW(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
975 {
976 if (argc < 1) {
977 SCPrint(TRUE, stdout, CFSTR("PPP password not specified\n"));
978 return -1;
979 }
980
981 if (strlen(argv[0]) > 0) {
982 CFStringRef encryptionType;
983
984 encryptionType = CFDictionaryGetValue(newConfiguration, kSCPropNetPPPAuthPasswordEncryption);
985 if (encryptionType == NULL) {
986 CFIndex n;
987 CFMutableDataRef pw;
988 CFStringRef str;
989
990 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
991 n = CFStringGetLength(str);
992 pw = CFDataCreateMutable(NULL, n * sizeof(UniChar));
993 CFDataSetLength(pw, n * sizeof(UniChar));
994 CFStringGetCharacters(str,
995 CFRangeMake(0, n),
996 (UniChar *)CFDataGetMutableBytePtr(pw));
997 CFRelease(str);
998
999 CFDictionarySetValue(newConfiguration, key, pw);
1000 CFRelease(pw);
1001 } else {
1002 SCPrint(TRUE, stdout, CFSTR("PPP password type \"%@\" not supported\n"), encryptionType);
1003 return -1;
1004 }
1005 } else {
1006 CFDictionaryRemoveValue(newConfiguration, key);
1007 }
1008
1009 return 1;
1010 }
1011
1012
1013 static int
1014 __doPPPAuthPWType(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1015 {
1016 if (argc < 1) {
1017 SCPrint(TRUE, stdout, CFSTR("PPP password type mode not specified\n"));
1018 return -1;
1019 }
1020
1021 if (strlen(argv[0]) > 0) {
1022 if (strcasecmp(argv[0], "keychain") == 0) {
1023 CFDictionarySetValue(newConfiguration, key, kSCValNetPPPAuthPasswordEncryptionKeychain);
1024 } else {
1025 SCPrint(TRUE, stdout, CFSTR("invalid password type\n"));
1026 return -1;
1027 }
1028 } else {
1029 CFDictionaryRemoveValue(newConfiguration, key);
1030 }
1031
1032 // encryption type changed, reset password
1033 CFDictionaryRemoveValue(newConfiguration, kSCPropNetPPPAuthPassword);
1034
1035 return 1;
1036 }
1037
1038
1039 static selections authPromptSelections[] = {
1040 { CFSTR("before"), &kSCValNetPPPAuthPromptBefore, 0 },
1041 { CFSTR("after") , &kSCValNetPPPAuthPromptAfter , 0 },
1042 { NULL , NULL , 0 }
1043 };
1044
1045
1046 static selections authProtocolSelections[] = {
1047 { CFSTR("CHAP") , &kSCValNetPPPAuthProtocolCHAP , 0 },
1048 { CFSTR("EAP") , &kSCValNetPPPAuthProtocolEAP , 0 },
1049 { CFSTR("MSCHAP1"), &kSCValNetPPPAuthProtocolMSCHAP1, 0 },
1050 { CFSTR("MSCHAP2"), &kSCValNetPPPAuthProtocolMSCHAP2, 0 },
1051 { CFSTR("PAP") , &kSCValNetPPPAuthProtocolPAP , 0 },
1052 { NULL , NULL , 0 }
1053 };
1054
1055
1056 static options pppOptions[] = {
1057 { "ACSP" , NULL , isBoolean , &kSCPropNetPPPACSPEnabled , NULL , NULL },
1058 { "ConnectTime" , "?time" , isNumber , &kSCPropNetPPPConnectTime , NULL , NULL },
1059 { "DialOnDemand" , NULL , isBoolean , &kSCPropNetPPPDialOnDemand , NULL , NULL },
1060 { "DisconnectOnFastUserSwitch", NULL , isBoolean , &kSCPropNetPPPDisconnectOnFastUserSwitch, NULL , NULL },
1061 { "DisconnectOnIdle" , NULL , isBoolean , &kSCPropNetPPPDisconnectOnIdle , NULL , NULL },
1062 { "DisconnectOnIdleTimer" , "timeout" , isNumber , &kSCPropNetPPPDisconnectOnIdleTimer , NULL , NULL },
1063 { "DisconnectOnLogout" , NULL , isBoolean , &kSCPropNetPPPDisconnectOnLogout , NULL , NULL },
1064 { "DisconnectOnSleep" , NULL , isBoolean , &kSCPropNetPPPDisconnectOnSleep , NULL , NULL },
1065 { "DisconnectTime" , "?time" , isNumber , &kSCPropNetPPPDisconnectTime , NULL , NULL },
1066 { "IdleReminder" , NULL , isBoolean , &kSCPropNetPPPIdleReminder , NULL , NULL },
1067 { "IdleReminderTimer" , "time" , isNumber , &kSCPropNetPPPIdleReminderTimer , NULL , NULL },
1068 { "Logfile" , "path" , isString , &kSCPropNetPPPLogfile , NULL , NULL },
1069 { "Plugins" , "plugin" , isStringArray , &kSCPropNetPPPPlugins , NULL , NULL },
1070 { "RetryConnectTime" , "time" , isNumber , &kSCPropNetPPPRetryConnectTime , NULL , NULL },
1071 { "SessionTimer" , "time" , isNumber , &kSCPropNetPPPSessionTimer , NULL , NULL },
1072 { "UseSessionTimer" , NULL , isBoolean , &kSCPropNetPPPUseSessionTimer , NULL , NULL },
1073 { "VerboseLogging" , NULL , isBoolean , &kSCPropNetPPPVerboseLogging , NULL , NULL },
1074
1075 // --- Auth: ---
1076 { "AuthEAPPlugins" , "plugin" , isStringArray , &kSCPropNetPPPAuthEAPPlugins , NULL , NULL },
1077 { "AuthName" , "account" , isString , &kSCPropNetPPPAuthName , NULL , NULL },
1078 { "Account" , "account" , isString , &kSCPropNetPPPAuthName , NULL , NULL },
1079 { "AuthPassword" , "password" , isOther , &kSCPropNetPPPAuthPassword , __doPPPAuthPW , NULL },
1080 { "Password" , "password" , isOther , &kSCPropNetPPPAuthPassword , __doPPPAuthPW , NULL },
1081 { "AuthPasswordEncryption" , "type" , isOther , &kSCPropNetPPPAuthPasswordEncryption , __doPPPAuthPWType, NULL },
1082 { "AuthPrompt" , "before/after", isChooseOne , &kSCPropNetPPPAuthPrompt , NULL , (void *)authPromptSelections },
1083 { "AuthProtocol" , "protocol" , isChooseMultiple , &kSCPropNetPPPAuthProtocol , NULL , (void *)authProtocolSelections },
1084
1085 // --- Comm: ---
1086 { "CommRemoteAddress" , "phone#" , isString , &kSCPropNetPPPCommRemoteAddress , NULL , NULL },
1087 { "CommAlternateRemoteAddress", "phone#" , isString , &kSCPropNetPPPCommAlternateRemoteAddress, NULL , NULL },
1088 { "CommConnectDelay" , "time" , isNumber , &kSCPropNetPPPCommConnectDelay , NULL , NULL },
1089 { "CommDisplayTerminalWindow" , NULL , isBoolean , &kSCPropNetPPPCommDisplayTerminalWindow , NULL , NULL },
1090 { "CommRedialCount" , "retry count" , isNumber , &kSCPropNetPPPCommRedialCount , NULL , NULL },
1091 { "CommRedialEnabled" , NULL , isBoolean , &kSCPropNetPPPCommRedialEnabled , NULL , NULL },
1092 { "CommRedialInterval" , "retry delay" , isNumber , &kSCPropNetPPPCommRedialInterval , NULL , NULL },
1093 { "CommTerminalScript" , "script" , isString , &kSCPropNetPPPCommTerminalScript , NULL , NULL },
1094 { "CommUseTerminalScript" , NULL , isBoolean , &kSCPropNetPPPCommUseTerminalScript , NULL , NULL },
1095
1096 // --- CCP: ---
1097 { "CCPEnabled" , NULL , isBoolean , &kSCPropNetPPPCCPEnabled , NULL , NULL },
1098 { "CCPMPPE40Enabled" , NULL , isBoolean , &kSCPropNetPPPCCPMPPE40Enabled , NULL , NULL },
1099 { "CCPMPPE128Enabled" , NULL , isBoolean , &kSCPropNetPPPCCPMPPE128Enabled , NULL , NULL },
1100
1101 // --- IPCP: ---
1102 { "IPCPCompressionVJ" , NULL , isBoolean , &kSCPropNetPPPIPCPCompressionVJ , NULL , NULL },
1103 { "IPCPUsePeerDNS" , NULL , isBoolean , &kSCPropNetPPPIPCPUsePeerDNS , NULL , NULL },
1104
1105 // --- LCP: ---
1106 { "LCPEchoEnabled" , NULL , isBoolean , &kSCPropNetPPPLCPEchoEnabled , NULL , NULL },
1107 { "LCPEchoFailure" , NULL , isNumber , &kSCPropNetPPPLCPEchoFailure , NULL , NULL },
1108 { "LCPEchoInterval" , NULL , isNumber , &kSCPropNetPPPLCPEchoInterval , NULL , NULL },
1109 { "LCPCompressionACField" , NULL , isBoolean , &kSCPropNetPPPLCPCompressionACField , NULL , NULL },
1110 { "LCPCompressionPField" , NULL , isBoolean , &kSCPropNetPPPLCPCompressionPField , NULL , NULL },
1111 { "LCPMRU" , NULL , isNumber , &kSCPropNetPPPLCPMRU , NULL , NULL },
1112 { "LCPMTU" , NULL , isNumber , &kSCPropNetPPPLCPMTU , NULL , NULL },
1113 { "LCPReceiveACCM" , NULL , isNumber , &kSCPropNetPPPLCPReceiveACCM , NULL , NULL },
1114 { "LCPTransmitACCM" , NULL , isNumber , &kSCPropNetPPPLCPTransmitACCM , NULL , NULL },
1115
1116 // --- Help ---
1117 { "?" , NULL , isHelp , NULL , NULL ,
1118 "\nPPP configuration commands\n\n"
1119 " set interface [Account account]\n"
1120 " set interface [Password password]\n"
1121 " set interface [Number telephone-number]\n"
1122 " set interface [AlternateNumber telephone-number]\n"
1123 " set interface [IdleReminder {enable|disable}]\n"
1124 " set interface [IdleReminderTimer time-in-seconds]\n"
1125 " set interface [DisconnectOnIdle {enable|disable}]\n"
1126 " set interface [DisconnectOnIdleTimer time-in-seconds]\n"
1127 " set interface [DisconnectOnLogout {enable|disable}]"
1128 }
1129 };
1130 #define N_PPP_OPTIONS (sizeof(pppOptions) / sizeof(pppOptions[0]))
1131
1132
1133 static Boolean
1134 set_interface_ppp(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1135 {
1136 Boolean ok;
1137
1138 ok = _process_options(pppOptions, N_PPP_OPTIONS, argc, argv, newConfiguration);
1139 return ok;
1140 }
1141
1142
1143 /* -------------------- */
1144
1145
1146 static Boolean
1147 set_interface_vlan(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
1148 {
1149 // xxxxx ("device", "tag")
1150 SCPrint(TRUE, stdout, CFSTR("vlan interface management not yet supported\n"));
1151 return FALSE;
1152 }
1153
1154
1155 /* -------------------- */
1156
1157
1158 __private_extern__
1159 void
1160 set_interface(int argc, char **argv)
1161 {
1162 CFDictionaryRef configuration;
1163 CFStringRef interfaceType;
1164 CFMutableDictionaryRef newConfiguration = NULL;
1165 Boolean ok = FALSE;
1166
1167 if (net_interface == NULL) {
1168 SCPrint(TRUE, stdout, CFSTR("interface not selected\n"));
1169 return;
1170 }
1171
1172 if (argc < 1) {
1173 SCPrint(TRUE, stdout, CFSTR("set what?\n"));
1174 return;
1175 }
1176
1177 configuration = SCNetworkInterfaceGetConfiguration(net_interface);
1178 if (configuration == NULL) {
1179 newConfiguration = CFDictionaryCreateMutable(NULL,
1180 0,
1181 &kCFTypeDictionaryKeyCallBacks,
1182 &kCFTypeDictionaryValueCallBacks);
1183 } else {
1184 newConfiguration = CFDictionaryCreateMutableCopy(NULL, 0, configuration);
1185 CFDictionaryRemoveValue(newConfiguration, kSCResvInactive);
1186 }
1187
1188 interfaceType = SCNetworkInterfaceGetInterfaceType(net_interface);
1189
1190 if (CFEqual(interfaceType, kSCNetworkInterfaceTypeBond)) {
1191 ok = set_interface_bond(argc, argv, newConfiguration);
1192 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeEthernet)) {
1193 ok = set_interface_ethernet(argc, argv, newConfiguration);
1194 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeFireWire)) {
1195 ok = set_interface_firewire(argc, argv, newConfiguration);
1196 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeModem)) {
1197 ok = set_interface_modem(argc, argv, newConfiguration);
1198 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeIEEE80211)) {
1199 ok = set_interface_airport(argc, argv, newConfiguration);
1200 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) {
1201 ok = set_interface_ppp(argc, argv, newConfiguration);
1202 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeVLAN)) {
1203 ok = set_interface_vlan(argc, argv, newConfiguration);
1204 } else {
1205 SCPrint(TRUE, stdout, CFSTR("this interfaces configuration cannot be changed\n"));
1206 }
1207
1208 if (!ok) {
1209 goto done;
1210 }
1211
1212 if (((configuration == NULL) && (CFDictionaryGetCount(newConfiguration) > 0)) ||
1213 ((configuration != NULL) && !CFEqual(configuration, newConfiguration))) {
1214 if (!SCNetworkInterfaceSetConfiguration(net_interface, newConfiguration)) {
1215 if (SCError() == kSCStatusNoKey) {
1216 SCPrint(TRUE, stdout, CFSTR("could not update per-service interface configuration\n"));
1217 } else {
1218 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
1219 }
1220 goto done;
1221 }
1222
1223 _prefs_changed = TRUE;
1224 }
1225
1226 done :
1227
1228 if (newConfiguration != NULL) CFRelease(newConfiguration);
1229 return;
1230 }
1231
1232
1233 /* -------------------- */
1234
1235
1236 __private_extern__
1237 void
1238 show_interface(int argc, char **argv)
1239 {
1240 SCNetworkInterfaceRef interface;
1241
1242 if (argc == 1) {
1243 interface = _find_interface(argv[0]);
1244 } else {
1245 if (net_interface != NULL) {
1246 interface = net_interface;
1247 } else {
1248 SCPrint(TRUE, stdout, CFSTR("interface not selected\n"));
1249 return;
1250 }
1251 }
1252
1253 if (interface != NULL) {
1254 _show_interface(interface, CFSTR(""), TRUE);
1255 }
1256
1257 return;
1258 }
1259
1260
1261 /* -------------------- */
1262
1263
1264 __private_extern__
1265 CFStringRef
1266 _interface_description(SCNetworkInterfaceRef interface)
1267 {
1268 CFMutableStringRef description;
1269 CFStringRef if_bsd_name;
1270 CFStringRef if_type;
1271
1272 description = CFStringCreateMutable(NULL, 0);
1273
1274 if_type = SCNetworkInterfaceGetInterfaceType(interface);
1275 CFStringAppend(description, if_type);
1276
1277 if_bsd_name = SCNetworkInterfaceGetBSDName(interface);
1278 if (if_bsd_name != NULL) {
1279 CFStringAppendFormat(description, NULL, CFSTR(" (%@)"), if_bsd_name);
1280 }
1281
1282 interface = SCNetworkInterfaceGetInterface(interface);
1283 while ((interface != NULL) &&
1284 !CFEqual(interface, kSCNetworkInterfaceIPv4)) {
1285 CFStringRef childDescription;
1286
1287 childDescription = _interface_description(interface);
1288 CFStringAppendFormat(description, NULL, CFSTR(" / %@"), childDescription);
1289 CFRelease(childDescription);
1290
1291 interface = SCNetworkInterfaceGetInterface(interface);
1292 }
1293
1294 return description;
1295 }