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