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