this repo has no description
at fixPythonPipStalling 2344 lines 59 kB view raw
1/* 2 * Copyright (c) 2004-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 * May 13, 2004 Allan Nathanson <ajn@apple.com> 28 * - initial revision 29 */ 30 31 32#include <CoreFoundation/CoreFoundation.h> 33#include <CoreFoundation/CFRuntime.h> 34#include "SCNetworkConfigurationInternal.h" 35 36#include <pthread.h> 37 38 39static CFStringRef __SCNetworkSetCopyDescription (CFTypeRef cf); 40static void __SCNetworkSetDeallocate (CFTypeRef cf); 41static Boolean __SCNetworkSetEqual (CFTypeRef cf1, CFTypeRef cf2); 42static CFHashCode __SCNetworkSetHash (CFTypeRef cf); 43 44 45static CFTypeID __kSCNetworkSetTypeID = _kCFRuntimeNotATypeID; 46 47 48static const CFRuntimeClass __SCNetworkSetClass = { 49 0, // version 50 "SCNetworkSet", // className 51 NULL, // init 52 NULL, // copy 53 __SCNetworkSetDeallocate, // dealloc 54 __SCNetworkSetEqual, // equal 55 __SCNetworkSetHash, // hash 56 NULL, // copyFormattingDesc 57 __SCNetworkSetCopyDescription // copyDebugDesc 58}; 59 60 61static pthread_once_t initialized = PTHREAD_ONCE_INIT; 62 63 64static CFStringRef 65__SCNetworkSetCopyDescription(CFTypeRef cf) 66{ 67 CFAllocatorRef allocator = CFGetAllocator(cf); 68 CFMutableStringRef result; 69 SCNetworkSetRef set = (SCNetworkSetRef)cf; 70 SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set; 71 72 result = CFStringCreateMutable(allocator, 0); 73 CFStringAppendFormat(result, NULL, CFSTR("<SCNetworkSet %p [%p]> {"), set, allocator); 74 CFStringAppendFormat(result, NULL, CFSTR("id = %@"), setPrivate->setID); 75 CFStringAppendFormat(result, NULL, CFSTR(", prefs = %p"), setPrivate->prefs); 76 if (setPrivate->name != NULL) { 77 CFStringAppendFormat(result, NULL, CFSTR(", name = %@"), setPrivate->name); 78 } 79 if (!__SCNetworkSetExists(set)) { 80 CFStringAppendFormat(result, NULL, CFSTR(", REMOVED")); 81 } 82 CFStringAppendFormat(result, NULL, CFSTR("}")); 83 84 return result; 85} 86 87 88static void 89__SCNetworkSetDeallocate(CFTypeRef cf) 90{ 91 SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)cf; 92 93 /* release resources */ 94 95 CFRelease(setPrivate->setID); 96 CFRelease(setPrivate->prefs); 97 if (setPrivate->name != NULL) 98 CFRelease(setPrivate->name); 99 100 return; 101} 102 103 104static Boolean 105__SCNetworkSetEqual(CFTypeRef cf1, CFTypeRef cf2) 106{ 107 SCNetworkSetPrivateRef s1 = (SCNetworkSetPrivateRef)cf1; 108 SCNetworkSetPrivateRef s2 = (SCNetworkSetPrivateRef)cf2; 109 110 if (s1 == s2) 111 return TRUE; 112 113 if (s1->prefs != s2->prefs) 114 return FALSE; // if not the same prefs 115 116 if (!CFEqual(s1->setID, s2->setID)) 117 return FALSE; // if not the same set identifier 118 119 return TRUE; 120} 121 122 123static CFHashCode 124__SCNetworkSetHash(CFTypeRef cf) 125{ 126 SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)cf; 127 128 return CFHash(setPrivate->setID); 129} 130 131 132static void 133__SCNetworkSetInitialize(void) 134{ 135 __kSCNetworkSetTypeID = _CFRuntimeRegisterClass(&__SCNetworkSetClass); 136 return; 137} 138 139 140static SCNetworkSetPrivateRef 141__SCNetworkSetCreatePrivate(CFAllocatorRef allocator, 142 SCPreferencesRef prefs, 143 CFStringRef setID) 144{ 145 SCNetworkSetPrivateRef setPrivate; 146 uint32_t size; 147 148 /* initialize runtime */ 149 pthread_once(&initialized, __SCNetworkSetInitialize); 150 151 /* allocate target */ 152 size = sizeof(SCNetworkSetPrivate) - sizeof(CFRuntimeBase); 153 setPrivate = (SCNetworkSetPrivateRef)_CFRuntimeCreateInstance(allocator, 154 __kSCNetworkSetTypeID, 155 size, 156 NULL); 157 if (setPrivate == NULL) { 158 return NULL; 159 } 160 161 /* initialize non-zero/NULL members */ 162 setPrivate->setID = CFStringCreateCopy(NULL, setID); 163 setPrivate->prefs = CFRetain(prefs); 164 165 return setPrivate; 166} 167 168 169#pragma mark - 170 171 172static int 173_serviceOrder(SCNetworkServiceRef service) 174{ 175 SCNetworkInterfaceRef interface; 176 177 interface = SCNetworkServiceGetInterface(service); 178 if ((interface == NULL) || _SCNetworkServiceIsVPN(service)) { 179 return 100000; // if unknown or VPN interface, sort last 180 } 181 182 return __SCNetworkInterfaceOrder(interface); 183} 184 185 186static CFIndex 187_serviceOrder_clear(CFMutableArrayRef order, CFStringRef serviceID) 188{ 189 CFIndex f; // # of serviceID's found 190 CFIndex i; 191 CFIndex n; 192 193 f = 0; 194 i = 0; 195 n = CFArrayGetCount(order); 196 while (i < n) { 197 CFStringRef thisServiceID = CFArrayGetValueAtIndex(order, i); 198 199 if (CFEqual(thisServiceID, serviceID)) { 200 // remove the serviceID 201 CFArrayRemoveValueAtIndex(order, i); 202 n--; 203 f++; 204 continue; 205 } 206 207 i++; // move to the next serviceID 208 } 209 210 return f; 211} 212 213 214static void 215_serviceOrder_add(SCNetworkSetRef set, SCNetworkServiceRef service) 216{ 217 CFIndex n; 218 CFMutableArrayRef newOrder; 219 CFArrayRef order; 220 CFStringRef serviceID = SCNetworkServiceGetServiceID(service); 221 CFIndex serviceOrder = _serviceOrder(service); 222 SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set; 223 CFIndex slot; 224 225 order = SCNetworkSetGetServiceOrder(set); 226 if (order != NULL) { 227 newOrder = CFArrayCreateMutableCopy(NULL, 0, order); 228 } else { 229 newOrder = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 230 } 231 assert(newOrder != NULL); 232 233 n = _serviceOrder_clear(newOrder, serviceID); 234 if (n > 0) { 235 SC_log(LOG_ERR, "SCNetworkSetAddService() w/service already in ServiceOrder\n service = %@\n matched = %ld", 236 service, 237 n); 238 _SC_crash_once("SCNetworkSetAddService() w/service already in ServiceOrder", NULL, NULL); 239 } 240 241 slot = 0; 242 n = CFArrayGetCount(newOrder); 243 for (CFIndex i = 0; i < n; i++) { 244 int slotOrder; 245 SCNetworkServiceRef slotService; 246 CFStringRef slotServiceID; 247 248 slotServiceID = CFArrayGetValueAtIndex(newOrder, i); 249 if (!isA_CFString(slotServiceID)) { 250 // if bad prefs 251 continue; 252 } 253 254 slotService = SCNetworkServiceCopy(setPrivate->prefs, slotServiceID); 255 if (slotService == NULL) { 256 // if serviceID not valid 257 continue; 258 } 259 260 slotOrder = _serviceOrder(slotService); 261 if (serviceOrder >= slotOrder) { 262 // add the service *after* this one 263 slot = i + 1; 264 } 265 266 CFRelease(slotService); 267 } 268 269 CFArrayInsertValueAtIndex(newOrder, slot, serviceID); 270 (void) SCNetworkSetSetServiceOrder(set, newOrder); 271 CFRelease(newOrder); 272 273 return; 274} 275 276 277static void 278_serviceOrder_remove(SCNetworkSetRef set, SCNetworkServiceRef service) 279{ 280 CFIndex n; 281 CFMutableArrayRef newOrder; 282 CFArrayRef order; 283 CFStringRef serviceID; 284 285 order = SCNetworkSetGetServiceOrder(set); 286 if (order == NULL) { 287 return; 288 } 289 newOrder = CFArrayCreateMutableCopy(NULL, 0, order); 290 291 serviceID = SCNetworkServiceGetServiceID(service); 292 293 n = _serviceOrder_clear(newOrder, serviceID); 294 if (n > 1) { 295 SC_log(LOG_ERR, "SCNetworkSetRemoveService() w/multiple instances of service in ServiceOrder\n service = %@\n count = %ld", 296 service, 297 n); 298 } 299 300 (void) SCNetworkSetSetServiceOrder(set, newOrder); 301 CFRelease(newOrder); 302 303 return; 304} 305 306 307#pragma mark - 308#pragma mark SCNetworkSet APIs 309 310 311#define DEFAULT_SET_NAME CFSTR("Automatic") 312#define N_QUICK 16 313 314 315static CFStringRef 316copy_default_set_name(Boolean loc) 317{ 318 CFStringRef name; 319 static CFStringRef non_localized = NULL; 320 static CFStringRef localized = NULL; 321 322 if (!loc) { 323 static dispatch_once_t once; 324 325 dispatch_once(&once, ^{ 326 CFBundleRef bundle; 327 328 bundle = _SC_CFBundleGet(); 329 if (bundle != NULL) { 330 non_localized = _SC_CFBundleCopyNonLocalizedString(bundle, 331 CFSTR("DEFAULT_SET_NAME"), 332 DEFAULT_SET_NAME, 333 NULL); 334 } 335 }); 336 name = non_localized; 337 } else { 338 static dispatch_once_t once; 339 340 dispatch_once(&once, ^{ 341 CFBundleRef bundle; 342 343 bundle = _SC_CFBundleGet(); 344 if (bundle != NULL) { 345 localized = CFBundleCopyLocalizedString(bundle, 346 CFSTR("DEFAULT_SET_NAME"), 347 DEFAULT_SET_NAME, 348 NULL); 349 } 350 }); 351 name = localized; 352 } 353 354 if (name == NULL) { 355 // if bundle or localized names not available 356 name = DEFAULT_SET_NAME; 357 } 358 359 CFRetain(name); 360 return name; 361} 362 363 364#define PREVENT_DUPLICATE_SERVICE_NAMES 365#ifdef PREVENT_DUPLICATE_SERVICE_NAMES 366static CFStringRef 367copy_next_name(CFStringRef name) 368{ 369 CFArrayRef components; 370 CFIndex n; 371 CFMutableArrayRef newComponents; 372 SInt32 suffix = 2; 373 374 if (name == NULL) { 375 return NULL; 376 } 377 378 components = CFStringCreateArrayBySeparatingStrings(NULL, name, CFSTR(" ")); 379 if (components != NULL) { 380 newComponents = CFArrayCreateMutableCopy(NULL, 0, components); 381 CFRelease(components); 382 } else { 383 newComponents = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 384 CFArrayAppendValue(newComponents, name); 385 } 386 387 n = CFArrayGetCount(newComponents); 388 if (n > 1) { 389 CFStringRef str; 390 391 str = CFArrayGetValueAtIndex(newComponents, n - 1); 392 suffix = CFStringGetIntValue(str); 393 if (suffix++ > 0) { 394 CFArrayRemoveValueAtIndex(newComponents, n - 1); 395 } else { 396 suffix = 2; 397 } 398 } 399 400 name = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), (int)suffix); 401 CFArrayAppendValue(newComponents, name); 402 CFRelease(name); 403 404 name = CFStringCreateByCombiningStrings(NULL, newComponents, CFSTR(" ")); 405 CFRelease(newComponents); 406 407 return name; 408} 409 410 411static Boolean 412ensure_unique_service_name(SCNetworkServiceRef service) 413{ 414 SCNetworkInterfaceRef interface; 415 CFStringRef name; 416 Boolean ok = TRUE; 417 418 interface = SCNetworkServiceGetInterface(service); 419 420 name = SCNetworkServiceGetName(service); 421 if (name != NULL) { 422 CFRetain(name); 423 } 424 425 while (TRUE) { 426 CFStringRef newName; 427 428 ok = SCNetworkServiceSetName(service, name); 429 if (ok) { 430 break; 431 } 432 433 if (SCError() != kSCStatusKeyExists) { 434 SC_log(LOG_INFO, "could not update service name for \"%@\": %s", 435 SCNetworkInterfaceGetLocalizedDisplayName(interface), 436 SCErrorString(SCError())); 437 break; 438 } 439 440 newName = copy_next_name(name); 441 if (newName == NULL) { 442 SC_log(LOG_INFO, "could not create unique name for \"%@\": %s", 443 SCNetworkInterfaceGetLocalizedDisplayName(interface), 444 SCErrorString(SCError())); 445 break; 446 } 447 448 // try again with the "new" name 449 if (name != NULL) { 450 CFRelease(name); 451 } 452 name = newName; 453 } 454 455 if (name != NULL) { 456 CFRelease(name); 457 } 458 459 return ok; 460} 461#endif // PREVENT_DUPLICATE_SERVICE_NAMES 462 463 464Boolean 465SCNetworkSetAddService(SCNetworkSetRef set, SCNetworkServiceRef service) 466{ 467 SCNetworkInterfaceRef interface; 468 CFArrayRef interface_config = NULL; 469 CFStringRef link; 470 Boolean ok; 471 CFStringRef path; 472 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service; 473 SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set; 474 475 if (!isA_SCNetworkSet(set)) { 476 _SCErrorSet(kSCStatusInvalidArgument); 477 return FALSE; 478 } 479 480 if (!isA_SCNetworkService(service) || (servicePrivate->prefs == NULL)) { 481 _SCErrorSet(kSCStatusInvalidArgument); 482 return FALSE; 483 } 484 485 if (!__SCNetworkSetExists(set)) { 486 SC_log(LOG_ERR, "SCNetworkSetAddService() w/removed set\n set = %@\n service = %@", 487 set, 488 service); 489 _SC_crash_once("SCNetworkSetAddService() w/removed set", NULL, NULL); 490 _SCErrorSet(kSCStatusInvalidArgument); 491 } 492 493 if (!__SCNetworkServiceExists(service)) { 494 SC_log(LOG_ERR, "SCNetworkSetAddService() w/removed service\n set = %@\n service = %@", 495 set, 496 service); 497 _SC_crash_once("SCNetworkSetAddService() w/removed service", NULL, NULL); 498 _SCErrorSet(kSCStatusInvalidArgument); 499 return FALSE; 500 } 501 502 // make sure that we do not add an orphaned network service if its 503 // associated interface is a member of a bond or bridge. 504 interface = SCNetworkServiceGetInterface(service); 505 if ((interface != NULL) && 506 __SCNetworkInterfaceIsMember(servicePrivate->prefs, interface)) { 507 _SCErrorSet(kSCStatusKeyExists); 508 return FALSE; 509 } 510 511//#define PREVENT_DUPLICATE_SETS 512#ifdef PREVENT_DUPLICATE_SETS 513 CFArrayRef sets; 514 515 // ensure that each service is only a member of ONE set 516 sets = SCNetworkSetCopyAll(setPrivate->prefs); 517 if (sets != NULL) { 518 CFIndex i; 519 CFIndex n; 520 521 n = CFArrayGetCount(sets); 522 for (i = 0; i < n; i++) { 523 Boolean found; 524 CFArrayRef services; 525 SCNetworkSetRef set; 526 527 set = CFArrayGetValueAtIndex(sets, i); 528 services = SCNetworkSetCopyServices(set); 529 found = CFArrayContainsValue(services, 530 CFRangeMake(0, CFArrayGetCount(services)), 531 service); 532 CFRelease(services); 533 534 if (found) { 535 CFRelease(sets); 536 _SCErrorSet(kSCStatusKeyExists); 537 return FALSE; 538 } 539 } 540 CFRelease(sets); 541 } 542#endif /* PREVENT_DUPLICATE_SETS */ 543 544 // get the [deep] interface configuration settings 545 interface = SCNetworkServiceGetInterface(service); 546 if (interface != NULL) { 547 interface_config = __SCNetworkInterfaceCopyDeepConfiguration(set, interface); 548 } 549 550 // create the link between "set" and the "service" 551 path = SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL, // allocator 552 setPrivate->setID, // set 553 servicePrivate->serviceID, // service 554 NULL); // entity 555 link = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator 556 servicePrivate->serviceID, // service 557 NULL); // entity 558 ok = SCPreferencesPathSetLink(setPrivate->prefs, path, link); 559#ifdef PREVENT_DUPLICATE_SERVICE_NAMES 560 if (ok) { 561 // We use the interface cache here to not reach into the 562 // IORegistry for every service we go through 563 _SCNetworkInterfaceCacheOpen(); 564 ok = ensure_unique_service_name(service); 565 _SCNetworkInterfaceCacheClose(); 566 567 if (!ok) { 568 // if we could not ensure a unique name, remove the (just added) 569 // link between the "set" and the "service" 570 (void) SCPreferencesPathRemoveValue(setPrivate->prefs, path); 571 } 572 } 573#endif // PREVENT_DUPLICATE_SERVICE_NAMES 574 CFRelease(path); 575 CFRelease(link); 576 if (!ok) { 577 goto done; 578 } 579 580 // push the [deep] interface configuration into all sets which contain this service. 581 if (interface != NULL) { 582 __SCNetworkInterfaceSetDeepConfiguration(set, interface, interface_config); 583 } 584 585 // add service to ServiceOrder 586 _serviceOrder_add(set, service); 587 588 // mark set as no longer "new" 589 setPrivate->established = TRUE; 590 591 done : 592 593 if (ok) { 594 SC_log(LOG_DEBUG, "SCNetworkSetAddService(): %@, %@", set, service); 595 } 596 597 if (interface_config != NULL) CFRelease(interface_config); 598 return ok; 599} 600 601 602SCNetworkSetRef 603SCNetworkSetCopy(SCPreferencesRef prefs, CFStringRef setID) 604{ 605 CFDictionaryRef entity; 606 CFStringRef path; 607 SCNetworkSetPrivateRef setPrivate; 608 609 if (!isA_CFString(setID)) { 610 _SCErrorSet(kSCStatusInvalidArgument); 611 return NULL; 612 } 613 614 path = SCPreferencesPathKeyCreateSet(NULL, setID); 615 entity = SCPreferencesPathGetValue(prefs, path); 616 CFRelease(path); 617 618 if (!isA_CFDictionary(entity)) { 619 _SCErrorSet(kSCStatusNoKey); 620 return NULL; 621 } 622 623 setPrivate = __SCNetworkSetCreatePrivate(NULL, prefs, setID); 624 assert(setPrivate != NULL); 625 626 // mark set as "old" (already established) 627 setPrivate->established = TRUE; 628 629 return (SCNetworkSetRef)setPrivate; 630} 631 632 633Boolean 634SCNetworkSetContainsInterface(SCNetworkSetRef set, SCNetworkInterfaceRef interface) 635{ 636 Boolean found = FALSE; 637 CFArrayRef services; 638 639 services = SCNetworkSetCopyServices(set); 640 if (services != NULL) { 641 found = __SCNetworkServiceExistsForInterface(services, interface); 642 CFRelease(services); 643 } 644 645 return found; 646} 647 648 649CFArrayRef /* of SCNetworkSetRef's */ 650SCNetworkSetCopyAll(SCPreferencesRef prefs) 651{ 652 CFMutableArrayRef array; 653 CFIndex n; 654 CFStringRef path; 655 CFDictionaryRef sets; 656 657 path = SCPreferencesPathKeyCreateSets(NULL); 658 sets = SCPreferencesPathGetValue(prefs, path); 659 CFRelease(path); 660 661 if ((sets != NULL) && !isA_CFDictionary(sets)) { 662 return NULL; 663 } 664 665 array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 666 667 n = (sets != NULL) ? CFDictionaryGetCount(sets) : 0; 668 if (n > 0) { 669 CFIndex i; 670 const void * keys_q[N_QUICK]; 671 const void ** keys = keys_q; 672 const void * vals_q[N_QUICK]; 673 const void ** vals = vals_q; 674 675 if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) { 676 keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0); 677 vals = CFAllocatorAllocate(NULL, n * sizeof(CFPropertyListRef), 0); 678 } 679 CFDictionaryGetKeysAndValues(sets, keys, vals); 680 for (i = 0; i < n; i++) { 681 SCNetworkSetPrivateRef setPrivate; 682 683 if (!isA_CFDictionary(vals[i])) { 684 SC_log(LOG_INFO, "error w/set \"%@\"", keys[i]); 685 continue; 686 } 687 688 setPrivate = __SCNetworkSetCreatePrivate(NULL, prefs, keys[i]); 689 assert(setPrivate != NULL); 690 691 // mark set as "old" (already established) 692 setPrivate->established = TRUE; 693 694 CFArrayAppendValue(array, (SCNetworkSetRef)setPrivate); 695 CFRelease(setPrivate); 696 } 697 if (keys != keys_q) { 698 CFAllocatorDeallocate(NULL, keys); 699 CFAllocatorDeallocate(NULL, vals); 700 } 701 } 702 703 return array; 704} 705 706 707CFArrayRef /* of SCNetworkInterfaceRef's */ 708SCNetworkSetCopyAvailableInterfaces(SCNetworkSetRef set) 709{ 710 CFMutableArrayRef available; 711 CFMutableSetRef excluded = NULL; 712 int i; 713 CFArrayRef interfaces; 714 CFIndex n_interfaces; 715 CFIndex n_exclusions = 0; 716 SCPreferencesRef prefs; 717 SCNetworkSetPrivateRef setPrivate; 718 719 setPrivate = (SCNetworkSetPrivateRef)set; 720 prefs = setPrivate->prefs; 721 722 interfaces = _SCNetworkInterfaceCopyAllWithPreferences(prefs); 723 n_interfaces = CFArrayGetCount(interfaces); 724 if (n_interfaces == 0) { 725 return interfaces; 726 } 727 728 if (prefs != NULL) { 729 CFArrayRef bridges = NULL; 730 731 excluded = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks); 732 733#if !TARGET_OS_IPHONE 734 CFArrayRef bonds = NULL; 735 736 bonds = SCBondInterfaceCopyAll(prefs); 737 if (bonds != NULL) { 738 __SCBondInterfaceListCollectMembers(bonds, excluded); 739 CFRelease(bonds); 740 } 741#endif /* !TARGET_OS_IPHONE */ 742 743 bridges = SCBridgeInterfaceCopyAll(prefs); 744 if (bridges != NULL) { 745 __SCBridgeInterfaceListCollectMembers(bridges, excluded); 746 CFRelease(bridges); 747 } 748 749 n_exclusions = CFSetGetCount(excluded); 750 } 751 752 if (n_exclusions == 0) { 753 if (excluded != NULL) { 754 CFRelease(excluded); 755 } 756 757 return interfaces; 758 } 759 760 available = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 761 762 for (i = 0; i < n_interfaces; i++) { 763 SCNetworkInterfaceRef interface; 764 765 interface = CFArrayGetValueAtIndex(interfaces, i); 766 if (CFSetContainsValue(excluded, interface)) { 767 // if excluded 768 continue; 769 } 770 771 CFArrayAppendValue(available, interface); 772 } 773 774 CFRelease(interfaces); 775 CFRelease(excluded); 776 777 return available; 778} 779 780 781SCNetworkSetRef 782SCNetworkSetCopyCurrent(SCPreferencesRef prefs) 783{ 784 CFArrayRef components; 785 CFStringRef currentID; 786 SCNetworkSetPrivateRef setPrivate = NULL; 787 788 currentID = SCPreferencesGetValue(prefs, kSCPrefCurrentSet); 789 if (!isA_CFString(currentID)) { 790 return NULL; 791 } 792 793 components = CFStringCreateArrayBySeparatingStrings(NULL, currentID, CFSTR("/")); 794 if (CFArrayGetCount(components) == 3) { 795 CFStringRef setID; 796 CFStringRef path; 797 798 setID = CFArrayGetValueAtIndex(components, 2); 799 path = SCPreferencesPathKeyCreateSet(NULL, setID); 800 if (CFEqual(path, currentID)) { 801 setPrivate = __SCNetworkSetCreatePrivate(NULL, prefs, setID); 802 assert(setPrivate != NULL); 803 804 // mark set as "old" (already established) 805 setPrivate->established = TRUE; 806 } else { 807 SC_log(LOG_NOTICE, "SCNetworkSetCopyCurrent(): preferences are non-conformant"); 808 } 809 CFRelease(path); 810 } 811 CFRelease(components); 812 813 return (SCNetworkSetRef)setPrivate; 814} 815 816 817CFArrayRef /* of SCNetworkServiceRef's */ 818SCNetworkSetCopyServices(SCNetworkSetRef set) 819{ 820 CFMutableArrayRef array; 821 CFDictionaryRef dict; 822 CFIndex n; 823 CFStringRef path; 824 SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set; 825 826 if (!isA_SCNetworkSet(set)) { 827 _SCErrorSet(kSCStatusInvalidArgument); 828 return NULL; 829 } 830 831 path = SCPreferencesPathKeyCreateSetNetworkService(NULL, setPrivate->setID, NULL); 832 dict = SCPreferencesPathGetValue(setPrivate->prefs, path); 833 CFRelease(path); 834 if ((dict != NULL) && !isA_CFDictionary(dict)) { 835 return NULL; 836 } 837 838 array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 839 840 n = (dict != NULL) ? CFDictionaryGetCount(dict) : 0; 841 if (n > 0) { 842 CFIndex i; 843 const void * keys_q[N_QUICK]; 844 const void ** keys = keys_q; 845 846 if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) { 847 keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0); 848 } 849 CFDictionaryGetKeysAndValues(dict, keys, NULL); 850 for (i = 0; i < n; i++) { 851 CFArrayRef components; 852 CFStringRef link; 853 854 path = SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL, 855 setPrivate->setID, 856 (CFStringRef)keys[i], 857 NULL); 858 link = SCPreferencesPathGetLink(setPrivate->prefs, path); 859 CFRelease(path); 860 if (link == NULL) { 861 SC_log(LOG_INFO, "service \"%@\" for set \"%@\" is not a link", 862 keys[i], 863 setPrivate->setID); 864 continue; // if the service is not a link 865 } 866 867 components = CFStringCreateArrayBySeparatingStrings(NULL, link, CFSTR("/")); 868 if (CFArrayGetCount(components) == 3) { 869 CFStringRef serviceID; 870 871 serviceID = CFArrayGetValueAtIndex(components, 2); 872 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator 873 serviceID, // service 874 NULL); // entity 875 if (CFEqual(path, link)) { 876 CFDictionaryRef entity; 877 CFStringRef interfacePath; 878 Boolean skip = FALSE; 879 880 interfacePath = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator 881 serviceID, // service 882 kSCEntNetInterface); // entity 883 entity = SCPreferencesPathGetValue(setPrivate->prefs, interfacePath); 884 CFRelease(interfacePath); 885 886 if (__SCNetworkInterfaceEntityIsPPTP(entity)) { 887 SC_log(LOG_INFO, "PPTP services are no longer supported"); 888 skip = TRUE; 889 } 890 891 if (!skip) { 892 SCNetworkServicePrivateRef servicePrivate; 893 894 servicePrivate = __SCNetworkServiceCreatePrivate(NULL, 895 setPrivate->prefs, 896 serviceID, 897 NULL); 898 CFArrayAppendValue(array, (SCNetworkServiceRef)servicePrivate); 899 CFRelease(servicePrivate); 900 } 901 } 902 CFRelease(path); 903 } 904 CFRelease(components); 905 } 906 if (keys != keys_q) { 907 CFAllocatorDeallocate(NULL, keys); 908 } 909 } 910 911 return array; 912} 913 914 915SCNetworkSetRef 916SCNetworkSetCreate(SCPreferencesRef prefs) 917{ 918 CFArrayRef components; 919 CFDictionaryRef entity; 920 Boolean ok; 921 CFStringRef path; 922 CFStringRef prefix; 923 CFStringRef setID; 924 SCNetworkSetPrivateRef setPrivate; 925 926 prefix = SCPreferencesPathKeyCreateSets(NULL); 927 path = __SCPreferencesPathCreateUniqueChild_WithMoreSCFCompatibility(prefs, prefix); 928 if (path == NULL) path = SCPreferencesPathCreateUniqueChild(prefs, prefix); 929 CFRelease(prefix); 930 if (path == NULL) { 931 return NULL; 932 } 933 934 components = CFStringCreateArrayBySeparatingStrings(NULL, path, CFSTR("/")); 935 setID = CFArrayGetValueAtIndex(components, 2); 936 setPrivate = __SCNetworkSetCreatePrivate(NULL, prefs, setID); 937 assert(setPrivate != NULL); 938 CFRelease(components); 939 940 // mark set as "new" (not yet established) 941 setPrivate->established = FALSE; 942 943 // establish the set in the preferences 944 entity = CFDictionaryCreate(NULL, 945 NULL, NULL, 0, 946 &kCFTypeDictionaryKeyCallBacks, 947 &kCFTypeDictionaryValueCallBacks); 948 ok = SCPreferencesPathSetValue(prefs, path, entity); 949 CFRelease(path); 950 CFRelease(entity); 951 if (!ok) { 952 CFRelease(setPrivate); 953 setPrivate = NULL; 954 } 955 956 if (setPrivate != NULL) { 957 SC_log(LOG_DEBUG, "SCNetworkSetCreate(): %@", setPrivate); 958 } 959 960 return (SCNetworkSetRef)setPrivate; 961} 962 963 964SCNetworkSetRef 965_SCNetworkSetCreateDefault(SCPreferencesRef prefs) 966{ 967 CFStringRef model; 968 Boolean ok = TRUE; 969 SCNetworkSetRef set; 970 CFStringRef setName = NULL; 971 972 set = SCNetworkSetCopyCurrent(prefs); 973 if (set != NULL) { 974 SC_log(LOG_NOTICE, "creating default set w/already existing set"); 975 CFRelease(set); 976 _SCErrorSet(kSCStatusKeyExists); 977 return NULL; 978 } 979 980 // create a new ("Automatic") set 981 set = SCNetworkSetCreate(prefs); 982 if (set == NULL) { 983 SC_log(LOG_NOTICE, "could not create \"new\" set: %s", 984 SCErrorString(SCError())); 985 goto done; 986 } 987 988 setName = copy_default_set_name(TRUE); 989 ok = SCNetworkSetSetName(set, setName); 990 CFRelease(setName); 991 if (!ok) { 992 // if we could not save the new set's "name" 993 SC_log(LOG_NOTICE, "could not save the new set's name: %s", 994 SCErrorString(SCError())); 995 goto done; 996 } 997 998 ok = SCNetworkSetSetCurrent(set); 999 if (!ok) { 1000 // if we could not make this the "current" set 1001 SC_log(LOG_NOTICE, "could not establish new set as current: %s", 1002 SCErrorString(SCError())); 1003// goto done; 1004 } 1005 1006 model = SCPreferencesGetValue(prefs, MODEL); 1007 if (model == NULL) { 1008 model = _SC_hw_model(FALSE); 1009 SCPreferencesSetValue(prefs, MODEL, model); 1010 } 1011 1012 done : 1013 1014 if (!ok && (set != NULL)) { 1015 SCNetworkSetRemove(set); 1016 CFRelease(set); 1017 set = NULL; 1018 } 1019 return set; 1020} 1021 1022 1023CFStringRef 1024SCNetworkSetGetSetID(SCNetworkSetRef set) 1025{ 1026 SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set; 1027 1028 if (!isA_SCNetworkSet(set)) { 1029 _SCErrorSet(kSCStatusInvalidArgument); 1030 return NULL; 1031 } 1032 1033 return setPrivate->setID; 1034} 1035 1036 1037CFStringRef 1038SCNetworkSetGetName(SCNetworkSetRef set) 1039{ 1040 CFDictionaryRef entity; 1041 CFStringRef path; 1042 SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set; 1043 1044 if (!isA_SCNetworkSet(set)) { 1045 _SCErrorSet(kSCStatusInvalidArgument); 1046 return NULL; 1047 } 1048 1049 if (setPrivate->name != NULL) { 1050 return setPrivate->name; 1051 } 1052 1053 path = SCPreferencesPathKeyCreateSet(NULL, setPrivate->setID); 1054 entity = SCPreferencesPathGetValue(setPrivate->prefs, path); 1055 CFRelease(path); 1056 1057 if (isA_CFDictionary(entity)) { 1058 CFStringRef name; 1059 1060 name = CFDictionaryGetValue(entity, kSCPropUserDefinedName); 1061 if (isA_CFString(name)) { 1062 setPrivate->name = CFRetain(name); 1063 } 1064 } 1065 1066 if (setPrivate->name != NULL) { 1067 CFStringRef non_localized; 1068 1069 non_localized = copy_default_set_name(FALSE); 1070 if (CFEqual(setPrivate->name, non_localized)) { 1071 CFStringRef localized; 1072 1073 // if "Automatic", return localized name 1074 localized = copy_default_set_name(TRUE); 1075 CFRelease(setPrivate->name); 1076 setPrivate->name = localized; 1077 } 1078 1079 CFRelease(non_localized); 1080 } 1081 1082 return setPrivate->name; 1083} 1084 1085 1086CFArrayRef /* of serviceID CFStringRef's */ 1087SCNetworkSetGetServiceOrder(SCNetworkSetRef set) 1088{ 1089 CFDictionaryRef dict; 1090 CFStringRef path; 1091 CFArrayRef serviceOrder; 1092 SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set; 1093 1094 if (!isA_SCNetworkSet(set)) { 1095 _SCErrorSet(kSCStatusInvalidArgument); 1096 return NULL; 1097 } 1098 1099 path = SCPreferencesPathKeyCreateSetNetworkGlobalEntity(NULL, setPrivate->setID, kSCEntNetIPv4); 1100 if (path == NULL) { 1101 return NULL; 1102 } 1103 1104 dict = SCPreferencesPathGetValue(setPrivate->prefs, path); 1105 CFRelease(path); 1106 if (!isA_CFDictionary(dict)) { 1107 return NULL; 1108 } 1109 1110 serviceOrder = CFDictionaryGetValue(dict, kSCPropNetServiceOrder); 1111 serviceOrder = isA_CFArray(serviceOrder); 1112 1113 return serviceOrder; 1114} 1115 1116 1117CFTypeID 1118SCNetworkSetGetTypeID(void) 1119{ 1120 pthread_once(&initialized, __SCNetworkSetInitialize); /* initialize runtime */ 1121 return __kSCNetworkSetTypeID; 1122} 1123 1124 1125#if TARGET_OS_IPHONE 1126static Boolean 1127isDefaultSet(SCNetworkSetRef set) 1128{ 1129 CFStringRef defaultName; 1130 Boolean isDefault = FALSE; 1131 CFStringRef setName; 1132 1133 defaultName = copy_default_set_name(TRUE); 1134 setName = SCNetworkSetGetName(set); 1135 isDefault = _SC_CFEqual(setName, defaultName); 1136 CFRelease(defaultName); 1137 1138 return isDefault; 1139} 1140#endif // TARGET_OS_IPHONE 1141 1142 1143Boolean 1144SCNetworkSetRemove(SCNetworkSetRef set) 1145{ 1146 CFStringRef currentPath; 1147 Boolean ok = FALSE; 1148 CFStringRef path; 1149 SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set; 1150 1151 if (!isA_SCNetworkSet(set)) { 1152 _SCErrorSet(kSCStatusInvalidArgument); 1153 return FALSE; 1154 } 1155 1156 if (!__SCNetworkSetExists(set)) { 1157 SC_log(LOG_ERR, "SCNetworkSetRemove() w/removed set\n set = %@", set); 1158 _SC_crash_once("SCNetworkSetRemove() w/removed set", NULL, NULL); 1159 _SCErrorSet(kSCStatusInvalidArgument); 1160 } 1161 1162#if TARGET_OS_IPHONE 1163 if (isDefaultSet(set) && (geteuid() != 0)) { 1164 SC_log(LOG_ERR, "SCNetworkSetRemove() failed, cannot remove set : %@", set); 1165 _SC_crash("The \"Automatic\" network set cannot be removed", NULL, NULL); 1166 _SCErrorSet(kSCStatusInvalidArgument); 1167 return FALSE; 1168 } 1169#endif // TARGET_OS_IPHONE 1170 1171 currentPath = SCPreferencesGetValue(setPrivate->prefs, kSCPrefCurrentSet); 1172 path = SCPreferencesPathKeyCreateSet(NULL, setPrivate->setID); 1173 if (!isA_CFString(currentPath) || !CFEqual(currentPath, path)) { 1174 ok = SCPreferencesPathRemoveValue(setPrivate->prefs, path); 1175 } else { 1176 SC_log(LOG_DEBUG, "SCNetworkSetRemove() failed, currently active: %@", setPrivate->setID); 1177 _SCErrorSet(kSCStatusInvalidArgument); 1178 } 1179 CFRelease(path); 1180 1181 if (ok) { 1182 SC_log(LOG_DEBUG, "SCNetworkSetRemove(): %@", set); 1183 } 1184 1185 return ok; 1186} 1187 1188 1189Boolean 1190SCNetworkSetRemoveService(SCNetworkSetRef set, SCNetworkServiceRef service) 1191{ 1192 SCNetworkInterfaceRef interface; 1193 CFArrayRef interface_config = NULL; 1194 Boolean ok; 1195 CFStringRef path; 1196 int sc_status = kSCStatusOK; 1197 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service; 1198 SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set; 1199 1200 if (!isA_SCNetworkSet(set)) { 1201 _SCErrorSet(kSCStatusInvalidArgument); 1202 return FALSE; 1203 } 1204 1205 if (!isA_SCNetworkService(service) || (servicePrivate->prefs == NULL)) { 1206 _SCErrorSet(kSCStatusInvalidArgument); 1207 return FALSE; 1208 } 1209 1210 if (!__SCNetworkSetExists(set)) { 1211 SC_log(LOG_ERR, "SCNetworkSetRemoveService() w/removed set\n set = %@\n service = %@", 1212 set, 1213 service); 1214 _SC_crash_once("SCNetworkSetRemoveService() w/removed set", NULL, NULL); 1215 _SCErrorSet(kSCStatusInvalidArgument); 1216 } 1217 1218 if (!__SCNetworkServiceExists(service)) { 1219 SC_log(LOG_ERR, "SCNetworkSetRemoveService() w/removed service\n set = %@\n service = %@", 1220 set, 1221 service); 1222 _SC_crash_once("SCNetworkSetRemoveService() w/removed service", NULL, NULL); 1223 _SCErrorSet(kSCStatusInvalidArgument); 1224 return FALSE; 1225 } 1226 1227 // remove service from ServiceOrder 1228 _serviceOrder_remove(set, service); 1229 1230 // get the [deep] interface configuration settings 1231 interface = SCNetworkServiceGetInterface(service); 1232 if (interface != NULL) { 1233 interface_config = __SCNetworkInterfaceCopyDeepConfiguration(set, interface); 1234 if (interface_config != NULL) { 1235 // remove the interface configuration from all sets which contain this service. 1236 __SCNetworkInterfaceSetDeepConfiguration(set, interface, NULL); 1237 } 1238 } 1239 1240 // remove the link between "set" and the "service" 1241 path = SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL, 1242 setPrivate->setID, 1243 servicePrivate->serviceID, 1244 NULL); 1245 ok = SCPreferencesPathRemoveValue(setPrivate->prefs, path); 1246 if (!ok) { 1247 sc_status = SCError(); // preserve the error 1248 } 1249 CFRelease(path); 1250 1251 // push the [deep] interface configuration [back] into all sets which contain the service. 1252 if (interface_config != NULL) { 1253 __SCNetworkInterfaceSetDeepConfiguration(set, interface, interface_config); 1254 CFRelease(interface_config); 1255 } 1256 1257 if (ok) { 1258 SC_log(LOG_DEBUG, "SCNetworkSetRemoveService(): %@, %@", set, service); 1259 } else { 1260 _SCErrorSet(sc_status); 1261 } 1262 1263 return ok; 1264} 1265 1266 1267Boolean 1268SCNetworkSetSetCurrent(SCNetworkSetRef set) 1269{ 1270 Boolean ok; 1271 CFStringRef path; 1272 SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set; 1273 1274 if (!isA_SCNetworkSet(set)) { 1275 _SCErrorSet(kSCStatusInvalidArgument); 1276 return FALSE; 1277 } 1278 1279 if (!__SCNetworkSetExists(set)) { 1280 SC_log(LOG_ERR, "SCNetworkSetSetCurrent() w/removed set\n set = %@", set); 1281 _SC_crash_once("SCNetworkSetSetCurrent() w/removed set", NULL, NULL); 1282 _SCErrorSet(kSCStatusInvalidArgument); 1283 return FALSE; 1284 } 1285 1286 path = SCPreferencesPathKeyCreateSet(NULL, setPrivate->setID); 1287 ok = SCPreferencesSetValue(setPrivate->prefs, kSCPrefCurrentSet, path); 1288 CFRelease(path); 1289 1290 if (ok) { 1291 SC_log(LOG_DEBUG, "SCNetworkSetSetCurrent(): %@", set); 1292 } 1293 1294 return ok; 1295} 1296 1297 1298Boolean 1299SCNetworkSetSetName(SCNetworkSetRef set, CFStringRef name) 1300{ 1301 CFDictionaryRef entity; 1302#if TARGET_OS_IPHONE 1303 Boolean isDefaultName = FALSE; 1304#endif // TARGET_OS_IPHONE 1305 CFStringRef localized = NULL; 1306 CFStringRef non_localized = NULL; 1307 Boolean ok = FALSE; 1308 CFStringRef path; 1309 SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set; 1310 1311 if (!isA_SCNetworkSet(set)) { 1312 _SCErrorSet(kSCStatusInvalidArgument); 1313 return FALSE; 1314 } 1315 1316 if (!__SCNetworkSetExists(set)) { 1317 SC_log(LOG_ERR, "SCNetworkSetSetName() w/removed set\n set = %@\n name = %@", 1318 set, 1319 name != NULL ? name : CFSTR("<NULL>")); 1320 _SC_crash_once("SCNetworkSetSetName() w/removed set", NULL, NULL); 1321 _SCErrorSet(kSCStatusInvalidArgument); 1322 return FALSE; 1323 } 1324 1325 if ((name != NULL) && !isA_CFString(name)) { 1326 _SCErrorSet(kSCStatusInvalidArgument); 1327 return FALSE; 1328 } 1329 1330 // if known, compare against localized name 1331 1332 if (name != NULL) { 1333 non_localized = copy_default_set_name(FALSE); 1334 if (CFEqual(name, non_localized)) { 1335 localized = copy_default_set_name(TRUE); 1336 name = localized; 1337#if TARGET_OS_IPHONE 1338 isDefaultName = TRUE; 1339#endif // TARGET_OS_IPHONE 1340 } 1341#if TARGET_OS_IPHONE 1342 else { 1343 localized = copy_default_set_name(TRUE); 1344 isDefaultName = CFEqual(name, non_localized); 1345 } 1346#endif // TARGET_OS_IPHONE 1347 } 1348 1349#if TARGET_OS_IPHONE 1350 if (!isDefaultName && isDefaultSet(set) && (geteuid() != 0)) { 1351 // if we are trying to change the name of the "Automatic" set 1352 SC_log(LOG_ERR, "SCNetworkSetSetName() failed, cannot rename : %@", set); 1353 _SC_crash("The \"Automatic\" network set cannot be renamed", NULL, NULL); 1354 _SCErrorSet(kSCStatusInvalidArgument); 1355 goto done; 1356 } 1357#endif // TARGET_OS_IPHONE 1358 1359#define PREVENT_DUPLICATE_SET_NAMES 1360#ifdef PREVENT_DUPLICATE_SET_NAMES 1361 1362#if TARGET_OS_IPHONE 1363 if (!isDefaultName) { 1364 // On iOS, only block naming multiple sets with the name 1365 // "Automatic". Others names are OK. 1366 } else 1367#endif // TARGET_OS_IPHONE 1368 1369 if (name != NULL) { 1370 CFArrayRef sets; 1371 1372 // ensure that each set is uniquely named 1373 1374 sets = SCNetworkSetCopyAll(setPrivate->prefs); 1375 if (sets != NULL) { 1376 CFIndex i; 1377 CFIndex n; 1378 1379 n = CFArrayGetCount(sets); 1380 for (i = 0; i < n; i++) { 1381 CFStringRef otherID; 1382 CFStringRef otherName; 1383 SCNetworkSetRef set = CFArrayGetValueAtIndex(sets, i); 1384 1385 otherID = SCNetworkSetGetSetID(set); 1386 if (CFEqual(setPrivate->setID, otherID)) { 1387 continue; // skip current set 1388 } 1389 1390 otherName = SCNetworkSetGetName(set); 1391 if ((otherName != NULL) && CFEqual(name, otherName)) { 1392 // if "name" not unique 1393 CFRelease(sets); 1394 _SCErrorSet(kSCStatusKeyExists); 1395 goto done; 1396 } 1397 } 1398 CFRelease(sets); 1399 } 1400 } 1401#endif /* PREVENT_DUPLICATE_SET_NAMES */ 1402 1403 // if known, store non-localized name 1404 1405 if ((name != NULL) && (non_localized != NULL)) { 1406 if (localized == NULL) { 1407 localized = copy_default_set_name(TRUE); 1408 } 1409 if (CFEqual(name, localized)) { 1410 name = non_localized; 1411 } 1412 } 1413 1414 // update the "name" 1415 1416 path = SCPreferencesPathKeyCreateSet(NULL, setPrivate->setID); 1417 entity = SCPreferencesPathGetValue(setPrivate->prefs, path); 1418 if (isA_CFDictionary(entity) || 1419 ((entity == NULL) && (name != NULL))) { 1420 CFMutableDictionaryRef newEntity; 1421 1422 if (entity != NULL) { 1423 newEntity = CFDictionaryCreateMutableCopy(NULL, 0, entity); 1424 } else { 1425 newEntity = CFDictionaryCreateMutable(NULL, 1426 0, 1427 &kCFTypeDictionaryKeyCallBacks, 1428 &kCFTypeDictionaryValueCallBacks); 1429 } 1430 if (name != NULL) { 1431 CFDictionarySetValue(newEntity, kSCPropUserDefinedName, name); 1432 } else { 1433 CFDictionaryRemoveValue(newEntity, kSCPropUserDefinedName); 1434 } 1435 ok = SCPreferencesPathSetValue(setPrivate->prefs, path, newEntity); 1436 CFRelease(newEntity); 1437 } 1438 CFRelease(path); 1439 1440 done : 1441 1442 if (ok) { 1443 SC_log(LOG_DEBUG, "SCNetworkSetSetName(): %@", set); 1444 } 1445 1446 if (localized != NULL) CFRelease(localized); 1447 if (non_localized != NULL) CFRelease(non_localized); 1448 return ok; 1449} 1450 1451 1452Boolean 1453SCNetworkSetSetServiceOrder(SCNetworkSetRef set, CFArrayRef newOrder) 1454{ 1455 CFMutableArrayRef cleanOrder; 1456 CFDictionaryRef dict; 1457 CFIndex i; 1458 CFIndex n; 1459 CFMutableDictionaryRef newDict; 1460 Boolean ok; 1461 CFStringRef path; 1462 SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set; 1463 1464 if (!isA_SCNetworkSet(set)) { 1465 _SCErrorSet(kSCStatusInvalidArgument); 1466 return FALSE; 1467 } 1468 1469 if (!__SCNetworkSetExists(set)) { 1470 SC_log(LOG_ERR, "SCNetworkSetSetServiceOrder() w/removed set\n set = %@", set); 1471 _SC_crash_once("SCNetworkSetSetServiceOrder() w/removed set", NULL, NULL); 1472 _SCErrorSet(kSCStatusInvalidArgument); 1473 return FALSE; 1474 } 1475 1476 if (isA_CFArray(newOrder)) { 1477 n = CFArrayGetCount(newOrder); 1478 for (i = 0; i < n; i++) { 1479 CFStringRef serviceID; 1480 1481 serviceID = CFArrayGetValueAtIndex(newOrder, i); 1482 if (!isA_CFString(serviceID)) { 1483 _SCErrorSet(kSCStatusInvalidArgument); 1484 return FALSE; 1485 } 1486 } 1487 } else { 1488 _SCErrorSet(kSCStatusInvalidArgument); 1489 return FALSE; 1490 } 1491 1492 path = SCPreferencesPathKeyCreateSetNetworkGlobalEntity(NULL, setPrivate->setID, kSCEntNetIPv4); 1493 if (path == NULL) { 1494 return FALSE; 1495 } 1496 1497 dict = SCPreferencesPathGetValue(setPrivate->prefs, path); 1498 if (dict != NULL) { 1499 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict); 1500 } else { 1501 newDict = CFDictionaryCreateMutable(NULL, 1502 0, 1503 &kCFTypeDictionaryKeyCallBacks, 1504 &kCFTypeDictionaryValueCallBacks); 1505 } 1506 1507 cleanOrder = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 1508 n = CFArrayGetCount(newOrder); 1509 for (i = 0; i < n; i++) { 1510 CFIndex nClean = CFArrayGetCount(cleanOrder); 1511 CFStringRef serviceID = CFArrayGetValueAtIndex(newOrder, i); 1512 1513 if ((nClean == 0) || 1514 !CFArrayContainsValue(cleanOrder, CFRangeMake(0, nClean), serviceID)) { 1515 // if first reference to this serviceID 1516 CFArrayAppendValue(cleanOrder, serviceID); 1517 } else { 1518 // skip duplicate serviceID 1519 SC_log(LOG_ERR, "SCNetworkSetSetServiceOrder() found duplicate serviceID: removed %@\n", serviceID); 1520 } 1521 } 1522 CFDictionarySetValue(newDict, kSCPropNetServiceOrder, cleanOrder); 1523 CFRelease(cleanOrder); 1524 1525 ok = SCPreferencesPathSetValue(setPrivate->prefs, path, newDict); 1526 CFRelease(newDict); 1527 CFRelease(path); 1528 1529 return ok; 1530} 1531 1532 1533#pragma mark - 1534#pragma mark SCNetworkSet SPIs 1535 1536 1537__private_extern__ 1538Boolean 1539__SCNetworkSetExists(SCNetworkSetRef set) 1540{ 1541 CFDictionaryRef entity; 1542 CFStringRef path; 1543 SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set; 1544 1545 if (setPrivate->prefs == NULL) { 1546 return FALSE; 1547 } 1548 1549 path = SCPreferencesPathKeyCreateSet(NULL, setPrivate->setID); 1550 entity = SCPreferencesPathGetValue(setPrivate->prefs, path); 1551 CFRelease(path); 1552 1553 if (!isA_CFDictionary(entity)) { 1554 // if no "set" 1555 return FALSE; 1556 } 1557 1558 return TRUE; 1559} 1560 1561 1562static void 1563add_supported_interfaces(CFMutableArrayRef interface_list, SCNetworkInterfaceRef interface) 1564{ 1565 CFIndex i; 1566 CFArrayRef interface_types; 1567 CFIndex n; 1568 1569 interface_types = SCNetworkInterfaceGetSupportedInterfaceTypes(interface); 1570 n = (interface_types != NULL) ? CFArrayGetCount(interface_types) : 0; 1571 for (i = 0; i < n; i++) { 1572 SCNetworkInterfaceRef parent; 1573 CFStringRef interface_type; 1574 1575 interface_type = CFArrayGetValueAtIndex(interface_types, i); 1576 parent = SCNetworkInterfaceCreateWithInterface(interface, interface_type); 1577 if (parent != NULL) { 1578 CFArrayAppendValue(interface_list, parent); 1579 CFRelease(parent); 1580 } 1581 } 1582 1583 return; 1584} 1585 1586 1587static CFSetRef /* of SCNetworkInterfaceRef's */ 1588copyExcludedInterfaces(SCPreferencesRef prefs) 1589{ 1590 CFMutableSetRef excluded; 1591 CFArrayRef interfaces; 1592 1593 excluded = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks); 1594 1595#if !TARGET_OS_IPHONE 1596 // exclude Bond [member] interfaces 1597 interfaces = SCBondInterfaceCopyAll(prefs); 1598 if (interfaces != NULL) { 1599 __SCBondInterfaceListCollectMembers(interfaces, excluded); 1600 CFRelease(interfaces); 1601 } 1602#endif // !TARGET_OS_IPHONE 1603 1604 // exclude Bridge [member] interfaces 1605 interfaces = SCBridgeInterfaceCopyAll(prefs); 1606 if (interfaces != NULL) { 1607 __SCBridgeInterfaceListCollectMembers(interfaces, excluded); 1608 CFRelease(interfaces); 1609 } 1610 1611 return excluded; 1612} 1613 1614 1615#if !TARGET_OS_IPHONE 1616static SCBridgeInterfaceRef 1617copyAutoBridgeInterface(SCPreferencesRef prefs, CFStringRef bridgeName) 1618{ 1619 SCBridgeInterfaceRef bridge = NULL; 1620 CFArrayRef interfaces; 1621 1622 // exclude Bridge [member] interfaces 1623 interfaces = SCBridgeInterfaceCopyAll(prefs); 1624 if (interfaces != NULL) { 1625 CFIndex i; 1626 CFIndex n; 1627 1628 n = CFArrayGetCount(interfaces); 1629 for (i = 0; i < n; i++) { 1630 SCBridgeInterfaceRef interface; 1631 CFStringRef name = NULL; 1632 CFDictionaryRef options; 1633 1634 interface = CFArrayGetValueAtIndex(interfaces, i); 1635 options = SCBridgeInterfaceGetOptions(interface); 1636 if ((options != NULL) && 1637 CFDictionaryGetValueIfPresent(options, 1638 CFSTR("__AUTO__"), 1639 (const void **)&name) && 1640 _SC_CFEqual(name, bridgeName)) { 1641 bridge = interface; 1642 CFRetain(bridge); 1643 break; 1644 } 1645 } 1646 1647 CFRelease(interfaces); 1648 } 1649 1650 if (bridge == NULL) { 1651 bridge = SCBridgeInterfaceCreate(prefs); 1652 if (bridge != NULL) { 1653 CFMutableDictionaryRef newOptions; 1654 Boolean ok; 1655 1656 newOptions = CFDictionaryCreateMutable(NULL, 0, 1657 &kCFTypeDictionaryKeyCallBacks, 1658 &kCFTypeDictionaryValueCallBacks); 1659 CFDictionarySetValue(newOptions, CFSTR("__AUTO__"), bridgeName); 1660 ok = SCBridgeInterfaceSetOptions(bridge, newOptions); 1661 CFRelease(newOptions); 1662 if (!ok) { 1663 CFRelease(bridge); 1664 bridge = NULL; 1665 } 1666 } 1667 } 1668 1669 return bridge; 1670} 1671#endif // !TARGET_OS_IPHONE 1672 1673 1674static CFArrayRef 1675copyServices(SCNetworkSetRef set) 1676{ 1677 CFArrayRef services; 1678 SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set; 1679 1680 // first, assume that we only want to add new services 1681 // for those interfaces that are not represented in the 1682 // current set. 1683 services = SCNetworkSetCopyServices(set); 1684 if ((services != NULL) && setPrivate->established) { 1685 // but, if we are given an existing (or "established") set 1686 // than we only want to add new services for those interfaces 1687 // that are not represented in *any* set. 1688 CFRelease(services); 1689 services = SCNetworkServiceCopyAll(setPrivate->prefs); 1690 } 1691 1692 return services; 1693} 1694 1695 1696#if !TARGET_OS_IPHONE 1697static CF_RETURNS_RETAINED CFArrayRef 1698updateServices(CFArrayRef services, SCNetworkInterfaceRef interface) 1699{ 1700 CFStringRef bsdName; 1701 CFIndex i; 1702 CFIndex n; 1703 CFMutableArrayRef newServices; 1704 1705 if (services == NULL) { 1706 return NULL; 1707 } 1708 1709 bsdName = SCNetworkInterfaceGetBSDName(interface); 1710 1711 newServices = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 1712 1713 n = CFArrayGetCount(services); 1714 for (i = 0; i < n; i++) { 1715 SCNetworkInterfaceRef interface; 1716 CFStringRef interfaceName; 1717 SCNetworkServiceRef newService; 1718 SCNetworkServiceRef service; 1719 CFStringRef serviceID; 1720 SCNetworkServicePrivateRef servicePrivate; 1721 1722 service = CFArrayGetValueAtIndex(services, i); 1723 interface = SCNetworkServiceGetInterface(service); 1724 interfaceName = SCNetworkInterfaceGetBSDName(interface); 1725 if (!_SC_CFEqual(interfaceName, bsdName)) { 1726 // if not a match, retain 1727 CFArrayAppendValue(newServices, service); 1728 continue; 1729 } 1730 1731 // if a match, update 1732 serviceID = SCNetworkServiceGetServiceID(service); 1733 servicePrivate = (SCNetworkServicePrivateRef)service; 1734 newService = SCNetworkServiceCopy(servicePrivate->prefs, serviceID); 1735 if (newService != NULL) { 1736 CFArrayAppendValue(newServices, newService); 1737 CFRelease(newService); 1738 } 1739 } 1740 1741 return newServices; 1742} 1743#endif // !TARGET_OS_IPHONE 1744 1745 1746static __inline__ Boolean 1747skipInterface(SCNetworkInterfaceRef interface) 1748{ 1749 CFStringRef action; 1750 1751 action = _SCNetworkInterfaceGetConfigurationAction(interface); 1752 if (isA_CFString(action) && 1753 CFEqual(action, kSCNetworkInterfaceConfigurationActionValueNone)) { 1754 return TRUE; 1755 } 1756 1757 return FALSE; 1758} 1759 1760 1761CFComparisonResult 1762_SCNetworkSetCompare(const void *val1, const void *val2, void *context) 1763{ 1764#pragma unused(context) 1765 CFStringRef id1; 1766 CFStringRef id2; 1767 CFStringRef name1; 1768 CFStringRef name2; 1769 SCNetworkSetRef s1 = (SCNetworkSetRef)val1; 1770 SCNetworkSetRef s2 = (SCNetworkSetRef)val2; 1771 1772 name1 = SCNetworkSetGetName(s1); 1773 name2 = SCNetworkSetGetName(s2); 1774 1775 if (name1 != NULL) { 1776 if (name2 != NULL) { 1777 return CFStringCompare(name1, name2, 0); 1778 } else { 1779 return kCFCompareLessThan; 1780 } 1781 } 1782 1783 if (name2 != NULL) { 1784 return kCFCompareGreaterThan; 1785 } 1786 1787 id1 = SCNetworkSetGetSetID(s1); 1788 id2 = SCNetworkSetGetSetID(s2); 1789 return CFStringCompare(id1, id2, 0); 1790} 1791 1792 1793static Boolean 1794__SCNetworkSetEstablishDefaultConfigurationForInterfaces(SCNetworkSetRef set, CFArrayRef interfaces, Boolean excludeHidden) 1795{ 1796 CFSetRef excluded; 1797 CFIndex i; 1798 CFIndex n = 0; 1799 Boolean ok = TRUE; 1800 CFArrayRef services; 1801 SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set; 1802 Boolean updated = FALSE; 1803#if !TARGET_OS_IPHONE 1804 Boolean updatedIFs = FALSE; 1805#endif // !TARGET_OS_IPHONE 1806 1807#if TARGET_OS_IPHONE 1808 CFArrayRef orphans = NULL; 1809 CFArrayRef sets; 1810 1811 sets = SCNetworkSetCopyAll(setPrivate->prefs); 1812 if (sets != NULL) { 1813 if (CFArrayGetCount(sets) == 1) { 1814 services = SCNetworkSetCopyServices(set); 1815 if (services != NULL) { 1816 n = CFArrayGetCount(services); 1817 CFRelease(services); 1818 } 1819 1820 if ((n == 0) && CFEqual(set, CFArrayGetValueAtIndex(sets, 0))) { 1821 // after a "Reset Network Settings" we need to find (and 1822 // add back) any VPN services that were orphaned. 1823 orphans = SCNetworkServiceCopyAll(setPrivate->prefs); 1824 } 1825 } 1826 1827 CFRelease(sets); 1828 } 1829#endif // TARGET_OS_IPHONE 1830 1831 // copy network services 1832 services = copyServices(set); 1833 1834 // copy network interfaces to be excluded 1835 excluded = copyExcludedInterfaces(setPrivate->prefs); 1836 1837#if !TARGET_OS_IPHONE 1838 // look for interfaces that should auto-magically be added 1839 // to an Ethernet bridge 1840 n = ((services != NULL) && (interfaces != NULL)) ? CFArrayGetCount(interfaces) : 0; 1841 for (i = 0; i < n; i++) { 1842 SCBridgeInterfaceRef bridge = NULL; 1843 SCNetworkInterfaceRef interface; 1844 1845 interface = CFArrayGetValueAtIndex(interfaces, i); 1846 1847 if (excludeHidden && skipInterface(interface)) { 1848 // if not auto-configure 1849 continue; 1850 } 1851 1852 if (CFSetContainsValue(excluded, interface)) { 1853 // if this interface is a member of a Bond or Bridge 1854 continue; 1855 } 1856 1857 if (__SCNetworkServiceExistsForInterface(services, interface)) { 1858 // if this is not a new interface 1859 continue; 1860 } 1861 1862 if (_SCNetworkInterfaceIsBuiltin(interface) && 1863 _SCNetworkInterfaceIsThunderbolt(interface) && 1864 !isA_SCBridgeInterface(interface)) { 1865 // add built-in Thunderbolt interfaces to bridge 1866 bridge = copyAutoBridgeInterface(setPrivate->prefs, CFSTR("thunderbolt-bridge")); 1867 } 1868 1869 if (bridge != NULL) { 1870 CFIndex bridgeIndex; 1871 CFArrayRef members; 1872 CFMutableArrayRef newMembers; 1873 CFMutableSetRef newExcluded; 1874 CFMutableArrayRef newInterfaces; 1875 CFArrayRef newServices; 1876 1877 // track the bridge interface (if it's in our list) 1878 bridgeIndex = CFArrayGetFirstIndexOfValue(interfaces, 1879 CFRangeMake(0, CFArrayGetCount(interfaces)), 1880 bridge); 1881 1882 // add new member interface 1883 members = SCBridgeInterfaceGetMemberInterfaces(bridge); 1884 if ((members != NULL) && (CFArrayGetCount(members) > 0)) { 1885 newMembers = CFArrayCreateMutableCopy(NULL, 0, members); 1886 updated = TRUE; // if we're updating an existing bridge 1887 } else { 1888 newMembers = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 1889 } 1890 CFArrayAppendValue(newMembers, interface); 1891 ok = SCBridgeInterfaceSetMemberInterfaces(bridge, newMembers); 1892 CFRelease(newMembers); 1893 if (!ok) { 1894 SC_log(LOG_INFO, "could not update bridge with \"%@\": %s", 1895 SCNetworkInterfaceGetLocalizedDisplayName(interface), 1896 SCErrorString(SCError())); 1897 CFRelease(bridge); 1898 continue; 1899 } 1900 1901 // exclude the new member interface 1902 newExcluded = CFSetCreateMutableCopy(NULL, 0, excluded); 1903 CFRelease(excluded); 1904 CFSetAddValue(newExcluded, interface); 1905 excluded = newExcluded; 1906 1907 // update the list of interfaces to include the [new or updated] bridge 1908 newInterfaces = CFArrayCreateMutableCopy(NULL, 0, interfaces); 1909 if (bridgeIndex != kCFNotFound) { 1910 CFArraySetValueAtIndex(newInterfaces, bridgeIndex, bridge); 1911 } else { 1912 CFArrayAppendValue(newInterfaces, bridge); 1913 } 1914 if (updatedIFs) { 1915 CFRelease(interfaces); 1916 } 1917 interfaces = newInterfaces; 1918 updatedIFs = TRUE; 1919 1920 // refresh [existing] services 1921 newServices = updateServices(services, bridge); 1922 if (newServices != NULL) { 1923 CFRelease(services); 1924 services = newServices; 1925 } 1926 1927 CFRelease(bridge); 1928 } 1929 } 1930#endif // !TARGET_OS_IPHONE 1931 1932 n = ((services != NULL) && (interfaces != NULL)) ? CFArrayGetCount(interfaces) : 0; 1933 for (i = 0; i < n; i++) { 1934 SCNetworkInterfaceRef interface; 1935 CFMutableArrayRef interface_list; 1936 1937 interface = CFArrayGetValueAtIndex(interfaces, i); 1938 1939 if (excludeHidden && skipInterface(interface)) { 1940 // if not auto-configure 1941 continue; 1942 } 1943 1944 if (CFSetContainsValue(excluded, interface)) { 1945 // if this interface is a member of a Bond or Bridge 1946 continue; 1947 } 1948 1949 if (__SCNetworkServiceExistsForInterface(services, interface)) { 1950 // if this is not a new interface 1951 continue; 1952 } 1953 1954 interface_list = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 1955 CFArrayAppendValue(interface_list, interface); 1956 1957 while (ok && (CFArrayGetCount(interface_list) > 0)) { 1958 CFArrayRef protocol_types; 1959 1960 interface = CFArrayGetValueAtIndex(interface_list, 0); 1961 1962 protocol_types = SCNetworkInterfaceGetSupportedProtocolTypes(interface); 1963 if ((protocol_types != NULL) && (CFArrayGetCount(protocol_types) > 0)) { 1964 SCNetworkServiceRef service; 1965 1966 service = SCNetworkServiceCreate(setPrivate->prefs, interface); 1967 if (service == NULL) { 1968 SC_log(LOG_ERR, "could not create service for \"%@\": %s", 1969 SCNetworkInterfaceGetLocalizedDisplayName(interface), 1970 SCErrorString(SCError())); 1971 ok = FALSE; 1972 goto nextInterface; 1973 } 1974 1975 ok = SCNetworkServiceEstablishDefaultConfiguration(service); 1976 if (!ok) { 1977 SC_log(LOG_ERR, "could not estabish default configuration for \"%@\": %s", 1978 SCNetworkInterfaceGetLocalizedDisplayName(interface), 1979 SCErrorString(SCError())); 1980 SCNetworkServiceRemove(service); 1981 CFRelease(service); 1982 goto nextInterface; 1983 } 1984 1985 ok = SCNetworkSetAddService(set, service); 1986 if (!ok) { 1987 SC_log(LOG_ERR, "could not add service for \"%@\": %s", 1988 SCNetworkInterfaceGetLocalizedDisplayName(interface), 1989 SCErrorString(SCError())); 1990 SCNetworkServiceRemove(service); 1991 CFRelease(service); 1992 goto nextInterface; 1993 } 1994 1995 CFRelease(service); 1996 updated = TRUE; 1997 } else { 1998 add_supported_interfaces(interface_list, interface); 1999 } 2000 2001 nextInterface : 2002 2003 CFArrayRemoveValueAtIndex(interface_list, 0); 2004 } 2005 CFRelease(interface_list); 2006 } 2007#if !TARGET_OS_IPHONE 2008 if (updatedIFs && (interfaces != NULL)) { 2009 CFRelease(interfaces); 2010 } 2011#endif // !TARGET_OS_IPHONE 2012 if (services != NULL) CFRelease(services); 2013 CFRelease(excluded); 2014 2015#if TARGET_OS_IPHONE 2016 if (orphans != NULL) { 2017 if (ok && updated) { 2018 CFIndex i; 2019 CFIndex n = CFArrayGetCount(orphans); 2020 2021 for (i = 0; i < n; i++) { 2022 SCNetworkServiceRef service; 2023 2024 service = CFArrayGetValueAtIndex(orphans, i); 2025 if (_SCNetworkServiceIsVPN(service)) { 2026 ok = SCNetworkSetAddService(set, service); 2027 if (!ok) { 2028 break; 2029 } 2030 } 2031 } 2032 } 2033 2034 CFRelease(orphans); 2035 } 2036#endif // TARGET_OS_IPHONE 2037 2038 if (ok) { 2039 if (updated) { 2040 CFStringRef model; 2041 2042 model = SCPreferencesGetValue(setPrivate->prefs, MODEL); 2043 if (model == NULL) { 2044 model = _SC_hw_model(FALSE); 2045 SCPreferencesSetValue(setPrivate->prefs, MODEL, model); 2046 } 2047 } else { 2048 // if no changes were made 2049 _SCErrorSet(kSCStatusOK); 2050 } 2051 } 2052 2053 return updated; 2054} 2055 2056 2057Boolean 2058SCNetworkSetEstablishDefaultConfiguration(SCNetworkSetRef set) 2059{ 2060 CFArrayRef interfaces; 2061 SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set; 2062 Boolean updated = FALSE; 2063 2064 if (!isA_SCNetworkSet(set)) { 2065 _SCErrorSet(kSCStatusInvalidArgument); 2066 return FALSE; 2067 } 2068 2069 interfaces = _SCNetworkInterfaceCopyAllWithPreferences(setPrivate->prefs); 2070 if (interfaces != NULL) { 2071 updated = __SCNetworkSetEstablishDefaultConfigurationForInterfaces(set, interfaces, TRUE); 2072 CFRelease(interfaces); 2073 } 2074 2075 return updated; 2076} 2077 2078 2079Boolean 2080SCNetworkSetEstablishDefaultInterfaceConfiguration(SCNetworkSetRef set, SCNetworkInterfaceRef interface) 2081{ 2082 CFArrayRef interfaces; 2083 Boolean updated; 2084 2085 if (!isA_SCNetworkSet(set)) { 2086 _SCErrorSet(kSCStatusInvalidArgument); 2087 return FALSE; 2088 } 2089 2090 if (!isA_SCNetworkInterface(interface)) { 2091 _SCErrorSet(kSCStatusInvalidArgument); 2092 return FALSE; 2093 } 2094 2095 interfaces = CFArrayCreate(NULL, (const void **)&interface, 1, &kCFTypeArrayCallBacks); 2096 assert(interfaces != NULL); 2097 updated = __SCNetworkSetEstablishDefaultConfigurationForInterfaces(set, interfaces, FALSE); 2098 CFRelease(interfaces); 2099 2100 return updated; 2101} 2102 2103 2104SCNetworkServiceRef 2105SCNetworkSetCopySelectedVPNService(SCNetworkSetRef set) 2106{ 2107 CFIndex i; 2108 CFIndex n; 2109 SCNetworkServiceRef selected = NULL; 2110 CFArrayRef services; 2111 CFMutableArrayRef services_vpn = NULL; 2112 2113 if (!isA_SCNetworkSet(set)) { 2114 _SCErrorSet(kSCStatusInvalidArgument); 2115 return NULL; 2116 } 2117 2118 services = SCNetworkSetCopyServices(set); 2119 if (services != NULL) { 2120 n = CFArrayGetCount(services); 2121 for (i = 0; i < n; i++) { 2122 SCNetworkServiceRef service; 2123 2124 service = CFArrayGetValueAtIndex(services, i); 2125 if (!SCNetworkServiceGetEnabled(service)) { 2126 // if not enabled 2127 continue; 2128 } 2129 2130 if (!_SCNetworkServiceIsVPN(service)) { 2131 // if not VPN service 2132 continue; 2133 } 2134 2135 if (services_vpn == NULL) { 2136 services_vpn = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 2137 } 2138 CFArrayAppendValue(services_vpn, service); 2139 } 2140 2141 CFRelease(services); 2142 } 2143 2144 if (services_vpn == NULL) { 2145 // if no VPN services 2146 return NULL; 2147 } 2148 2149 n = CFArrayGetCount(services_vpn); 2150 if (n > 1) { 2151 CFArrayRef order; 2152 CFMutableArrayRef sorted; 2153 2154 order = SCNetworkSetGetServiceOrder(set); 2155 sorted = CFArrayCreateMutableCopy(NULL, 0, services_vpn); 2156 CFArraySortValues(sorted, 2157 CFRangeMake(0, CFArrayGetCount(sorted)), 2158 _SCNetworkServiceCompare, 2159 (void *)order); 2160 CFRelease(services_vpn); 2161 services_vpn = sorted; 2162 } 2163 2164#if TARGET_OS_IPHONE 2165 if (n > 1) { 2166 CFStringRef serviceID_prefs; 2167 2168#define VPN_PREFERENCES CFSTR("com.apple.mobilevpn") 2169#define VPN_SERVICE_ID CFSTR("activeVPNID") 2170 2171 CFPreferencesAppSynchronize(VPN_PREFERENCES); 2172 serviceID_prefs = CFPreferencesCopyAppValue(VPN_SERVICE_ID, VPN_PREFERENCES); 2173 if (serviceID_prefs != NULL) { 2174 for (i = 0; i < n; i++) { 2175 SCNetworkServiceRef service; 2176 CFStringRef serviceID; 2177 2178 service = CFArrayGetValueAtIndex(services_vpn, i); 2179 serviceID = SCNetworkServiceGetServiceID(service); 2180 if (CFEqual(serviceID, serviceID_prefs)) { 2181 selected = service; 2182 CFRetain(selected); 2183 break; 2184 } 2185 2186 } 2187 2188 CFRelease(serviceID_prefs); 2189 } 2190 } 2191#endif // TARGET_OS_IPHONE 2192 2193 if (selected == NULL) { 2194 selected = CFArrayGetValueAtIndex(services_vpn, 0); 2195 CFRetain(selected); 2196 } 2197 2198 CFRelease(services_vpn); 2199 return selected; 2200} 2201 2202 2203Boolean 2204SCNetworkSetSetSelectedVPNService(SCNetworkSetRef set, SCNetworkServiceRef service) 2205{ 2206 Boolean ok = TRUE; 2207 CFArrayRef services; 2208 2209 if (!isA_SCNetworkSet(set)) { 2210 _SCErrorSet(kSCStatusInvalidArgument); 2211 return FALSE; 2212 } 2213 2214 if (!isA_SCNetworkService(service) || !_SCNetworkServiceIsVPN(service)) { 2215 _SCErrorSet(kSCStatusInvalidArgument); 2216 return FALSE; 2217 } 2218 2219 services = SCNetworkSetCopyServices(set); 2220 if (services != NULL) { 2221 CFIndex i; 2222 CFIndex n = CFArrayGetCount(services); 2223 2224 if (!CFArrayContainsValue(services, CFRangeMake(0, n), service)) { 2225 // if selected service not a member of the current set 2226 _SCErrorSet(kSCStatusInvalidArgument); 2227 ok = FALSE; 2228 goto done; 2229 } 2230 2231 for (i = 0; ok && (i < n); i++) { 2232 SCNetworkServiceRef vpn; 2233 2234 vpn = CFArrayGetValueAtIndex(services, i); 2235 if (!_SCNetworkServiceIsVPN(vpn)) { 2236 // if not VPN service 2237 continue; 2238 } 2239 2240 ok = SCNetworkServiceSetEnabled(vpn, CFEqual(service, vpn)); 2241 } 2242 } 2243 2244 done : 2245 2246 if (services != NULL) CFRelease(services); 2247 return ok; 2248} 2249 2250 2251Boolean 2252_SCNetworkSetSetSetID(SCNetworkSetRef set, CFStringRef newSetID) 2253{ 2254 SCNetworkSetRef currentSet = NULL; 2255 SCNetworkSetPrivateRef currentSetPrivate = NULL; 2256 CFDictionaryRef entity; 2257 CFStringRef newPath; 2258 Boolean ok = FALSE; 2259 CFStringRef oldPath = NULL; 2260 SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set; 2261 Boolean updateCurrentSet = FALSE; 2262 2263 if (!isA_SCNetworkSet(set)) { 2264 _SCErrorSet(kSCStatusInvalidArgument); 2265 return FALSE; 2266 } 2267 2268 if (!isA_CFString(newSetID)) { 2269 _SCErrorSet(kSCStatusInvalidArgument); 2270 return FALSE; 2271 } 2272 2273 if (!__SCNetworkSetExists(set)) { 2274 SC_log(LOG_ERR, "_SCNetworkSetSetSetID() w/removed set\n set = %@\n setID = %@", 2275 set, 2276 newSetID); 2277 _SC_crash_once("_SCNetworkSetSetSetID() w/removed set", NULL, NULL); 2278 _SCErrorSet(kSCStatusInvalidArgument); 2279 return FALSE; 2280 } 2281 2282 // If newSetID is equal to current setID, our work is done 2283 if (CFEqual(newSetID, setPrivate->setID)) { 2284 return TRUE; 2285 } 2286 2287 newPath = SCPreferencesPathKeyCreateSet(NULL, newSetID); 2288 entity = SCPreferencesPathGetValue(setPrivate->prefs, newPath); 2289 if (isA_CFDictionary(entity)) { 2290 // if the new set already exists 2291 _SCErrorSet(kSCStatusKeyExists); 2292 goto done; 2293 } 2294 2295 oldPath = SCPreferencesPathKeyCreateSet(NULL, setPrivate->setID); 2296 entity = SCPreferencesPathGetValue(setPrivate->prefs, oldPath); 2297 if (!isA_CFDictionary(entity)) { 2298 // if the set has already been removed 2299 _SCErrorSet(kSCStatusNoKey); 2300 goto done; 2301 } 2302 2303 ok = SCPreferencesPathSetValue(setPrivate->prefs, newPath, entity); 2304 if (!ok) { 2305 goto done; 2306 } 2307 2308 ok = SCPreferencesPathRemoveValue(setPrivate->prefs, oldPath); 2309 if (!ok) { 2310 goto done; 2311 } 2312 2313 // update current set (if needed) 2314 currentSet = SCNetworkSetCopyCurrent(setPrivate->prefs); 2315 if (currentSet != NULL) { 2316 currentSetPrivate = (SCNetworkSetPrivateRef)currentSet; 2317 if (CFEqual(currentSetPrivate->setID, setPrivate->setID)) { 2318 updateCurrentSet = TRUE; 2319 } 2320 CFRelease(currentSet); 2321 } 2322 2323 SC_log(LOG_DEBUG, "_SCNetworkSetSetID(): %@ --> %@", set, newSetID); 2324 2325 // replace setID with new one 2326 CFRetain(newSetID); 2327 CFRelease(setPrivate->setID); 2328 setPrivate->setID = newSetID; 2329 2330 if (updateCurrentSet) { 2331 SCNetworkSetSetCurrent(set); 2332 } 2333 2334 done: 2335 2336 if (oldPath != NULL) { 2337 CFRelease(oldPath); 2338 } 2339 if (newPath != NULL) { 2340 CFRelease(newPath); 2341 } 2342 2343 return ok; 2344}