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