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