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