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