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