this repo has no description
at fixPythonPipStalling 1842 lines 54 kB view raw
1/* 2 * Copyright (c) 2004-2009, 2011, 2014, 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 "scutil.h" 33#include "net.h" 34#include "net_protocol.h" 35#include "prefs.h" 36 37#include <sys/types.h> 38#include <sys/socket.h> 39#include <net/if.h> 40#include <netinet/in.h> 41#include <arpa/inet.h> 42 43 44/* -------------------- */ 45 46 47static CFStringRef 48__copyIPv4Address(const char *arg) 49{ 50 char buf[128]; 51 struct sockaddr_in sin; 52 53 if (_SC_string_to_sockaddr(arg, AF_INET, (void *)&sin, sizeof(sin)) == NULL) { 54 return NULL; 55 } 56 57 _SC_sockaddr_to_string((struct sockaddr *)&sin, buf, sizeof(buf)); 58 return CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8); 59} 60 61 62static CFStringRef 63__copyIPv6Address(const char *arg) 64{ 65 char buf[128]; 66 struct sockaddr_in6 sin6; 67 68 if (_SC_string_to_sockaddr(arg, AF_INET6, (void *)&sin6, sizeof(sin6)) == NULL) { 69 return NULL; 70 } 71 72 _SC_sockaddr_to_string((struct sockaddr *)&sin6, buf, sizeof(buf)); 73 return CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8); 74} 75 76 77/* -------------------- */ 78 79 80static SCNetworkProtocolRef 81_find_protocol(char *match) 82{ 83 Boolean allowIndex = TRUE; 84 CFIndex i; 85 CFIndex n; 86 CFStringRef select_name = NULL; 87 SCNetworkProtocolRef selected = NULL; 88 89 if (protocols == NULL) { 90 if (net_service == NULL) { 91 SCPrint(TRUE, stdout, CFSTR("network service not selected\n")); 92 return NULL; 93 } 94 95 protocols = SCNetworkServiceCopyProtocols(net_service); 96 if (protocols == NULL) { 97 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError())); 98 return NULL; 99 } 100 101 n = CFArrayGetCount(protocols); 102 if (n > 1) { 103 CFMutableArrayRef sorted; 104 105 sorted = CFArrayCreateMutableCopy(NULL, 0, protocols); 106 CFArraySortValues(sorted, 107 CFRangeMake(0, n), 108 _SCNetworkProtocolCompare, 109 NULL); 110 CFRelease(protocols); 111 protocols = sorted; 112 } 113 114 allowIndex = FALSE; 115 } 116 117 // try to select the protocol by its protocol type 118 119 select_name = CFStringCreateWithCString(NULL, match, kCFStringEncodingUTF8); 120 121 n = CFArrayGetCount(protocols); 122 for (i = 0; i < n; i++) { 123 SCNetworkProtocolRef protocol; 124 CFStringRef type; 125 126 protocol = CFArrayGetValueAtIndex(protocols, i); 127 type = SCNetworkProtocolGetProtocolType(protocol); 128 if (CFStringCompare(select_name, type, kCFCompareCaseInsensitive) == kCFCompareEqualTo) { 129 selected = protocol; 130 goto done; 131 } 132 } 133 134 if (allowIndex) { 135 char *end; 136 char *str = match; 137 long val; 138 139 // try to select the protocol by its index 140 141 errno = 0; 142 val = strtol(str, &end, 10); 143 if ((*str != '\0') && (*end == '\0') && (errno == 0)) { 144 if ((val > 0) && (val <= n)) { 145 selected = CFArrayGetValueAtIndex(protocols, val - 1); 146 } 147 } 148 } 149 150 if (selected != NULL) { 151 goto done; 152 } 153 154 SCPrint(TRUE, stdout, CFSTR("no match, which protocol?\n")); 155 156 done : 157 158 if (select_name != NULL) CFRelease(select_name); 159 return selected; 160} 161 162 163/* -------------------- */ 164 165 166__private_extern__ 167void 168create_protocol(int argc, char **argv) 169{ 170 SCNetworkInterfaceRef interface; 171 CFStringRef protocolType; 172 173 if ((argc < 1) || (strlen(argv[0]) == 0)) { 174 SCPrint(TRUE, stdout, CFSTR("what protocol type?\n")); 175 return; 176 } 177 178 if (net_service == NULL) { 179 SCPrint(TRUE, stdout, CFSTR("network service not selected\n")); 180 return; 181 } 182 183 protocolType = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8); 184 185 interface = SCNetworkServiceGetInterface(net_service); 186 if (interface != NULL) { 187 CFArrayRef supported; 188 CFIndex i; 189 CFIndex n; 190 191 supported = SCNetworkInterfaceGetSupportedProtocolTypes(interface); 192 n = (supported != NULL) ? CFArrayGetCount(supported) : 0; 193 for (i = 0; i < n; i++) { 194 CFStringRef supportedType; 195 196 supportedType = CFArrayGetValueAtIndex(supported, i); 197 if (CFStringCompare(protocolType, 198 supportedType, 199 kCFCompareCaseInsensitive) == kCFCompareEqualTo) { 200 CFRelease(protocolType); 201 protocolType = CFRetain(supportedType); 202 break; 203 } 204 } 205 } 206 207 if (!SCNetworkServiceAddProtocolType(net_service, protocolType)) { 208 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError())); 209 goto done; 210 } 211 212 _prefs_changed = TRUE; 213 214 if (protocols != NULL) { 215 CFRelease(protocols); 216 protocols = NULL; 217 } 218 219 if (net_protocol != NULL) CFRelease(net_protocol); 220// net_protocol = NULL; 221 222 net_protocol = SCNetworkServiceCopyProtocol(net_service, protocolType); 223 if (net_protocol == NULL) { 224 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError())); 225 goto done; 226 } 227 228 SCPrint(TRUE, stdout, 229 CFSTR("protocol \"%@\" selected\n"), 230 protocolType); 231 232 done : 233 234 CFRelease(protocolType); 235 return; 236} 237 238 239/* -------------------- */ 240 241 242__private_extern__ 243void 244disable_protocol(int argc, char **argv) 245{ 246 SCNetworkProtocolRef protocol = NULL; 247 248 if (argc > 0) { 249 protocol = _find_protocol(argv[0]); 250 } else { 251 if (net_protocol != NULL) { 252 protocol = net_protocol; 253 } else { 254 SCPrint(TRUE, stdout, CFSTR("protocol not selected\n")); 255 return; 256 } 257 } 258 259 if (protocol == NULL) { 260 return; 261 } 262 263 if (!SCNetworkProtocolSetEnabled(protocol, FALSE)) { 264 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError())); 265 return; 266 } 267 268 _prefs_changed = TRUE; 269 270 return; 271} 272 273 274/* -------------------- */ 275 276 277__private_extern__ 278void 279enable_protocol(int argc, char **argv) 280{ 281 SCNetworkProtocolRef protocol = NULL; 282 283 if (argc > 0) { 284 protocol = _find_protocol(argv[0]); 285 } else { 286 if (net_protocol != NULL) { 287 protocol = net_protocol; 288 } else { 289 SCPrint(TRUE, stdout, CFSTR("protocol not selected\n")); 290 return; 291 } 292 } 293 294 if (protocol == NULL) { 295 return; 296 } 297 298 if (!SCNetworkProtocolSetEnabled(protocol, TRUE)) { 299 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError())); 300 return; 301 } 302 303 _prefs_changed = TRUE; 304 305 return; 306} 307 308 309/* -------------------- */ 310 311 312__private_extern__ 313void 314remove_protocol(int argc, char **argv) 315{ 316 SCNetworkProtocolRef protocol = NULL; 317 CFStringRef protocolType; 318 319 if (argc > 0) { 320 protocol = _find_protocol(argv[0]); 321 } else { 322 if (net_protocol != NULL) { 323 protocol = net_protocol; 324 } else { 325 SCPrint(TRUE, stdout, CFSTR("protocol not selected\n")); 326 return; 327 } 328 } 329 330 if (protocol == NULL) { 331 return; 332 } 333 334 CFRetain(protocol); 335 336 protocolType = SCNetworkProtocolGetProtocolType(protocol); 337 if (!SCNetworkServiceRemoveProtocolType(net_service, protocolType)) { 338 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError())); 339 goto done; 340 } 341 342 _prefs_changed = TRUE; 343 344 SCPrint(TRUE, stdout, 345 CFSTR("protocol \"%@\" removed\n"), 346 protocolType); 347 348 if ((net_protocol != NULL) && CFEqual(protocol, net_protocol)) { 349 CFRelease(net_protocol); 350 net_protocol = NULL; 351 SCPrint(TRUE, stdout, CFSTR("& no protocol selected\n")); 352 } 353 354 if (protocols != NULL) { 355 CFRelease(protocols); 356 protocols = NULL; 357 } 358 359 done : 360 361 CFRelease(protocol); 362 return; 363} 364 365 366/* -------------------- */ 367 368 369__private_extern__ 370void 371select_protocol(int argc, char **argv) 372{ 373#pragma unused(argc) 374 SCNetworkProtocolRef protocol; 375 376 protocol = _find_protocol(argv[0]); 377 378 if (protocol == NULL) { 379 return; 380 } 381 382 if (net_protocol != NULL) CFRelease(net_protocol); 383 net_protocol = CFRetain(protocol); 384 385 SCPrint(TRUE, stdout, 386 CFSTR("protocol \"%@\" selected\n"), 387 SCNetworkProtocolGetProtocolType(protocol)); 388 389 return; 390} 391 392 393#pragma mark - 394#pragma mark DNS 395 396 397static CF_RETURNS_RETAINED CFStringRef 398__cleanupDomainName(CFStringRef domain) 399{ 400 CFMutableStringRef newDomain; 401 402 newDomain = CFStringCreateMutableCopy(NULL, 0, domain); 403 CFStringTrimWhitespace(newDomain); 404 CFStringTrim(newDomain, CFSTR(".")); 405 if (CFStringGetLength(newDomain) == 0) { 406 CFRelease(newDomain); 407 newDomain = NULL; 408 } 409 410 return newDomain; 411} 412 413 414static int 415__doDNSDomain(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration) 416{ 417#pragma unused(description) 418#pragma unused(info) 419 if (argc < 1) { 420 SCPrint(TRUE, stdout, CFSTR("DNS domain name not specified\n")); 421 return -1; 422 } 423 424 if (strlen(argv[0]) > 0) { 425 CFStringRef domain; 426 CFStringRef str; 427 428 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8); 429 domain = __cleanupDomainName(str); 430 CFRelease(str); 431 432 if (domain != NULL) { 433 CFDictionarySetValue(newConfiguration, key, domain); 434 CFRelease(domain); 435 } else { 436 SCPrint(TRUE, stdout, CFSTR("invalid DNS domain name\n")); 437 return -1; 438 } 439 } else { 440 CFDictionaryRemoveValue(newConfiguration, key); 441 } 442 443 return 1; 444} 445 446 447static int 448__doDNSDomainArray(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration) 449{ 450#pragma unused(description) 451#pragma unused(info) 452 CFMutableArrayRef domains; 453 454 if (argc < 1) { 455 SCPrint(TRUE, stdout, CFSTR("DNS search domain name(s) not specified\n")); 456 return -1; 457 } 458 459 domains = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 460 461 if (strlen(argv[0]) > 0) { 462 CFArrayRef array; 463 CFStringRef str; 464 465 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8); 466 array = CFStringCreateArrayBySeparatingStrings(NULL, str, CFSTR(",")); 467 CFRelease(str); 468 469 if (array != NULL) { 470 CFIndex i; 471 CFIndex n = CFArrayGetCount(array); 472 473 for (i = 0; i < n; i++) { 474 CFStringRef domain; 475 476 domain = __cleanupDomainName(CFArrayGetValueAtIndex(array, i)); 477 if (domain != NULL) { 478 CFArrayAppendValue(domains, domain); 479 CFRelease(domain); 480 } else { 481 CFRelease(array); 482 CFRelease(domains); 483 SCPrint(TRUE, stdout, CFSTR("invalid DNS search domain name\n")); 484 return -1; 485 } 486 } 487 CFRelease(array); 488 } 489 } 490 491 if (CFArrayGetCount(domains) > 0) { 492 CFDictionarySetValue(newConfiguration, key, domains); 493 } else { 494 CFDictionaryRemoveValue(newConfiguration, key); 495 } 496 497 CFRelease(domains); 498 return 1; 499} 500 501 502static int 503__doDNSServerAddresses(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration) 504{ 505#pragma unused(description) 506#pragma unused(info) 507 CFMutableArrayRef servers; 508 509 if (argc < 1) { 510 SCPrint(TRUE, stdout, CFSTR("DNS name server address(es) not specified\n")); 511 return -1; 512 } 513 514 servers = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 515 516 if (strlen(argv[0]) > 0) { 517 CFArrayRef array; 518 CFIndex i; 519 CFIndex n; 520 CFStringRef str; 521 522 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8); 523 array = CFStringCreateArrayBySeparatingStrings(NULL, str, CFSTR(",")); 524 CFRelease(str); 525 526 n = (array != NULL) ? CFArrayGetCount(array) : 0; 527 for (i = 0; i < n; i++) { 528 char str[32]; 529 530 if (_SC_cfstring_to_cstring(CFArrayGetValueAtIndex(array, i), 531 str, 532 sizeof(str), 533 kCFStringEncodingUTF8) != NULL) { 534 CFStringRef server; 535 536 server = __copyIPv4Address(str); 537 if (server == NULL) { 538 server = __copyIPv6Address(str); 539 } 540 if (server != NULL) { 541 CFArrayAppendValue(servers, server); 542 CFRelease(server); 543 continue; 544 } 545 } 546 547 SCPrint(TRUE, stdout, CFSTR("invalid DNS name server address\n")); 548 CFRelease(array); 549 CFRelease(servers); 550 return -1; 551 } 552 if (array != NULL) CFRelease(array); 553 } 554 555 if (CFArrayGetCount(servers) > 0) { 556 CFDictionarySetValue(newConfiguration, key, servers); 557 } else { 558 CFDictionaryRemoveValue(newConfiguration, key); 559 } 560 561 CFRelease(servers); 562 return 1; 563} 564 565 566static options dnsOptions[] = { 567 { "DomainName" , "domain" , isOther, &kSCPropNetDNSDomainName , __doDNSDomain , NULL }, 568 { "domain" , "domain" , isOther, &kSCPropNetDNSDomainName , __doDNSDomain , NULL }, 569 { "SearchDomains" , "search" , isOther, &kSCPropNetDNSSearchDomains , __doDNSDomainArray , NULL }, 570 { "search" , "search" , isOther, &kSCPropNetDNSSearchDomains , __doDNSDomainArray , NULL }, 571 { "ServerAddresses", "address", isOther, &kSCPropNetDNSServerAddresses, __doDNSServerAddresses, NULL }, 572 { "nameserver" , "address", isOther, &kSCPropNetDNSServerAddresses, __doDNSServerAddresses, NULL }, 573 { "nameservers" , "address", isOther, &kSCPropNetDNSServerAddresses, __doDNSServerAddresses, NULL }, 574 { "SupplementalMatchDomains", 575 "domain", 576 isOther, 577 &kSCPropNetDNSSupplementalMatchDomains, 578 __doDNSDomainArray, 579 NULL }, 580 581 { "?" , NULL , isHelp , NULL , NULL, 582 "\nDNS configuration commands\n\n" 583 " set protocol search domain-name[,domain-name-2]\n" 584 " set protocol nameserver x1.x1.x1.x1[,x2.x2.x2.x2]\n" 585 } 586}; 587#define N_DNS_OPTIONS (sizeof(dnsOptions) / sizeof(dnsOptions[0])) 588 589 590static Boolean 591set_protocol_dns(int argc, char **argv, CFMutableDictionaryRef newConfiguration) 592{ 593 Boolean ok; 594 595 ok = _process_options(dnsOptions, N_DNS_OPTIONS, argc, argv, newConfiguration); 596 return ok; 597} 598 599 600#pragma mark - 601#pragma mark IPv4 602 603 604#define allowIPv4Address 1<<1 // allow address 605#define allowIPv4Netmask 1<<2 // allow subnet mask 606#define allowIPv4Router 1<<3 // allow router 607#define allowIPv4DHCPClientID 1<<4 // allow DCHP Client ID 608 609static selections ipv4ConfigMethods[] = { 610 { CFSTR("BOOTP") , &kSCValNetIPv4ConfigMethodBOOTP , 0 }, 611 { CFSTR("DHCP") , &kSCValNetIPv4ConfigMethodDHCP , allowIPv4DHCPClientID }, 612 { CFSTR("INFORM") , &kSCValNetIPv4ConfigMethodINFORM , allowIPv4Address }, 613 { CFSTR("LinkLocal"), &kSCValNetIPv4ConfigMethodLinkLocal, 0 }, 614 { CFSTR("Manual") , &kSCValNetIPv4ConfigMethodManual , allowIPv4Address|allowIPv4Netmask|allowIPv4Router }, 615 { CFSTR("PPP") , &kSCValNetIPv4ConfigMethodPPP , allowIPv4Address|selectionNotAvailable }, 616 { NULL , NULL , 0 } 617}; 618 619 620static int 621__doIPv4ConfigMethod(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration) 622{ 623#pragma unused(description) 624#pragma unused(info) 625#pragma unused(argc) 626#pragma unused(argv) 627 unsigned int flags; 628 CFStringRef method; 629 CFIndex methodIndex; 630 631 method = CFDictionaryGetValue(newConfiguration, key); 632 methodIndex = _find_selection(method, (selections *)ipv4ConfigMethods, &flags); 633 if (methodIndex != kCFNotFound) { 634 if (!(flags & allowIPv4Address)) { 635 CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv4Addresses); 636 } 637 if (!(flags & allowIPv4Netmask)) { 638 CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv4SubnetMasks); 639 } 640 if (!(flags & allowIPv4Router)) { 641 CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv4Router); 642 } 643 if (!(flags & allowIPv4DHCPClientID)) { 644 CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv4DHCPClientID); 645 } 646 } else { 647 SCPrint(TRUE, stdout, CFSTR("unknown configuration method\n")); 648 return -1; 649 } 650 651 return 0; 652} 653 654 655static int 656__doIPv4Addresses(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration) 657{ 658#pragma unused(description) 659#pragma unused(argc) 660 Boolean useArray = (info == (void *)FALSE) ? FALSE : TRUE; 661 662 if (strlen(argv[0]) > 0) { 663 CFStringRef address; 664 665 address = __copyIPv4Address(argv[0]); 666 if (address != NULL) { 667 if (useArray) { 668 CFArrayRef addresses; 669 670 addresses = CFArrayCreate(NULL, (const void **)&address, 1, &kCFTypeArrayCallBacks); 671 CFDictionarySetValue(newConfiguration, key, addresses); 672 CFRelease(addresses); 673 } else { 674 CFDictionarySetValue(newConfiguration, key, address); 675 } 676 CFRelease(address); 677 } else { 678 return -1; 679 } 680 } else { 681 CFDictionaryRemoveValue(newConfiguration, key); 682 } 683 684 return 1; 685} 686 687 688static options ipv4Options[] = { 689 { "ConfigMethod", "configuration method" 690 , isChooseOne , &kSCPropNetIPv4ConfigMethod, __doIPv4ConfigMethod, (void *)ipv4ConfigMethods }, 691 { "config" , "configuration method" 692 , isChooseOne , &kSCPropNetIPv4ConfigMethod, __doIPv4ConfigMethod, (void *)ipv4ConfigMethods }, 693 { "Addresses" , "address" , isOther , &kSCPropNetIPv4Addresses , __doIPv4Addresses , (void *)TRUE }, 694 { "address" , "address" , isOther , &kSCPropNetIPv4Addresses , __doIPv4Addresses , (void *)TRUE }, 695 { "SubnetMasks" , "netmask" , isOther , &kSCPropNetIPv4SubnetMasks , __doIPv4Addresses , (void *)TRUE }, 696 { "netmask" , "netmask" , isOther , &kSCPropNetIPv4SubnetMasks , __doIPv4Addresses , (void *)TRUE }, 697 { "Router" , "address" , isOther , &kSCPropNetIPv4Router , __doIPv4Addresses , (void *)FALSE }, 698 { "DHCPClientID", "client ID", isString , &kSCPropNetIPv4DHCPClientID, NULL , NULL }, 699 700 { "?" , NULL , isHelp , NULL , NULL , 701 "\nIPv4 configuration commands\n\n" 702 " set protocol config {BOOTP|DHCP|INFORM|MANUAL}\n" 703 "\n w/config=BOOTP\n" 704 " None\n" 705 "\n w/config=DHCP\n" 706 " set protocol dhcpclientid identifier\n" 707 "\n w/config=INFORM\n" 708 " set protocol address x.x.x.x\n" 709 "\n w/config=MANUAL\n" 710 " set protocol address x.x.x.x\n" 711 " set protocol netmask x.x.x.x\n" 712 " set protocol router x.x.x.x\n" 713 } 714}; 715#define N_IPV4_OPTIONS (sizeof(ipv4Options) / sizeof(ipv4Options[0])) 716 717 718static Boolean 719set_protocol_ipv4(int argc, char **argv, CFMutableDictionaryRef newConfiguration) 720{ 721 Boolean ok; 722 723 ok = _process_options(ipv4Options, N_IPV4_OPTIONS, argc, argv, newConfiguration); 724 if (ok) { 725 unsigned int flags; 726 CFStringRef method; 727 CFIndex methodIndex; 728 729 // validate configuration 730 method = CFDictionaryGetValue(newConfiguration, kSCPropNetIPv4ConfigMethod); 731 methodIndex = _find_selection(method, (selections *)ipv4ConfigMethods, &flags); 732 if (methodIndex == kCFNotFound) { 733 SCPrint(TRUE, stdout, CFSTR("unknown configuration method\n")); 734 return FALSE; 735 } 736 737 if (!(flags & allowIPv4Address) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv4Addresses)) { 738 SCPrint(TRUE, stdout, 739 CFSTR("IP address not allowed with %@ configuration\n"), 740 ipv4ConfigMethods[methodIndex].selection); 741 return FALSE; 742 } 743 744 if (!(flags & allowIPv4Netmask) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv4SubnetMasks)) { 745 SCPrint(TRUE, stdout, 746 CFSTR("Subnet mask not allowed with %@ configuration\n"), 747 ipv4ConfigMethods[methodIndex].selection); 748 return FALSE; 749 } 750 751 if (!(flags & allowIPv4Router) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv4Router)) { 752 SCPrint(TRUE, stdout, 753 CFSTR("Default route not allowed with %@ configuration\n"), 754 ipv4ConfigMethods[methodIndex].selection); 755 return FALSE; 756 } 757 758 if (!(flags & allowIPv4DHCPClientID) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv4DHCPClientID)) { 759 SCPrint(TRUE, stdout, 760 CFSTR("DHCP client ID not allowed with %@ configuration\n"), 761 ipv4ConfigMethods[methodIndex].selection); 762 return FALSE; 763 } 764 } 765 766 return ok; 767} 768 769 770#pragma mark - 771#pragma mark IPv6 772 773 774#define allowIPv6Address 1<<1 // allow address 775#define allowIPv6PrefixLength 1<<2 // allow prefix length 776#define allowIPv6Router 1<<3 // allow router 777 778static selections ipv6ConfigMethods[] = { 779 { CFSTR("Automatic") , & kSCValNetIPv6ConfigMethodAutomatic , 0 }, 780 { CFSTR("Manual") , & kSCValNetIPv6ConfigMethodManual , allowIPv6Address|allowIPv6PrefixLength|allowIPv6Router }, 781 { CFSTR("RouterAdvertisement"), & kSCValNetIPv6ConfigMethodRouterAdvertisement, allowIPv6Address }, 782 { CFSTR("6to4") , & kSCValNetIPv6ConfigMethod6to4 , 0 }, 783 { NULL , NULL , 0 } 784}; 785 786 787static int 788__doIPv6ConfigMethod(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration) 789{ 790#pragma unused(description) 791#pragma unused(info) 792#pragma unused(argc) 793#pragma unused(argv) 794 unsigned int flags; 795 CFStringRef method; 796 CFIndex methodIndex; 797 798 method = CFDictionaryGetValue(newConfiguration, key); 799 methodIndex = _find_selection(method, (selections *)ipv6ConfigMethods, &flags); 800 if (methodIndex != kCFNotFound) { 801 if (!(flags & allowIPv6Address)) { 802 CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv6Addresses); 803 } 804 if (!(flags & allowIPv6PrefixLength)) { 805 CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv6PrefixLength); 806 } 807 if (!(flags & allowIPv6Router)) { 808 CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv6Router); 809 } 810 } else { 811 SCPrint(TRUE, stdout, CFSTR("unknown configuration method\n")); 812 return -1; 813 } 814 815 return 0; 816} 817 818 819static int 820__doIPv6Addresses(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration) 821{ 822#pragma unused(description) 823#pragma unused(argc) 824 Boolean useArray = (info == (void *)FALSE) ? FALSE : TRUE; 825 826 if (strlen(argv[0]) > 0) { 827 CFStringRef address; 828 829 address = __copyIPv6Address(argv[0]); 830 if (address != NULL) { 831 if (useArray) { 832 CFArrayRef addresses; 833 834 addresses = CFArrayCreate(NULL, (const void **)&address, 1, &kCFTypeArrayCallBacks); 835 CFDictionarySetValue(newConfiguration, key, addresses); 836 CFRelease(addresses); 837 } else { 838 CFDictionarySetValue(newConfiguration, key, address); 839 } 840 CFRelease(address); 841 } else { 842 return -1; 843 } 844 } else { 845 CFDictionaryRemoveValue(newConfiguration, key); 846 } 847 848 return 1; 849} 850 851 852static options ipv6Options[] = { 853 { "ConfigMethod", "configuration method" 854 , isChooseOne, &kSCPropNetIPv6ConfigMethod, __doIPv6ConfigMethod, (void *)ipv6ConfigMethods }, 855 { "config" , "configuration method" 856 , isChooseOne, &kSCPropNetIPv6ConfigMethod, __doIPv6ConfigMethod, (void *)ipv6ConfigMethods }, 857 { "Addresses" , "address" , isOther , &kSCPropNetIPv6Addresses , __doIPv6Addresses , (void *)TRUE }, 858 { "address" , "address" , isOther , &kSCPropNetIPv6Addresses , __doIPv6Addresses , (void *)TRUE }, 859 { "EnableCGA" , NULL , isBoolean , &kSCPropNetIPv6EnableCGA , NULL , NULL }, 860 { "PrefixLength", "prefix length", isNumber , &kSCPropNetIPv6PrefixLength, NULL , NULL }, 861 { "Router" , "address" , isOther , &kSCPropNetIPv6Router , __doIPv6Addresses , (void *)FALSE }, 862 863 { "?" , NULL , isHelp , NULL , NULL , 864 "\nIPv6 configuration commands\n\n" 865 " set protocol config {Automatic|MANUAL}\n" 866 "\n w/config=Automatic\n" 867 " None\n" 868 "\n w/config=MANUAL\n" 869 " set protocol address x:x:x:x:x:x\n" 870 " set protocol router x:x:x:x:x:x\n" 871 " set protocol prefixlength n\n" 872 } 873}; 874#define N_IPV6_OPTIONS (sizeof(ipv6Options) / sizeof(ipv6Options[0])) 875 876 877static Boolean 878set_protocol_ipv6(int argc, char **argv, CFMutableDictionaryRef newConfiguration) 879{ 880 Boolean ok; 881 882 ok = _process_options(ipv6Options, N_IPV6_OPTIONS, argc, argv, newConfiguration); 883 if (ok) { 884 unsigned int flags; 885 CFStringRef method; 886 CFIndex methodIndex; 887 888 // validate configuration 889 method = CFDictionaryGetValue(newConfiguration, kSCPropNetIPv6ConfigMethod); 890 methodIndex = _find_selection(method, (selections *)ipv6ConfigMethods, &flags); 891 if (methodIndex == kCFNotFound) { 892 SCPrint(TRUE, stdout, CFSTR("unknown configuration method\n")); 893 return FALSE; 894 } 895 896 if (!(flags & allowIPv6Address) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv6Addresses)) { 897 SCPrint(TRUE, stdout, 898 CFSTR("IP address not allowed with %@ configuration\n"), 899 ipv6ConfigMethods[methodIndex].selection); 900 return FALSE; 901 } 902 903 if (!(flags & allowIPv6PrefixLength) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv6PrefixLength)) { 904 SCPrint(TRUE, stdout, 905 CFSTR("Prefix length not allowed with %@ configuration\n"), 906 ipv6ConfigMethods[methodIndex].selection); 907 return FALSE; 908 } 909 910 if (!(flags & allowIPv6Router) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv6Router)) { 911 SCPrint(TRUE, stdout, 912 CFSTR("Router not allowed with %@ configuration\n"), 913 ipv6ConfigMethods[methodIndex].selection); 914 return FALSE; 915 } 916 } 917 918 return ok; 919} 920 921 922#pragma mark - 923#pragma mark Proxies 924 925 926typedef const struct { 927 const char *proxy; 928 const CFStringRef *keyEnable; 929 const CFStringRef *keyProxy; 930 const CFStringRef *keyPort; 931 const CFStringRef *keyURL; 932} proxyKeys; 933 934static proxyKeys proxyKeys_FTP = { "FTP" , &kSCPropNetProxiesFTPEnable , &kSCPropNetProxiesFTPProxy , &kSCPropNetProxiesFTPPort , NULL }; 935static proxyKeys proxyKeys_Gopher = { "Gopher", &kSCPropNetProxiesGopherEnable , &kSCPropNetProxiesGopherProxy, &kSCPropNetProxiesGopherPort, NULL }; 936static proxyKeys proxyKeys_HTTP = { "HTTP" , &kSCPropNetProxiesHTTPEnable , &kSCPropNetProxiesHTTPProxy , &kSCPropNetProxiesHTTPPort , NULL }; 937static proxyKeys proxyKeys_HTTPS = { "HTTPS" , &kSCPropNetProxiesHTTPSEnable , &kSCPropNetProxiesHTTPSProxy , &kSCPropNetProxiesHTTPSPort , NULL }; 938static proxyKeys proxyKeys_RTSP = { "RTSP" , &kSCPropNetProxiesRTSPEnable , &kSCPropNetProxiesRTSPProxy , &kSCPropNetProxiesRTSPPort , NULL }; 939static proxyKeys proxyKeys_SOCKS = { "SOCKS" , &kSCPropNetProxiesSOCKSEnable , &kSCPropNetProxiesSOCKSProxy , &kSCPropNetProxiesSOCKSPort , NULL }; 940static proxyKeys proxyKeys_PAC = { ".pac" , &kSCPropNetProxiesProxyAutoConfigEnable , NULL , NULL , &kSCPropNetProxiesProxyAutoConfigURLString }; 941static proxyKeys proxyKeys_WPAD = { "WPAD" , &kSCPropNetProxiesProxyAutoDiscoveryEnable, NULL , NULL , NULL }; 942 943static proxyKeys *currentProxy = NULL; 944 945 946static int __doProxySelect (CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration); 947static int __doProxyEnable (CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration); 948static int __doProxyHost (CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration); 949static int __doProxyPort (CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration); 950static int __doProxyURL (CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration); 951static int __doProxyFTPPassive(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration); 952 953 954static options proxyOptions[] = { 955 // general options 956 { "ExceptionsList" , "exceptions", isStringArray, &kSCPropNetProxiesExceptionsList , NULL , NULL }, 957 { "ExcludeSimpleHostnames", NULL , isBoolean , &kSCPropNetProxiesExcludeSimpleHostnames, NULL , NULL }, 958 // proxy selection 959 { "FTP" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_FTP }, 960 { "Gopher" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_Gopher }, 961 { "HTTP" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_HTTP }, 962 { "HTTPS" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_HTTPS }, 963 { "RTSP" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_RTSP }, 964 { "SOCKS" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_SOCKS }, 965 { "ProxyAutoConfig" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_PAC }, 966 { ".pac" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_PAC }, 967 { "ProxyAutoDiscovery" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_WPAD }, 968 { "WPAD" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_WPAD }, 969 // proxy modifiers 970 { "disable" , NULL , isOther , NULL , __doProxyEnable , (void *)FALSE }, 971 { "enable" , NULL , isOther , NULL , __doProxyEnable , (void *)TRUE }, 972 { "proxy" , NULL , isOther , NULL , __doProxyHost , NULL }, 973 { "host" , NULL , isOther , NULL , __doProxyHost , NULL }, 974 { "port" , NULL , isOther , NULL , __doProxyPort , NULL }, 975 { "url" , NULL , isOther , NULL , __doProxyURL , NULL }, 976 // (ftp) proxy modifiers 977 { "FTPPassive" , NULL , isBoolean , &kSCPropNetProxiesFTPPassive , __doProxyFTPPassive, NULL }, 978 { "passive" , NULL , isBoolean , &kSCPropNetProxiesFTPPassive , __doProxyFTPPassive, NULL }, 979 // help 980 { "?" , NULL , isHelp , NULL , NULL , 981 "\nProxy configuration commands\n\n" 982 " set protocol ExceptionsList exception[,exception-2]\n" 983 " set protocol ExcludeSimpleHostnames {enable|disable}\n" 984 "\n" 985 " set protocol ftp {enable|disable}\n" 986 " set protocol ftp host proxy-host\n" 987 " set protocol ftp port proxy-port\n" 988 " set protocol ftp passive {enable|disable}\n" 989 "\n" 990 " set protocol http {enable|disable}\n" 991 " set protocol http host proxy-host\n" 992 " set protocol http port proxy-port\n" 993 "\n" 994 " set protocol https {enable|disable}\n" 995 " set protocol https host proxy-host\n" 996 " set protocol https port proxy-port\n" 997 "\n" 998 " set protocol rtsp {enable|disable}\n" 999 " set protocol rtsp host proxy-host\n" 1000 " set protocol rtsp port proxy-port\n" 1001 "\n" 1002 " set protocol socks {enable|disable}\n" 1003 " set protocol socks host proxy-host\n" 1004 " set protocol socks port proxy-port\n" 1005 "\n" 1006 " set protocol .pac {enable|disable}\n" 1007 " set protocol .pac url .pac-url\n" 1008 "\n" 1009 " set protocol wpad {enable|disable}\n" 1010 } 1011}; 1012#define N_PROXY_OPTIONS (sizeof(proxyOptions) / sizeof(proxyOptions[0])) 1013 1014 1015static int 1016__doProxySelect(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration) 1017{ 1018#pragma unused(key) 1019#pragma unused(description) 1020#pragma unused(newConfiguration) 1021 CFIndex nextOption; 1022 1023 if (argc < 1) { 1024 SCPrint(TRUE, stdout, CFSTR("proxy option[s] not specified\n")); 1025 return -1; 1026 } 1027 1028 currentProxy = (proxyKeys *)info; 1029 1030 nextOption = _find_option(argv[0], proxyOptions, N_PROXY_OPTIONS); 1031 if ((nextOption == kCFNotFound) || 1032 (proxyOptions[nextOption].handler == __doProxySelect)) { 1033 SCPrint(TRUE, stdout, CFSTR("%s proxy option[s] not specified\n"), currentProxy->proxy); 1034 return -1; 1035 } 1036 1037 return 0; 1038} 1039 1040 1041static int 1042__doProxyEnable(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration) 1043{ 1044#pragma unused(key) 1045#pragma unused(description) 1046#pragma unused(argc) 1047#pragma unused(argv) 1048 Boolean enabled = (info == (void *)FALSE) ? FALSE : TRUE; 1049 1050 if (currentProxy == NULL) { 1051 SCPrint(TRUE, stdout, CFSTR("proxy not specified\n")); 1052 return -1; 1053 } 1054 1055 if (currentProxy->keyEnable == NULL) { 1056 SCPrint(TRUE, stdout, CFSTR("%s proxy cannot be %s\n"), 1057 currentProxy->proxy, 1058 enabled ? "enabled" : "disabled"); 1059 return -1; 1060 } 1061 1062 1063 if (enabled) { 1064 CFDictionarySetValue(newConfiguration, *(currentProxy->keyEnable), CFNumberRef_1); 1065 } else { 1066 CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyEnable)); 1067 1068 if (currentProxy->keyProxy != NULL) { 1069 CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyProxy)); 1070 } 1071 1072 if (currentProxy->keyPort != NULL) { 1073 CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyPort)); 1074 } 1075 1076 if (currentProxy->keyURL != NULL) { 1077 CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyURL)); 1078 } 1079 } 1080 1081 return 0; 1082} 1083 1084 1085static Boolean 1086__proxy_enabled(CFDictionaryRef configuration, const CFStringRef *enableKey) 1087{ 1088 CFNumberRef num; 1089 int val; 1090 1091 if (enableKey == NULL) { 1092 return TRUE; // if proxy does not need to be enabled 1093 } 1094 1095 num = CFDictionaryGetValue(configuration, *enableKey); 1096 if (!isA_CFNumber(num) || 1097 !CFNumberGetValue(num, kCFNumberIntType, &val) || 1098 (val == 0)) { 1099 return FALSE; // if not enabled 1100 } 1101 1102 return TRUE; 1103} 1104 1105 1106static int 1107__doProxyHost(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration) 1108{ 1109#pragma unused(key) 1110#pragma unused(description) 1111#pragma unused(info) 1112 if (currentProxy == NULL) { 1113 SCPrint(TRUE, stdout, CFSTR("proxy not specified\n")); 1114 return -1; 1115 } 1116 1117 if (currentProxy->keyProxy == NULL) { 1118 SCPrint(TRUE, stdout, CFSTR("%s proxy host cannot be specified\n"), currentProxy->proxy); 1119 return -1; 1120 } 1121 1122 if (!__proxy_enabled(newConfiguration, currentProxy->keyEnable)) { 1123 SCPrint(TRUE, stdout, CFSTR("%s proxy not enabled\n"), currentProxy->proxy); 1124 return -1; 1125 } 1126 1127 if (argc < 1) { 1128 SCPrint(TRUE, stdout, CFSTR("%s proxy host not specified\n"), currentProxy->proxy); 1129 return -1; 1130 } 1131 1132 if (strlen(argv[0]) > 0) { 1133 CFStringRef host; 1134 1135 host = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8); 1136 CFDictionarySetValue(newConfiguration, *(currentProxy->keyProxy), host); 1137 CFRelease(host); 1138 } else { 1139 CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyProxy)); 1140 } 1141 1142 return 1; 1143} 1144 1145 1146static int 1147__doProxyPort(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration) 1148{ 1149#pragma unused(key) 1150#pragma unused(description) 1151#pragma unused(info) 1152 if (currentProxy == NULL) { 1153 SCPrint(TRUE, stdout, CFSTR("proxy not specified\n")); 1154 return -1; 1155 } 1156 1157 if (currentProxy->keyPort == NULL) { 1158 SCPrint(TRUE, stdout, CFSTR("%s proxy port cannot be specified\n"), currentProxy->proxy); 1159 return -1; 1160 } 1161 1162 if (!__proxy_enabled(newConfiguration, currentProxy->keyEnable)) { 1163 SCPrint(TRUE, stdout, CFSTR("%s proxy not enabled\n"), currentProxy->proxy); 1164 return -1; 1165 } 1166 1167 if (argc < 1) { 1168 SCPrint(TRUE, stdout, CFSTR("%s proxy port not specified\n"), currentProxy->proxy); 1169 return -1; 1170 } 1171 1172 if (strlen(argv[0]) > 0) { 1173 CFNumberRef num; 1174 int port; 1175 1176 num = _copy_number(argv[0]); 1177 if (!isA_CFNumber(num) || 1178 !CFNumberGetValue(num, kCFNumberIntType, &port) || 1179 (port < 0) || (port > 65535)) { 1180 SCPrint(TRUE, stdout, CFSTR("invalid %s proxy port number\n"), currentProxy->proxy); 1181 if (num != NULL) CFRelease(num); 1182 return -1; 1183 } 1184 1185 CFDictionarySetValue(newConfiguration, *(currentProxy->keyPort), num); 1186 CFRelease(num); 1187 } else { 1188 CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyPort)); 1189 } 1190 1191 return 1; 1192} 1193 1194 1195static int 1196__doProxyURL(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration) 1197{ 1198#pragma unused(key) 1199#pragma unused(description) 1200#pragma unused(info) 1201 if (currentProxy == NULL) { 1202 SCPrint(TRUE, stdout, CFSTR("proxy not specified\n")); 1203 return -1; 1204 } 1205 1206 if (currentProxy->keyURL == NULL) { 1207 SCPrint(TRUE, stdout, CFSTR("%s proxy URL cannot be specified\n"), currentProxy->proxy); 1208 return -1; 1209 } 1210 1211 if (!__proxy_enabled(newConfiguration, currentProxy->keyEnable)) { 1212 SCPrint(TRUE, stdout, CFSTR("%s proxy not enabled\n"), currentProxy->proxy); 1213 return -1; 1214 } 1215 1216 if (argc < 1) { 1217 SCPrint(TRUE, stdout, CFSTR("%s proxy URL not specified\n"), currentProxy->proxy); 1218 return -1; 1219 } 1220 1221 if (strlen(argv[0]) > 0) { 1222 CFStringRef url; 1223 1224 url = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8); 1225 CFDictionarySetValue(newConfiguration, *(currentProxy->keyURL), url); 1226 CFRelease(url); 1227 } else { 1228 CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyURL)); 1229 } 1230 1231 return 1; 1232} 1233 1234 1235static int 1236__doProxyFTPPassive(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration) 1237{ 1238#pragma unused(key) 1239#pragma unused(description) 1240#pragma unused(info) 1241#pragma unused(argc) 1242#pragma unused(argv) 1243#pragma unused(newConfiguration) 1244 if (currentProxy == NULL) { 1245 SCPrint(TRUE, stdout, CFSTR("proxy not specified\n")); 1246 return -1; 1247 } 1248 1249 if (currentProxy != &proxyKeys_FTP) { 1250 SCPrint(TRUE, stdout, CFSTR("passive can only be enable for FTP proxy\n")); 1251 return -1; 1252 } 1253 1254 return 0; 1255} 1256 1257 1258static Boolean 1259set_protocol_proxies(int argc, char **argv, CFMutableDictionaryRef newConfiguration) 1260{ 1261 Boolean ok; 1262 1263 ok = _process_options(proxyOptions, N_PROXY_OPTIONS, argc, argv, newConfiguration); 1264 return ok; 1265} 1266 1267 1268#pragma mark - 1269#pragma mark SMB 1270 1271 1272#if !TARGET_OS_IPHONE 1273 1274 1275static CF_RETURNS_RETAINED CFStringRef 1276__cleanupName(CFStringRef name) 1277{ 1278 CFMutableStringRef newName; 1279 1280 newName = CFStringCreateMutableCopy(NULL, 0, name); 1281 CFStringTrimWhitespace(newName); 1282 if (CFStringGetLength(newName) == 0) { 1283 CFRelease(newName); 1284 newName = NULL; 1285 } 1286 1287 return newName; 1288} 1289 1290 1291static int 1292__doSMBName(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration) 1293{ 1294#pragma unused(description) 1295#pragma unused(info) 1296 if (argc < 1) { 1297 SCPrint(TRUE, stdout, CFSTR("NetBIOS name not specified\n")); 1298 return -1; 1299 } 1300 1301 if (strlen(argv[0]) > 0) { 1302 CFStringRef name; 1303 CFStringRef str; 1304 1305 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8); 1306 name = __cleanupName(str); 1307 CFRelease(str); 1308 1309 if (name != NULL) { 1310 CFDictionarySetValue(newConfiguration, key, name); 1311 CFRelease(name); 1312 } else { 1313 SCPrint(TRUE, stdout, CFSTR("invalid NetBIOS name\n")); 1314 return -1; 1315 } 1316 } else { 1317 CFDictionaryRemoveValue(newConfiguration, key); 1318 } 1319 1320 return 1; 1321} 1322 1323 1324static int 1325__doSMBWorkgroup(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration) 1326{ 1327#pragma unused(description) 1328#pragma unused(info) 1329 if (argc < 1) { 1330 SCPrint(TRUE, stdout, CFSTR("Workgroup not specified\n")); 1331 return -1; 1332 } 1333 1334 if (strlen(argv[0]) > 0) { 1335 CFStringRef name; 1336 CFStringRef str; 1337 1338 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8); 1339 name = __cleanupName(str); 1340 CFRelease(str); 1341 1342 if (name != NULL) { 1343 CFDictionarySetValue(newConfiguration, key, name); 1344 CFRelease(name); 1345 } else { 1346 SCPrint(TRUE, stdout, CFSTR("invalid Workgroup\n")); 1347 return -1; 1348 } 1349 } else { 1350 CFDictionaryRemoveValue(newConfiguration, key); 1351 } 1352 1353 return 1; 1354} 1355 1356 1357static int 1358__doSMBWINSAddresses(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration) 1359{ 1360#pragma unused(description) 1361#pragma unused(info) 1362 CFMutableArrayRef servers; 1363 1364 if (argc < 1) { 1365 SCPrint(TRUE, stdout, CFSTR("WINS address(es) not specified\n")); 1366 return -1; 1367 } 1368 1369 servers = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 1370 1371 if (strlen(argv[0]) > 0) { 1372 CFArrayRef array; 1373 CFIndex i; 1374 CFIndex n; 1375 CFStringRef str; 1376 1377 str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8); 1378 array = CFStringCreateArrayBySeparatingStrings(NULL, str, CFSTR(",")); 1379 CFRelease(str); 1380 1381 n = (array != NULL) ? CFArrayGetCount(array) : 0; 1382 for (i = 0; i < n; i++) { 1383 char str[32]; 1384 1385 if (_SC_cfstring_to_cstring(CFArrayGetValueAtIndex(array, i), 1386 str, 1387 sizeof(str), 1388 kCFStringEncodingUTF8) != NULL) { 1389 CFStringRef server; 1390 1391 server = __copyIPv4Address(str); 1392 //if (server == NULL) { 1393 // server = __copyIPv6Address(str); 1394 //} 1395 if (server != NULL) { 1396 CFArrayAppendValue(servers, server); 1397 CFRelease(server); 1398 continue; 1399 } 1400 } 1401 1402 SCPrint(TRUE, stdout, CFSTR("invalid WINS address\n")); 1403 CFRelease(array); 1404 CFRelease(servers); 1405 return -1; 1406 } 1407 if (array != NULL) CFRelease(array); 1408 } 1409 1410 if (CFArrayGetCount(servers) > 0) { 1411 CFDictionarySetValue(newConfiguration, key, servers); 1412 } else { 1413 CFDictionaryRemoveValue(newConfiguration, key); 1414 } 1415 1416 CFRelease(servers); 1417 return 1; 1418} 1419 1420 1421static selections smbNodeTypes[] = { 1422 { CFSTR("Broadcast"), &kSCValNetSMBNetBIOSNodeTypeBroadcast, 0 }, 1423 { CFSTR("Peer") , &kSCValNetSMBNetBIOSNodeTypePeer , 0 }, 1424 { CFSTR("Mixed") , &kSCValNetSMBNetBIOSNodeTypeMixed , 0 }, 1425 { CFSTR("Hybrid") , &kSCValNetSMBNetBIOSNodeTypeHybrid , 0 }, 1426 { NULL , NULL , 0 } 1427}; 1428 1429 1430static options smbOptions[] = { 1431 { "NetBIOSName" , "name" , isOther , &kSCPropNetSMBNetBIOSName , __doSMBName , NULL }, 1432 { "name" , "name" , isOther , &kSCPropNetSMBNetBIOSName , __doSMBName , NULL }, 1433 { "NetBIOSNodeType", "type" , isChooseOne, &kSCPropNetSMBNetBIOSNodeType, NULL , (void *)smbNodeTypes }, 1434 { "type", "type" , isChooseOne, &kSCPropNetSMBNetBIOSNodeType, NULL , (void *)smbNodeTypes }, 1435 { "Workgroup" , "workgroup", isOther , &kSCPropNetSMBWorkgroup , __doSMBWorkgroup , NULL }, 1436 { "WINSAddresses" , "wins" , isOther , &kSCPropNetSMBWINSAddresses , __doSMBWINSAddresses, NULL }, 1437 { "wins" , "wins" , isOther , &kSCPropNetSMBWINSAddresses , __doSMBWINSAddresses, NULL }, 1438 1439 { "?" , NULL , isHelp , NULL , NULL, 1440 "\nSMB configuration commands\n\n" 1441 " set protocol name NetBIOS-name\n" 1442 " set protocol type (Broadcast|Peer|Mixed|Hybrid)\n" 1443 " set protocol workgroup SMB-workgroup\n" 1444 " set protocol wins x1.x1.x1.x1[,x2.x2.x2.x2]\n" 1445 } 1446}; 1447#define N_SMB_OPTIONS (sizeof(smbOptions) / sizeof(smbOptions[0])) 1448 1449 1450static Boolean 1451set_protocol_smb(int argc, char **argv, CFMutableDictionaryRef newConfiguration) 1452{ 1453 Boolean ok; 1454 1455 ok = _process_options(smbOptions, N_SMB_OPTIONS, argc, argv, newConfiguration); 1456 return ok; 1457} 1458 1459 1460#endif // !TARGET_OS_IPHONE 1461 1462 1463#pragma mark - 1464#pragma mark *Protocol* 1465 1466 1467__private_extern__ 1468void 1469set_protocol(int argc, char **argv) 1470{ 1471 CFDictionaryRef configuration; 1472 CFMutableDictionaryRef newConfiguration = NULL; 1473 Boolean ok = FALSE; 1474 CFStringRef protocolType; 1475 1476 if (net_protocol == NULL) { 1477 SCPrint(TRUE, stdout, CFSTR("protocol not selected\n")); 1478 return; 1479 } 1480 1481 if (argc < 1) { 1482 SCPrint(TRUE, stdout, CFSTR("set what?\n")); 1483 return; 1484 } 1485 1486 configuration = SCNetworkProtocolGetConfiguration(net_protocol); 1487 if (configuration == NULL) { 1488 newConfiguration = CFDictionaryCreateMutable(NULL, 1489 0, 1490 &kCFTypeDictionaryKeyCallBacks, 1491 &kCFTypeDictionaryValueCallBacks); 1492 } else { 1493 newConfiguration = CFDictionaryCreateMutableCopy(NULL, 0, configuration); 1494 CFDictionaryRemoveValue(newConfiguration, kSCResvInactive); 1495 } 1496 1497 protocolType = SCNetworkProtocolGetProtocolType(net_protocol); 1498 if (CFEqual(protocolType, kSCNetworkProtocolTypeDNS)) { 1499 ok = set_protocol_dns(argc, argv, newConfiguration); 1500 } else if (CFEqual(protocolType, kSCNetworkProtocolTypeIPv4)) { 1501 ok = set_protocol_ipv4(argc, argv, newConfiguration); 1502 } else if (CFEqual(protocolType, kSCNetworkProtocolTypeIPv6)) { 1503 ok = set_protocol_ipv6(argc, argv, newConfiguration); 1504 } else if (CFEqual(protocolType, kSCNetworkProtocolTypeProxies)) { 1505 ok = set_protocol_proxies(argc, argv, newConfiguration); 1506#if !TARGET_OS_IPHONE 1507 } else if (CFEqual(protocolType, kSCNetworkProtocolTypeSMB)) { 1508 ok = set_protocol_smb(argc, argv, newConfiguration); 1509#endif // !TARGET_OS_IPHONE 1510 } else { 1511 SCPrint(TRUE, stdout, CFSTR("this protocols configuration cannot be changed\n")); 1512 } 1513 1514 if (!ok) { 1515 goto done; 1516 } 1517 1518 if (((configuration == NULL) && (CFDictionaryGetCount(newConfiguration) > 0)) || 1519 ((configuration != NULL) && !CFEqual(configuration, newConfiguration))) { 1520 if (!SCNetworkProtocolSetConfiguration(net_protocol, newConfiguration)) { 1521 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError())); 1522 goto done; 1523 } 1524 1525 _prefs_changed = TRUE; 1526 } 1527 1528 done : 1529 1530 if (newConfiguration != NULL) CFRelease(newConfiguration); 1531 return; 1532} 1533 1534 1535/* -------------------- */ 1536 1537 1538__private_extern__ 1539void 1540show_protocol(int argc, char **argv) 1541{ 1542 CFDictionaryRef configuration; 1543 SCNetworkProtocolRef protocol = NULL; 1544 CFStringRef protocolType; 1545 1546 if (argc > 0) { 1547 protocol = _find_protocol(argv[0]); 1548 } else { 1549 if (net_protocol != NULL) { 1550 protocol = net_protocol; 1551 } else { 1552 SCPrint(TRUE, stdout, CFSTR("protocol not selected\n")); 1553 return; 1554 } 1555 } 1556 1557 if (protocol == NULL) { 1558 return; 1559 } 1560 1561 protocolType = SCNetworkProtocolGetProtocolType(protocol); 1562 SCPrint(TRUE, stdout, CFSTR("protocol type = %@\n"), protocolType); 1563 1564 configuration = SCNetworkProtocolGetConfiguration(protocol); 1565 if (configuration != NULL) { 1566 SCPrint(TRUE, stdout, CFSTR("\n protocol configuration\n")); 1567 _show_entity(configuration, CFSTR("")); 1568 } 1569 1570 if (_sc_debug) { 1571 SCPrint(TRUE, stdout, CFSTR("\n%@\n"), protocol); 1572 } 1573 1574 return; 1575} 1576 1577 1578/* -------------------- */ 1579 1580 1581__private_extern__ 1582void 1583show_protocols(int argc, char **argv) 1584{ 1585#pragma unused(argc) 1586#pragma unused(argv) 1587 CFIndex i; 1588 CFIndex n; 1589 1590 if (prefs == NULL) { 1591 SCPrint(TRUE, stdout, CFSTR("network configuration not open\n")); 1592 return; 1593 } 1594 1595 if (net_service == NULL) { 1596 SCPrint(TRUE, stdout, CFSTR("service not selected\n")); 1597 return; 1598 } 1599 1600 if (protocols != NULL) CFRelease(protocols); 1601 protocols = SCNetworkServiceCopyProtocols(net_service); 1602 if (protocols == NULL) { 1603 SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError())); 1604 return; 1605 } 1606 1607 n = CFArrayGetCount(protocols); 1608 if (n > 1) { 1609 CFMutableArrayRef sorted; 1610 1611 sorted = CFArrayCreateMutableCopy(NULL, 0, protocols); 1612 CFArraySortValues(sorted, 1613 CFRangeMake(0, n), 1614 _SCNetworkProtocolCompare, 1615 NULL); 1616 CFRelease(protocols); 1617 protocols = sorted; 1618 } 1619 1620 for (i = 0; i < n; i++) { 1621 SCNetworkProtocolRef protocol; 1622 CFStringRef protocolType; 1623 1624 protocol = CFArrayGetValueAtIndex(protocols, i); 1625 protocolType = SCNetworkProtocolGetProtocolType(protocol); 1626 1627 SCPrint(TRUE, stdout, CFSTR("%c%2ld: %@%*s :"), 1628 ((net_protocol != NULL) && CFEqual(protocol, net_protocol)) ? '>' : ' ', 1629 i + 1, 1630 protocolType, 1631 (int)(sizeof("Proxies") - CFStringGetLength(protocolType) - 1), 1632 ""); 1633 1634 if (SCNetworkProtocolGetEnabled(protocol)) { 1635 CFStringRef description; 1636 1637 description = _protocol_description(protocol, FALSE); 1638 SCPrint(TRUE, stdout, CFSTR(" %@"), description); 1639 CFRelease(description); 1640 } else { 1641 SCPrint(TRUE, stdout, CFSTR(" *DISABLED*")); 1642 } 1643 SCPrint(TRUE, stdout, CFSTR("\n")); 1644 } 1645 1646 return; 1647} 1648 1649 1650/* -------------------- */ 1651 1652 1653__private_extern__ 1654CF_RETURNS_RETAINED CFStringRef 1655_protocol_description(SCNetworkProtocolRef protocol, Boolean skipEmpty) 1656{ 1657 CFDictionaryRef configuration; 1658 CFMutableStringRef description = NULL; 1659 CFStringRef protocolType; 1660 1661 description = CFStringCreateMutable(NULL, 0); 1662 1663 if (!SCNetworkProtocolGetEnabled(protocol)) { 1664 goto done; 1665 } 1666 1667 configuration = SCNetworkProtocolGetConfiguration(protocol); 1668 if (configuration == NULL) { 1669 goto done; 1670 } 1671 1672 protocolType = SCNetworkProtocolGetProtocolType(protocol); 1673 if (CFEqual(protocolType, kSCNetworkProtocolTypeDNS)) { 1674 CFStringRef domain; 1675 CFArrayRef search; 1676 CFArrayRef servers; 1677 1678 domain = CFDictionaryGetValue(configuration, kSCPropNetDNSDomainName); 1679 if (isA_CFString(domain)) { 1680 CFStringAppendFormat(description, 1681 NULL, 1682 CFSTR("domain=%@"), 1683 domain); 1684 } 1685 1686 search = CFDictionaryGetValue(configuration, kSCPropNetDNSSearchDomains); 1687 if (isA_CFArray(search)) { 1688 CFStringRef str; 1689 1690 str = CFStringCreateByCombiningStrings(NULL, search, CFSTR(",")); 1691 CFStringAppendFormat(description, 1692 NULL, 1693 CFSTR("%ssearch=%@"), 1694 CFStringGetLength(description) > 0 ? ", " : "", 1695 str); 1696 CFRelease(str); 1697 } 1698 1699 servers = CFDictionaryGetValue(configuration, kSCPropNetDNSServerAddresses); 1700 if (isA_CFArray(servers)) { 1701 CFStringRef str; 1702 1703 str = CFStringCreateByCombiningStrings(NULL, servers, CFSTR(",")); 1704 CFStringAppendFormat(description, 1705 NULL, 1706 CFSTR("%sservers=%@"), 1707 CFStringGetLength(description) > 0 ? ", " : "", 1708 str); 1709 CFRelease(str); 1710 } 1711 } else if (CFEqual(protocolType, kSCNetworkProtocolTypeIPv4)) { 1712 CFStringRef method; 1713 1714 method = CFDictionaryGetValue(configuration, kSCPropNetIPv4ConfigMethod); 1715 if (isA_CFString(method)) { 1716 CFArrayRef addresses; 1717 1718 addresses = CFDictionaryGetValue(configuration, kSCPropNetIPv4Addresses); 1719 if (CFEqual(method, kSCValNetIPv4ConfigMethodINFORM) && 1720 isA_CFArray(addresses)) { 1721 CFStringAppendFormat(description, 1722 NULL, 1723 CFSTR("%@, address=%@"), 1724 method, 1725 CFArrayGetValueAtIndex(addresses, 0)); 1726 } else if (CFEqual(method, kSCValNetIPv4ConfigMethodManual) && 1727 isA_CFArray(addresses)) { 1728 CFArrayRef masks; 1729 CFStringRef router; 1730 1731 CFStringAppendFormat(description, 1732 NULL, 1733 CFSTR("%@, address=%@"), 1734 method, 1735 CFArrayGetValueAtIndex(addresses, 0)); 1736 1737 if (CFDictionaryGetValueIfPresent(configuration, 1738 kSCPropNetIPv4SubnetMasks, 1739 (const void **)&masks) && 1740 isA_CFArray(masks)) { 1741 CFStringAppendFormat(description, 1742 NULL, 1743 CFSTR(", mask=%@"), 1744 CFArrayGetValueAtIndex(masks, 0)); 1745 } 1746 1747 if (CFDictionaryGetValueIfPresent(configuration, 1748 kSCPropNetIPv4Router, 1749 (const void **)&router) && 1750 isA_CFString(router)) { 1751 CFStringAppendFormat(description, 1752 NULL, 1753 CFSTR(", router=%@"), 1754 router); 1755 } 1756 } else { 1757 CFStringAppendFormat(description, 1758 NULL, 1759 CFSTR("%@"), 1760 method); 1761 } 1762 } 1763 } else if (CFEqual(protocolType, kSCNetworkProtocolTypeIPv6)) { 1764 CFStringRef method; 1765 1766 method = CFDictionaryGetValue(configuration, kSCPropNetIPv6ConfigMethod); 1767 if (isA_CFString(method)) { 1768 CFStringAppendFormat(description, 1769 NULL, 1770 CFSTR("%@"), 1771 method); 1772 } 1773 } else if (CFEqual(protocolType, kSCNetworkProtocolTypeProxies)) { 1774 static proxyKeys *keys[] = { &proxyKeys_FTP, &proxyKeys_Gopher, &proxyKeys_HTTP, &proxyKeys_HTTPS, 1775 &proxyKeys_RTSP, &proxyKeys_SOCKS, &proxyKeys_PAC, &proxyKeys_WPAD }; 1776 1777 for (size_t i = 0; i < sizeof(keys)/sizeof(keys[0]); i++) { 1778 proxyKeys *currentProxy = keys[i]; 1779 1780 if (!__proxy_enabled(configuration, currentProxy->keyEnable)) { 1781 continue; 1782 } 1783 1784 if (((currentProxy->keyProxy != NULL) && 1785 !CFDictionaryContainsKey(configuration, *(currentProxy->keyProxy))) || 1786 ((currentProxy->keyURL != NULL) && 1787 !CFDictionaryContainsKey(configuration, *(currentProxy->keyURL)))) { 1788 continue; 1789 } 1790 1791 CFStringAppendFormat(description, 1792 NULL, 1793 CFSTR("%s%s"), 1794 CFStringGetLength(description) > 0 ? ", " : "", 1795 currentProxy->proxy); 1796 } 1797#if !TARGET_OS_IPHONE 1798 } else if (CFEqual(protocolType, kSCNetworkProtocolTypeSMB)) { 1799 CFStringRef name; 1800 CFArrayRef servers; 1801 CFStringRef workgroup; 1802 1803 name = CFDictionaryGetValue(configuration, kSCPropNetSMBNetBIOSName); 1804 if (isA_CFString(name)) { 1805 CFStringAppendFormat(description, 1806 NULL, 1807 CFSTR("NetBIOS name=%@"), 1808 name); 1809 } 1810 1811 workgroup = CFDictionaryGetValue(configuration, kSCPropNetSMBWorkgroup); 1812 if (isA_CFString(workgroup)) { 1813 CFStringAppendFormat(description, 1814 NULL, 1815 CFSTR("Workgroup=%@"), 1816 workgroup); 1817 } 1818 1819 servers = CFDictionaryGetValue(configuration, kSCPropNetSMBWINSAddresses); 1820 if (isA_CFArray(servers)) { 1821 CFStringRef str; 1822 1823 str = CFStringCreateByCombiningStrings(NULL, servers, CFSTR(",")); 1824 CFStringAppendFormat(description, 1825 NULL, 1826 CFSTR("%sWINS servers=%@"), 1827 CFStringGetLength(description) > 0 ? ", " : "", 1828 str); 1829 CFRelease(str); 1830 } 1831#endif // !TARGET_OS_IPHONE 1832 } 1833 1834 done : 1835 1836 if (skipEmpty && CFStringGetLength(description) == 0) { 1837 CFRelease(description); 1838 description = NULL; 1839 } 1840 1841 return description; 1842}