this repo has no description
at fixPythonPipStalling 2556 lines 75 kB view raw
1/* 2 * Copyright (c) 2004-2018 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#include "SCPreferencesInternal.h" 36 37#include <pthread.h> 38 39#define EXTERNAL_ID_DOMAIN_PREFIX "_" 40 41static CFStringRef __SCNetworkServiceCopyDescription (CFTypeRef cf); 42static void __SCNetworkServiceDeallocate (CFTypeRef cf); 43static Boolean __SCNetworkServiceEqual (CFTypeRef cf1, CFTypeRef cf2); 44static CFHashCode __SCNetworkServiceHash (CFTypeRef cf); 45 46 47static CFTypeID __kSCNetworkServiceTypeID = _kCFRuntimeNotATypeID; 48 49 50static const CFRuntimeClass __SCNetworkServiceClass = { 51 0, // version 52 "SCNetworkService", // className 53 NULL, // init 54 NULL, // copy 55 __SCNetworkServiceDeallocate, // dealloc 56 __SCNetworkServiceEqual, // equal 57 __SCNetworkServiceHash, // hash 58 NULL, // copyFormattingDesc 59 __SCNetworkServiceCopyDescription // copyDebugDesc 60}; 61 62 63static pthread_once_t initialized = PTHREAD_ONCE_INIT; 64 65 66static CFStringRef 67__SCNetworkServiceCopyDescription(CFTypeRef cf) 68{ 69 CFAllocatorRef allocator = CFGetAllocator(cf); 70 CFMutableStringRef result; 71 SCNetworkServiceRef service = (SCNetworkServiceRef)cf; 72 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service; 73 74 result = CFStringCreateMutable(allocator, 0); 75 CFStringAppendFormat(result, NULL, CFSTR("<SCNetworkService %p [%p]> {"), service, allocator); 76 CFStringAppendFormat(result, NULL, CFSTR("id = %@"), servicePrivate->serviceID); 77 if (servicePrivate->prefs != NULL) { 78 CFStringAppendFormat(result, NULL, CFSTR(", prefs = %p"), servicePrivate->prefs); 79 } else if (servicePrivate->store != NULL) { 80 CFStringAppendFormat(result, NULL, CFSTR(", store = %p"), servicePrivate->store); 81 } 82 if (servicePrivate->name != NULL) { 83 CFStringAppendFormat(result, NULL, CFSTR(", name = %@"), servicePrivate->name); 84 } 85 if (!__SCNetworkServiceExists(service)) { 86 CFStringAppendFormat(result, NULL, CFSTR(", REMOVED")); 87 } 88 CFStringAppendFormat(result, NULL, CFSTR("}")); 89 90 return result; 91} 92 93 94static void 95__SCNetworkServiceDeallocate(CFTypeRef cf) 96{ 97 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)cf; 98 99 /* release resources */ 100 101 CFRelease(servicePrivate->serviceID); 102 if (servicePrivate->interface != NULL) CFRelease(servicePrivate->interface); 103 if (servicePrivate->prefs != NULL) CFRelease(servicePrivate->prefs); 104 if (servicePrivate->store != NULL) CFRelease(servicePrivate->store); 105 if (servicePrivate->name != NULL) CFRelease(servicePrivate->name); 106 if (servicePrivate->externalIDs != NULL) CFRelease(servicePrivate->externalIDs); 107 108 return; 109} 110 111 112static Boolean 113__SCNetworkServiceEqual(CFTypeRef cf1, CFTypeRef cf2) 114{ 115 SCNetworkServicePrivateRef s1 = (SCNetworkServicePrivateRef)cf1; 116 SCNetworkServicePrivateRef s2 = (SCNetworkServicePrivateRef)cf2; 117 118 if (s1 == s2) 119 return TRUE; 120 121 if (s1->prefs != s2->prefs) 122 return FALSE; // if not the same prefs 123 124 if (!CFEqual(s1->serviceID, s2->serviceID)) 125 return FALSE; // if not the same service identifier 126 127 return TRUE; 128} 129 130 131static CFHashCode 132__SCNetworkServiceHash(CFTypeRef cf) 133{ 134 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)cf; 135 136 return CFHash(servicePrivate->serviceID); 137} 138 139 140static void 141__SCNetworkServiceInitialize(void) 142{ 143 __kSCNetworkServiceTypeID = _CFRuntimeRegisterClass(&__SCNetworkServiceClass); 144 return; 145} 146 147 148__private_extern__ SCNetworkServicePrivateRef 149__SCNetworkServiceCreatePrivate(CFAllocatorRef allocator, 150 SCPreferencesRef prefs, 151 CFStringRef serviceID, 152 SCNetworkInterfaceRef interface) 153{ 154 SCNetworkServicePrivateRef servicePrivate; 155 uint32_t size; 156 157 /* initialize runtime */ 158 pthread_once(&initialized, __SCNetworkServiceInitialize); 159 160 /* allocate target */ 161 size = sizeof(SCNetworkServicePrivate) - sizeof(CFRuntimeBase); 162 servicePrivate = (SCNetworkServicePrivateRef)_CFRuntimeCreateInstance(allocator, 163 __kSCNetworkServiceTypeID, 164 size, 165 NULL); 166 if (servicePrivate == NULL) { 167 return NULL; 168 } 169 170 /* initialize non-zero/NULL members */ 171 servicePrivate->prefs = (prefs != NULL) ? CFRetain(prefs): NULL; 172 servicePrivate->serviceID = CFStringCreateCopy(NULL, serviceID); 173 servicePrivate->interface = (interface != NULL) ? CFRetain(interface) : NULL; 174 175 return servicePrivate; 176} 177 178 179#pragma mark - 180#pragma mark Service ordering 181 182 183CFComparisonResult 184_SCNetworkServiceCompare(const void *val1, const void *val2, void *context) 185{ 186 CFStringRef id1; 187 CFStringRef id2; 188 CFArrayRef order = (CFArrayRef)context; 189 SCNetworkServiceRef s1 = (SCNetworkServiceRef)val1; 190 SCNetworkServiceRef s2 = (SCNetworkServiceRef)val2; 191 192 id1 = SCNetworkServiceGetServiceID(s1); 193 id2 = SCNetworkServiceGetServiceID(s2); 194 195 if (order != NULL) { 196 CFIndex o1; 197 CFIndex o2; 198 CFRange range; 199 200 range = CFRangeMake(0, CFArrayGetCount(order)); 201 o1 = CFArrayGetFirstIndexOfValue(order, range, id1); 202 o2 = CFArrayGetFirstIndexOfValue(order, range, id2); 203 204 if (o1 > o2) { 205 return (o2 != kCFNotFound) ? kCFCompareGreaterThan : kCFCompareLessThan; 206 } else if (o1 < o2) { 207 return (o1 != kCFNotFound) ? kCFCompareLessThan : kCFCompareGreaterThan; 208 } 209 } 210 211 return CFStringCompare(id1, id2, 0); 212} 213 214 215#pragma mark - 216#pragma mark SCNetworkService APIs 217 218 219#define N_QUICK 64 220 221 222__private_extern__ CFArrayRef /* of SCNetworkServiceRef's */ 223__SCNetworkServiceCopyAllEnabled(SCPreferencesRef prefs) 224{ 225 CFMutableArrayRef array = NULL; 226 CFIndex i_sets; 227 CFIndex n_sets; 228 CFArrayRef sets; 229 230 sets = SCNetworkSetCopyAll(prefs); 231 if (sets == NULL) { 232 return NULL; 233 } 234 235 n_sets = CFArrayGetCount(sets); 236 for (i_sets = 0; i_sets < n_sets; i_sets++) { 237 CFIndex i_services; 238 CFIndex n_services; 239 CFArrayRef services; 240 SCNetworkSetRef set; 241 242 set = CFArrayGetValueAtIndex(sets, i_sets); 243 services = SCNetworkSetCopyServices(set); 244 if (services == NULL) { 245 continue; 246 } 247 248 n_services = CFArrayGetCount(services); 249 for (i_services = 0; i_services < n_services; i_services++) { 250 SCNetworkServiceRef service; 251 252 service = CFArrayGetValueAtIndex(services, i_services); 253 if (!SCNetworkServiceGetEnabled(service)) { 254 // if not enabled 255 continue; 256 } 257 258 if ((array == NULL) || 259 !CFArrayContainsValue(array, 260 CFRangeMake(0, CFArrayGetCount(array)), 261 service)) { 262 if (array == NULL) { 263 array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 264 } 265 CFArrayAppendValue(array, service); 266 } 267 } 268 CFRelease(services); 269 } 270 CFRelease(sets); 271 272 return array; 273} 274 275 276__private_extern__ Boolean 277__SCNetworkServiceExistsForInterface(CFArrayRef services, SCNetworkInterfaceRef interface) 278{ 279 CFIndex i; 280 CFIndex n; 281 282 n = isA_CFArray(services) ? CFArrayGetCount(services) : 0; 283 for (i = 0; i < n; i++) { 284 SCNetworkServiceRef service; 285 SCNetworkInterfaceRef service_interface; 286 287 service = CFArrayGetValueAtIndex(services, i); 288 289 service_interface = SCNetworkServiceGetInterface(service); 290 while (service_interface != NULL) { 291 if (CFEqual(interface, service_interface)) { 292 return TRUE; 293 } 294 295 service_interface = SCNetworkInterfaceGetInterface(service_interface); 296 } 297 } 298 299 return FALSE; 300} 301 302 303static void 304mergeDict(const void *key, const void *value, void *context) 305{ 306 CFMutableDictionaryRef newDict = (CFMutableDictionaryRef)context; 307 308 CFDictionarySetValue(newDict, key, value); 309 return; 310} 311 312 313static CF_RETURNS_RETAINED CFDictionaryRef 314_protocolTemplate(SCNetworkServiceRef service, CFStringRef protocolType) 315{ 316 SCNetworkInterfaceRef interface; 317 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service; 318 CFDictionaryRef template = NULL; 319 320 interface = servicePrivate->interface; 321 if (interface != NULL) { 322 SCNetworkInterfaceRef childInterface; 323 CFStringRef childInterfaceType = NULL; 324 CFStringRef interfaceType; 325 326 // get the template 327 interfaceType = SCNetworkInterfaceGetInterfaceType(servicePrivate->interface); 328 childInterface = SCNetworkInterfaceGetInterface(servicePrivate->interface); 329 if (childInterface != NULL) { 330 childInterfaceType = SCNetworkInterfaceGetInterfaceType(childInterface); 331 } 332 333 template = __copyProtocolTemplate(interfaceType, childInterfaceType, protocolType); 334 if (template != NULL) { 335 CFDictionaryRef overrides; 336 337 // move to the interface at the lowest layer 338 while (childInterface != NULL) { 339 interface = childInterface; 340 childInterface = SCNetworkInterfaceGetInterface(interface); 341 } 342 343 overrides = __SCNetworkInterfaceGetTemplateOverrides(interface, protocolType); 344 if (isA_CFDictionary(overrides)) { 345 CFMutableDictionaryRef newTemplate; 346 347 newTemplate = CFDictionaryCreateMutableCopy(NULL, 0, template); 348 CFDictionaryApplyFunction(overrides, mergeDict, newTemplate); 349 CFRelease(template); 350 template = newTemplate; 351 } 352 } 353 } 354 355 if (template == NULL) { 356 template = CFDictionaryCreate(NULL, 357 NULL, 358 NULL, 359 0, 360 &kCFTypeDictionaryKeyCallBacks, 361 &kCFTypeDictionaryValueCallBacks); 362 } 363 364 return template; 365} 366 367 368Boolean 369SCNetworkServiceAddProtocolType(SCNetworkServiceRef service, CFStringRef protocolType) 370{ 371 CFDictionaryRef entity; 372 Boolean newEnabled; 373 CFDictionaryRef newEntity = NULL; 374 Boolean ok = FALSE; 375 CFStringRef path; 376 SCNetworkProtocolRef protocol = NULL; 377 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service; 378 379 if (!isA_SCNetworkService(service) || (servicePrivate->prefs == NULL)) { 380 _SCErrorSet(kSCStatusInvalidArgument); 381 return FALSE; 382 } 383 384 if (!__SCNetworkProtocolIsValidType(protocolType)) { 385 _SCErrorSet(kSCStatusInvalidArgument); 386 return FALSE; 387 } 388 389 if (!__SCNetworkServiceExists(service)) { 390 SC_log(LOG_ERR, "SCNetworkServiceAddProtocolType() w/removed service\n service = %@\n protocol = %@", 391 service, 392 protocolType); 393 _SC_crash_once("SCNetworkServiceAddProtocolType() w/removed service", NULL, NULL); 394 _SCErrorSet(kSCStatusInvalidArgument); 395 return FALSE; 396 } 397 398 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator 399 servicePrivate->serviceID, // service 400 protocolType); // entity 401 402 entity = SCPreferencesPathGetValue(servicePrivate->prefs, path); 403 if (entity != NULL) { 404 // if "protocol" already exists 405 _SCErrorSet(kSCStatusKeyExists); 406 goto done; 407 } 408 409 newEntity = CFDictionaryCreate(NULL, 410 NULL, 411 NULL, 412 0, 413 &kCFTypeDictionaryKeyCallBacks, 414 &kCFTypeDictionaryValueCallBacks); 415 ok = SCPreferencesPathSetValue(servicePrivate->prefs, path, newEntity); 416 CFRelease(newEntity); 417 newEntity = NULL; 418 if (!ok) { 419 goto done; 420 } 421 422 protocol = SCNetworkServiceCopyProtocol(service, protocolType); 423 assert(protocol != NULL); 424 425 newEntity = _protocolTemplate(service, protocolType); 426 assert(newEntity != NULL); 427 428 ok = SCNetworkProtocolSetConfiguration(protocol, newEntity); 429 if (!ok) { 430 // could not set default configuration 431 goto done; 432 } 433 434 newEnabled = !CFDictionaryContainsKey(newEntity, kSCResvInactive); 435 ok = SCNetworkProtocolSetEnabled(protocol, newEnabled); 436 if (!ok) { 437 // could not enable/disable protocol 438 goto done; 439 } 440 441 done : 442 443 if (newEntity != NULL) CFRelease(newEntity); 444 if (protocol != NULL) CFRelease(protocol); 445 446 if (ok) { 447 SC_log(LOG_DEBUG, "SCNetworkServiceAddProtocolType(): %@, %@", service, protocolType); 448 } 449 450 CFRelease(path); 451 return ok; 452} 453 454 455CFArrayRef /* of SCNetworkServiceRef's */ 456SCNetworkServiceCopyAll(SCPreferencesRef prefs) 457{ 458 CFMutableArrayRef array; 459 CFIndex n; 460 CFStringRef path; 461 CFDictionaryRef services; 462 463 path = SCPreferencesPathKeyCreateNetworkServices(NULL); 464 services = SCPreferencesPathGetValue(prefs, path); 465 CFRelease(path); 466 467 if ((services != NULL) && !isA_CFDictionary(services)) { 468 return NULL; 469 } 470 471 array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 472 473 n = (services != NULL) ? CFDictionaryGetCount(services) : 0; 474 if (n > 0) { 475 CFIndex i; 476 const void * keys_q[N_QUICK]; 477 const void ** keys = keys_q; 478 const void * vals_q[N_QUICK]; 479 const void ** vals = vals_q; 480 481 if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) { 482 keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0); 483 vals = CFAllocatorAllocate(NULL, n * sizeof(CFPropertyListRef), 0); 484 } 485 CFDictionaryGetKeysAndValues(services, keys, vals); 486 for (i = 0; i < n; i++) { 487 CFDictionaryRef entity; 488 SCNetworkServicePrivateRef servicePrivate; 489 490 if (!isA_CFDictionary(vals[i])) { 491 SC_log(LOG_INFO, "error w/service \"%@\"", keys[i]); 492 continue; 493 } 494 495 entity = CFDictionaryGetValue(vals[i], kSCEntNetInterface); 496 if (!isA_CFDictionary(entity)) { 497 // if no "interface" 498 SC_log(LOG_INFO, "no \"%@\" entity for service \"%@\"", 499 kSCEntNetInterface, 500 keys[i]); 501 continue; 502 } 503 504 if (__SCNetworkInterfaceEntityIsPPTP(entity)) { 505 SC_log(LOG_INFO, "PPTP services are no longer supported"); 506 continue; 507 } 508 509 servicePrivate = __SCNetworkServiceCreatePrivate(NULL, prefs, keys[i], NULL); 510 assert(servicePrivate != NULL); 511 CFArrayAppendValue(array, (SCNetworkServiceRef)servicePrivate); 512 CFRelease(servicePrivate); 513 } 514 if (keys != keys_q) { 515 CFAllocatorDeallocate(NULL, keys); 516 CFAllocatorDeallocate(NULL, vals); 517 } 518 } 519 520 return array; 521} 522 523 524__private_extern__ 525CFArrayRef /* of SCNetworkInterfaceRef's */ 526__SCNetworkServiceCopyAllInterfaces(SCPreferencesRef prefs) 527{ 528 CFMutableArrayRef interfaces = NULL; 529 CFArrayRef services = NULL; 530 CFIndex servicesCount = 0; 531 SCNetworkServiceRef service = NULL; 532 SCNetworkInterfaceRef interface = NULL; 533 534 services = SCNetworkServiceCopyAll(prefs); 535 if (services == NULL) { 536 goto done; 537 } 538 539 servicesCount = CFArrayGetCount(services); 540 if (servicesCount == 0) { 541 goto done; 542 } 543 544 interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 545 546 for (CFIndex idx = 0; idx < servicesCount; idx++) { 547 service = CFArrayGetValueAtIndex(services, idx); 548 interface = SCNetworkServiceGetInterface(service); 549 550 if (isA_SCNetworkInterface(interface) == NULL) { 551 continue; 552 } 553 CFArrayAppendValue(interfaces, interface); 554 } 555 556 if (CFArrayGetCount(interfaces) == 0) { 557 // Do not return an empty array 558 CFRelease(interfaces); 559 interfaces = NULL; 560 } 561 562 done: 563 564 if (services != NULL) { 565 CFRelease(services); 566 } 567 return interfaces; 568} 569 570 571/* 572 * build a list of all of a services entity types that are associated 573 * with the services interface. The list will include : 574 * 575 * - entity types associated with the interface type (Ethernet, FireWire, PPP, ...) 576 * - entity types associated with the interface sub-type (PPPSerial, PPPoE, L2TP, PPTP, ...) 577 * - entity types associated with the hardware device (Ethernet, AirPort, FireWire, Modem, ...) 578 */ 579static CFSetRef 580_copyInterfaceEntityTypes(CFDictionaryRef protocols) 581{ 582 CFDictionaryRef interface; 583 CFMutableSetRef interface_entity_types; 584 585 interface_entity_types = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks); 586 587 interface = CFDictionaryGetValue(protocols, kSCEntNetInterface); 588 if (isA_CFDictionary(interface)) { 589 CFStringRef entities[] = { kSCPropNetInterfaceType, 590 kSCPropNetInterfaceSubType, 591 kSCPropNetInterfaceHardware }; 592 593 // include the "Interface" entity itself 594 CFSetAddValue(interface_entity_types, kSCEntNetInterface); 595 596 // include the entities associated with the interface 597 for (size_t i = 0; i < sizeof(entities)/sizeof(entities[0]); i++) { 598 CFStringRef entity; 599 600 entity = CFDictionaryGetValue(interface, entities[i]); 601 if (isA_CFString(entity)) { 602 CFSetAddValue(interface_entity_types, entity); 603 } 604 } 605 606 /* 607 * and, because we've found some misguided network preference code 608 * developers leaving [PPP] entity dictionaries around even though 609 * they are unused and/or unneeded... 610 */ 611 CFSetAddValue(interface_entity_types, kSCEntNetPPP); 612 } 613 614 return interface_entity_types; 615} 616 617 618SCNetworkServiceRef 619SCNetworkServiceCopy(SCPreferencesRef prefs, CFStringRef serviceID) 620{ 621 CFDictionaryRef entity; 622 CFStringRef path; 623 SCNetworkServicePrivateRef servicePrivate; 624 625 if (!isA_CFString(serviceID)) { 626 _SCErrorSet(kSCStatusInvalidArgument); 627 return NULL; 628 } 629 630 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator 631 serviceID, // service 632 kSCEntNetInterface); // entity 633 entity = SCPreferencesPathGetValue(prefs, path); 634 CFRelease(path); 635 636 if (!isA_CFDictionary(entity)) { 637 // a "service" must have an "interface" 638 _SCErrorSet(kSCStatusNoKey); 639 return NULL; 640 } 641 642 if (__SCNetworkInterfaceEntityIsPPTP(entity)) { 643 SC_log(LOG_INFO, "PPTP services are no longer supported"); 644 _SCErrorSet(kSCStatusNoKey); 645 return NULL; 646 } 647 648 servicePrivate = __SCNetworkServiceCreatePrivate(NULL, prefs, serviceID, NULL); 649 return (SCNetworkServiceRef)servicePrivate; 650} 651 652 653SCNetworkServiceRef 654_SCNetworkServiceCopyActive(SCDynamicStoreRef store, CFStringRef serviceID) 655{ 656 SCNetworkServicePrivateRef servicePrivate; 657 658 if (!isA_CFString(serviceID)) { 659 _SCErrorSet(kSCStatusInvalidArgument); 660 return NULL; 661 } 662 663 servicePrivate = __SCNetworkServiceCreatePrivate(NULL, NULL, serviceID, NULL); 664 assert(servicePrivate != NULL); 665 if (store != NULL) { 666 servicePrivate->store = CFRetain(store); 667 } 668 return (SCNetworkServiceRef)servicePrivate; 669} 670 671 672SCNetworkProtocolRef 673SCNetworkServiceCopyProtocol(SCNetworkServiceRef service, CFStringRef protocolType) 674{ 675 CFSetRef non_protocol_entities; 676 CFStringRef path; 677 CFDictionaryRef protocols; 678 SCNetworkProtocolPrivateRef protocolPrivate = NULL; 679 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service; 680 681 if (!isA_SCNetworkService(service) || (servicePrivate->prefs == NULL)) { 682 _SCErrorSet(kSCStatusInvalidArgument); 683 return NULL; 684 } 685 686 if (!isA_CFString(protocolType)) { 687 _SCErrorSet(kSCStatusInvalidArgument); 688 return NULL; 689 } 690 691 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator 692 servicePrivate->serviceID, // service 693 NULL); // entity 694 protocols = SCPreferencesPathGetValue(servicePrivate->prefs, path); 695 CFRelease(path); 696 697 if (!isA_CFDictionary(protocols)) { 698 // if corrupt prefs 699 _SCErrorSet(kSCStatusFailed); 700 return NULL; 701 } 702 703 non_protocol_entities = _copyInterfaceEntityTypes(protocols); 704 if (CFSetContainsValue(non_protocol_entities, protocolType)) { 705 // if the "protocolType" matches an interface entity type 706 _SCErrorSet(kSCStatusInvalidArgument); 707 goto done; 708 } 709 710 if (!CFDictionaryContainsKey(protocols, protocolType)) { 711 // if the "protocolType" entity does not exist 712 _SCErrorSet(kSCStatusNoKey); 713 goto done; 714 } 715 716 protocolPrivate = __SCNetworkProtocolCreatePrivate(NULL, protocolType, service); 717 718 done : 719 720 CFRelease(non_protocol_entities); 721 722 return (SCNetworkProtocolRef)protocolPrivate; 723} 724 725 726CFArrayRef /* of SCNetworkProtocolRef's */ 727SCNetworkServiceCopyProtocols(SCNetworkServiceRef service) 728{ 729 CFMutableArrayRef array; 730 CFIndex n; 731 CFSetRef non_protocol_entities; 732 CFStringRef path; 733 CFDictionaryRef protocols; 734 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service; 735 736 if (!isA_SCNetworkService(service) || (servicePrivate->prefs == NULL)) { 737 _SCErrorSet(kSCStatusInvalidArgument); 738 return NULL; 739 } 740 741 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator 742 servicePrivate->serviceID, // service 743 NULL); // entity 744 protocols = SCPreferencesPathGetValue(servicePrivate->prefs, path); 745 CFRelease(path); 746 747 if (!isA_CFDictionary(protocols)) { 748 // if corrupt prefs 749 _SCErrorSet(kSCStatusFailed); 750 return NULL; 751 } 752 753 non_protocol_entities = _copyInterfaceEntityTypes(protocols); 754 755 array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 756 757 n = CFDictionaryGetCount(protocols); 758 if (n > 0) { 759 CFIndex i; 760 const void * keys_q[N_QUICK]; 761 const void ** keys = keys_q; 762 const void * vals_q[N_QUICK]; 763 const void ** vals = vals_q; 764 765 if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) { 766 keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0); 767 vals = CFAllocatorAllocate(NULL, n * sizeof(CFPropertyListRef), 0); 768 } 769 CFDictionaryGetKeysAndValues(protocols, keys, vals); 770 for (i = 0; i < n; i++) { 771 SCNetworkProtocolPrivateRef protocolPrivate; 772 773 if (!isA_CFDictionary(vals[i])) { 774 // if it's not a dictionary then it can't be a protocol entity 775 continue; 776 } 777 778 if (CFSetContainsValue(non_protocol_entities, keys[i])) { 779 // skip any non-protocol (interface) entities 780 continue; 781 } 782 783 protocolPrivate = __SCNetworkProtocolCreatePrivate(NULL, keys[i], service); 784 CFArrayAppendValue(array, (SCNetworkProtocolRef)protocolPrivate); 785 786 CFRelease(protocolPrivate); 787 } 788 if (keys != keys_q) { 789 CFAllocatorDeallocate(NULL, keys); 790 CFAllocatorDeallocate(NULL, vals); 791 } 792 } 793 794 CFRelease(non_protocol_entities); 795 796 return array; 797} 798 799 800static Boolean 801__SCNetworkServiceSetInterfaceEntity(SCNetworkServiceRef service, 802 SCNetworkInterfaceRef interface) 803{ 804 CFDictionaryRef entity; 805 Boolean ok; 806 CFStringRef path; 807 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service; 808 809 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator 810 servicePrivate->serviceID, // service 811 kSCEntNetInterface); // entity 812 entity = __SCNetworkInterfaceCopyInterfaceEntity(interface); 813 ok = SCPreferencesPathSetValue(servicePrivate->prefs, path, entity); 814 CFRelease(entity); 815 CFRelease(path); 816 817 return ok; 818} 819 820 821SCNetworkServiceRef 822SCNetworkServiceCreate(SCPreferencesRef prefs, SCNetworkInterfaceRef interface) 823{ 824 CFArrayRef components; 825 CFArrayRef interface_config; 826 CFStringRef interface_name; 827 SCNetworkInterfaceRef newInterface; 828 CFStringRef path; 829 CFStringRef prefix; 830 CFStringRef serviceID; 831 SCNetworkServicePrivateRef servicePrivate; 832 CFArrayRef supported_protocols; 833 834 if (!isA_SCNetworkInterface(interface)) { 835 _SCErrorSet(kSCStatusInvalidArgument); 836 return NULL; 837 } 838 839 // only allow network interfaces which support one or more protocols 840 // to be added to a service. The one exception is that we allow 841 // third-party interface types to be configured. 842 supported_protocols = SCNetworkInterfaceGetSupportedProtocolTypes(interface); 843 if (supported_protocols == NULL) { 844 CFStringRef interface_type; 845 846 interface_type = SCNetworkInterfaceGetInterfaceType(interface); 847 if (CFStringFind(interface_type, CFSTR("."), 0).location == kCFNotFound) { 848 _SCErrorSet(kSCStatusInvalidArgument); 849 return NULL; 850 } 851 } 852 853 // do not allow creation of a network service if the interface is a 854 // member of a bond or bridge 855 if (__SCNetworkInterfaceIsMember(prefs, interface)) { 856 _SCErrorSet(kSCStatusKeyExists); 857 return NULL; 858 } 859 860 // establish the service 861 prefix = SCPreferencesPathKeyCreateNetworkServices(NULL); 862 path = __SCPreferencesPathCreateUniqueChild_WithMoreSCFCompatibility(prefs, prefix); 863 if (path == NULL) path = SCPreferencesPathCreateUniqueChild(prefs, prefix); 864 CFRelease(prefix); 865 if (path == NULL) { 866 return NULL; 867 } 868 869 components = CFStringCreateArrayBySeparatingStrings(NULL, path, CFSTR("/")); 870 CFRelease(path); 871 872 serviceID = CFArrayGetValueAtIndex(components, 2); 873 servicePrivate = __SCNetworkServiceCreatePrivate(NULL, prefs, serviceID, NULL); 874 CFRelease(components); 875 876 // duplicate the interface and associate the copy with the new service 877 newInterface = (SCNetworkInterfaceRef)__SCNetworkInterfaceCreateCopy(NULL, 878 interface, 879 prefs, 880 serviceID); 881 servicePrivate->interface = newInterface; 882 883 // establish "default" configuration(s) for the interface 884 for (interface = newInterface; 885 interface != NULL; 886 interface = SCNetworkInterfaceGetInterface(interface)) { 887 SCNetworkInterfaceRef childInterface; 888 CFStringRef childInterfaceType = NULL; 889 CFDictionaryRef config; 890 CFStringRef interfaceType; 891 892 interfaceType = SCNetworkInterfaceGetInterfaceType(interface); 893 childInterface = SCNetworkInterfaceGetInterface(interface); 894 if (childInterface != NULL) { 895 childInterfaceType = SCNetworkInterfaceGetInterfaceType(childInterface); 896 } 897 898 config = __copyInterfaceTemplate(interfaceType, childInterfaceType); 899 if (config != NULL) { 900 if (CFEqual(interfaceType, kSCNetworkInterfaceTypeBluetooth) || 901 CFEqual(interfaceType, kSCNetworkInterfaceTypeIrDA ) || 902 CFEqual(interfaceType, kSCNetworkInterfaceTypeModem ) || 903 CFEqual(interfaceType, kSCNetworkInterfaceTypeSerial ) || 904 CFEqual(interfaceType, kSCNetworkInterfaceTypeWWAN )) { 905 CFDictionaryRef overrides; 906 907 overrides = __SCNetworkInterfaceGetTemplateOverrides(interface, kSCNetworkInterfaceTypeModem); 908 909 // a ConnectionScript (and related keys) from the interface 910 // should trump the settings from the configuration template. 911 if (isA_CFDictionary(overrides)) { 912 CFMutableDictionaryRef newConfig; 913 914 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config); 915 if (CFDictionaryContainsKey(overrides, kSCPropNetModemConnectionScript)) { 916 CFDictionaryRemoveValue(newConfig, kSCPropNetModemConnectionPersonality); 917 CFDictionaryRemoveValue(newConfig, kSCPropNetModemConnectionScript); 918 CFDictionaryRemoveValue(newConfig, kSCPropNetModemDeviceVendor); 919 CFDictionaryRemoveValue(newConfig, kSCPropNetModemDeviceModel); 920 } 921 CFDictionaryApplyFunction(overrides, mergeDict, newConfig); 922 CFRelease(config); 923 config = newConfig; 924 } 925 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPP) || 926 CFEqual(interfaceType, kSCNetworkInterfaceTypeVPN)) { 927 CFDictionaryRef overrides; 928 929 overrides = __SCNetworkInterfaceGetTemplateOverrides(interface, kSCNetworkInterfaceTypePPP); 930 if (isA_CFDictionary(overrides)) { 931 CFMutableDictionaryRef newConfig; 932 933 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config); 934 CFDictionaryApplyFunction(overrides, mergeDict, newConfig); 935 CFRelease(config); 936 config = newConfig; 937 } 938 } 939 940 if (!__SCNetworkInterfaceSetConfiguration(interface, NULL, config, TRUE)) { 941 SC_log(LOG_INFO, "__SCNetworkInterfaceSetConfiguration failed(), interface=%@, type=NULL", 942 interface); 943 } 944 CFRelease(config); 945 } 946 } 947 948 // add the interface [entity] to the service 949 (void) __SCNetworkServiceSetInterfaceEntity((SCNetworkServiceRef)servicePrivate, 950 servicePrivate->interface); 951 952 // push the [deep] interface configuration into the service. 953 interface_config = __SCNetworkInterfaceCopyDeepConfiguration(NULL, servicePrivate->interface); 954 __SCNetworkInterfaceSetDeepConfiguration(NULL, servicePrivate->interface, interface_config); 955 if (interface_config != NULL) CFRelease(interface_config); 956 957 // set the service name to match that of the associated interface 958 // 959 // Note: It might seem a bit odd to call SCNetworkServiceGetName 960 // followed by an immediate call to SCNetworkServiceSetName. The 961 // trick here is that if no name has previously been set, the 962 // "get" function will return the name of the associated interface. 963 // 964 // ... and we "set" a name to ensure that applications that do 965 // not use the APIs will still find a UserDefinedName property 966 // in the SCDynamicStore. 967 // 968 interface_name = SCNetworkServiceGetName((SCNetworkServiceRef)servicePrivate); 969 if (interface_name != NULL) { 970 (void) SCNetworkServiceSetName((SCNetworkServiceRef)servicePrivate, 971 interface_name); 972 } 973 974 SC_log(LOG_DEBUG, "SCNetworkServiceCreate(): %@", servicePrivate); 975 976 return (SCNetworkServiceRef)servicePrivate; 977} 978 979 980Boolean 981SCNetworkServiceEstablishDefaultConfiguration(SCNetworkServiceRef service) 982{ 983 CFIndex i; 984 SCNetworkInterfaceRef interface; 985 CFIndex n; 986 Boolean ok; 987 CFArrayRef protocolTypes; 988 CFStringRef rankStr; 989 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service; 990 991 if (!isA_SCNetworkService(service) || (servicePrivate->prefs == NULL)) { 992 _SCErrorSet(kSCStatusInvalidArgument); 993 return FALSE; 994 } 995 996 interface = SCNetworkServiceGetInterface(service); 997 if (interface == NULL) { 998 return FALSE; 999 } 1000 1001 protocolTypes = SCNetworkInterfaceGetSupportedProtocolTypes(interface); 1002 n = (protocolTypes != NULL) ? CFArrayGetCount(protocolTypes) : 0; 1003 for (i = 0; i < n; i++) { 1004 CFStringRef protocolType; 1005 1006 protocolType = CFArrayGetValueAtIndex(protocolTypes, i); 1007 ok = SCNetworkServiceAddProtocolType(service, protocolType); 1008 if (!ok) { 1009 SC_log(LOG_INFO, 1010 "SCNetworkServiceEstablishDefaultConfiguration(): could not add protocol \"%@\"", 1011 protocolType); 1012 } 1013 } 1014 1015 rankStr = __SCNetworkInterfaceGetTemplateOverrides(interface, kSCPropNetServicePrimaryRank); 1016 if (isA_CFString(rankStr)) { 1017 SCNetworkServicePrimaryRank rank; 1018 1019 ok = __str_to_rank(rankStr, &rank); 1020 if (!ok) { 1021 SC_log(LOG_INFO, 1022 "SCNetworkServiceEstablishDefaultConfiguration(): unknown rank \"%@\"", 1023 rankStr); 1024 goto done; 1025 } 1026 1027 ok = SCNetworkServiceSetPrimaryRank(service, rank); 1028 if (!ok) { 1029 SC_log(LOG_INFO, 1030 "SCNetworkServiceEstablishDefaultConfiguration(): could not set rank \"%@\"", 1031 rankStr); 1032 goto done; 1033 } 1034 } 1035 1036 done : 1037 1038 return TRUE; 1039} 1040 1041 1042Boolean 1043SCNetworkServiceGetEnabled(SCNetworkServiceRef service) 1044{ 1045 Boolean enabled; 1046 CFStringRef path; 1047 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service; 1048 1049 if (!isA_SCNetworkService(service) || (servicePrivate->prefs == NULL)) { 1050 _SCErrorSet(kSCStatusInvalidArgument); 1051 return FALSE; 1052 } 1053 1054 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator 1055 servicePrivate->serviceID, // service 1056 NULL); // entity 1057 enabled = __getPrefsEnabled(servicePrivate->prefs, path); 1058 CFRelease(path); 1059 1060 return enabled; 1061} 1062 1063 1064SCNetworkInterfaceRef 1065SCNetworkServiceGetInterface(SCNetworkServiceRef service) 1066{ 1067 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service; 1068 1069 if (!isA_SCNetworkService(service) || (servicePrivate->prefs == NULL)) { 1070 _SCErrorSet(kSCStatusInvalidArgument); 1071 return NULL; 1072 } 1073 1074 if (servicePrivate->interface == NULL) { 1075 CFDictionaryRef entity; 1076 CFStringRef path; 1077 1078 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator 1079 servicePrivate->serviceID, // service 1080 kSCEntNetInterface); // entity 1081 entity = SCPreferencesPathGetValue(servicePrivate->prefs, path); 1082 CFRelease(path); 1083 1084 if (isA_CFDictionary(entity)) { 1085 servicePrivate->interface = _SCNetworkInterfaceCreateWithEntity(NULL, entity, service); 1086 } 1087 } 1088 1089 return servicePrivate->interface; 1090} 1091 1092 1093CFStringRef 1094SCNetworkServiceGetName(SCNetworkServiceRef service) 1095{ 1096 CFDictionaryRef entity; 1097 SCNetworkInterfaceRef interface; 1098 CFStringRef name = NULL; 1099 CFStringRef path; 1100 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service; 1101 Boolean useSystemInterfaces = TRUE; 1102 1103 if (!isA_SCNetworkService(service) || (servicePrivate->prefs == NULL)) { 1104 _SCErrorSet(kSCStatusInvalidArgument); 1105 return NULL; 1106 } 1107 1108 if (servicePrivate->name != NULL) { 1109 return servicePrivate->name; 1110 } 1111 1112 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator 1113 servicePrivate->serviceID, // service 1114 NULL); // entity 1115 entity = SCPreferencesPathGetValue(servicePrivate->prefs, path); 1116 CFRelease(path); 1117 1118 useSystemInterfaces = ((__SCPreferencesUsingDefaultPrefs(servicePrivate->prefs)) && 1119 !__SCPreferencesGetLimitSCNetworkConfiguration(servicePrivate->prefs)); 1120 1121 if (isA_CFDictionary(entity)) { 1122 name = CFDictionaryGetValue(entity, kSCPropUserDefinedName); 1123 if (isA_CFString(name)) { 1124 servicePrivate->name = CFRetain(name); 1125 if (!useSystemInterfaces) { 1126 return servicePrivate->name; 1127 } 1128 } 1129 } 1130 1131 interface = SCNetworkServiceGetInterface(service); 1132 while (interface != NULL) { 1133 SCNetworkInterfaceRef childInterface; 1134 CFStringRef interfaceType; 1135 1136 interfaceType = SCNetworkInterfaceGetInterfaceType(interface); 1137 if (CFEqual(interfaceType, kSCNetworkInterfaceTypeVPN)) { 1138 break; 1139 } 1140 1141 childInterface = SCNetworkInterfaceGetInterface(interface); 1142 if ((childInterface == NULL) || 1143 CFEqual(childInterface, kSCNetworkInterfaceIPv4)) { 1144 break; 1145 } 1146 1147 interface = childInterface; 1148 } 1149 1150 if (interface != NULL) { 1151 int i; 1152 CFStringRef interface_name = NULL; 1153 CFStringRef suffix = NULL; 1154 1155 // 1156 // check if the [stored] service name matches the non-localized interface 1157 // name. If so, return the localized name. 1158 // 1159 // Also, the older "Built-in XXX" interface names are too long for the 1160 // current UI. If we find that the [stored] service name matches the older 1161 // name, return the newer (and shorter) localized name. 1162 // 1163 // Note: the user/admin will no longer be able to set the service name 1164 // to "Built-in Ethernet". 1165 // 1166 for (i = 0; i < 3; i++) { 1167 if (servicePrivate->name == NULL) { 1168 // if no [stored] service name to compare 1169 break; 1170 } 1171 1172 switch (i) { 1173 case 0 : 1174 // compare the non-localized interface name 1175 interface_name = __SCNetworkInterfaceGetNonLocalizedDisplayName(interface); 1176 if (interface_name != NULL) { 1177 CFRetain(interface_name); 1178 } 1179 break; 1180#if !TARGET_OS_IPHONE 1181 case 1 : 1182 // compare the older "Built-in XXX" localized name 1183 interface_name = __SCNetworkInterfaceCopyXLocalizedDisplayName(interface); 1184 break; 1185 case 2 : 1186 // compare the older "Built-in XXX" non-localized name 1187 interface_name = __SCNetworkInterfaceCopyXNonLocalizedDisplayName(interface); 1188 break; 1189#else // !TARGET_OS_IPHONE 1190 default : 1191 continue; 1192#endif // !TARGET_OS_IPHONE 1193 } 1194 1195 if (interface_name != NULL) { 1196 Boolean match = FALSE; 1197 1198 if (CFEqual(name, interface_name)) { 1199 // if service name matches the OLD localized 1200 // interface name 1201 match = TRUE; 1202 } else if (CFStringHasPrefix(name, interface_name)) { 1203 CFIndex prefixLen = CFStringGetLength(interface_name); 1204 CFIndex suffixLen = CFStringGetLength(name); 1205 1206 suffix = CFStringCreateWithSubstring(NULL, 1207 name, 1208 CFRangeMake(prefixLen, suffixLen - prefixLen)); 1209 match = TRUE; 1210 } 1211 CFRelease(interface_name); 1212 1213 if (match) { 1214 CFRelease(servicePrivate->name); 1215 servicePrivate->name = NULL; 1216 break; 1217 } 1218 } 1219 } 1220 1221 // 1222 // if the service name has not been set, use the localized interface name 1223 // 1224 if (servicePrivate->name == NULL) { 1225 interface_name = SCNetworkInterfaceGetLocalizedDisplayName(interface); 1226 if (interface_name != NULL) { 1227 if (suffix != NULL) { 1228 servicePrivate->name = CFStringCreateWithFormat(NULL, 1229 NULL, 1230 CFSTR("%@%@"), 1231 interface_name, 1232 suffix); 1233 } else { 1234 servicePrivate->name = CFRetain(interface_name); 1235 } 1236 } 1237 } 1238 if (suffix != NULL) CFRelease(suffix); 1239 } 1240 1241 return servicePrivate->name; 1242} 1243 1244 1245CFStringRef 1246SCNetworkServiceGetServiceID(SCNetworkServiceRef service) 1247{ 1248 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service; 1249 1250 if (!isA_SCNetworkService(service)) { 1251 _SCErrorSet(kSCStatusInvalidArgument); 1252 return NULL; 1253 } 1254 1255 return servicePrivate->serviceID; 1256} 1257 1258 1259CFTypeID 1260SCNetworkServiceGetTypeID(void) 1261{ 1262 pthread_once(&initialized, __SCNetworkServiceInitialize); /* initialize runtime */ 1263 return __kSCNetworkServiceTypeID; 1264} 1265 1266 1267Boolean 1268SCNetworkServiceRemove(SCNetworkServiceRef service) 1269{ 1270 Boolean ok = FALSE; 1271 CFStringRef path; 1272 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service; 1273 CFArrayRef sets; 1274 1275 if (!isA_SCNetworkService(service) || (servicePrivate->prefs == NULL)) { 1276 _SCErrorSet(kSCStatusInvalidArgument); 1277 return FALSE; 1278 } 1279 1280 if (!__SCNetworkServiceExists(service)) { 1281 SC_log(LOG_ERR, "SCNetworkServiceRemove() w/removed service\n service = %@", service); 1282 _SC_crash_once("SCNetworkServiceRemove() w/removed service", NULL, NULL); 1283 _SCErrorSet(kSCStatusInvalidArgument); 1284 return FALSE; 1285 } 1286 1287 // remove service from all sets 1288 1289 sets = SCNetworkSetCopyAll(servicePrivate->prefs); 1290 if (sets != NULL) { 1291 CFIndex n; 1292 1293 n = CFArrayGetCount(sets); 1294 for (CFIndex i = 0; i < n; i++) { 1295 SCNetworkSetRef set; 1296 1297 set = CFArrayGetValueAtIndex(sets, i); 1298 ok = SCNetworkSetRemoveService(set, service); 1299 if (!ok && (SCError() != kSCStatusNoKey)) { 1300 CFRelease(sets); 1301 return ok; 1302 } 1303 } 1304 CFRelease(sets); 1305 } 1306 1307 // remove service 1308 1309 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator 1310 servicePrivate->serviceID, // service 1311 NULL); // entity 1312 ok = SCPreferencesPathRemoveValue(servicePrivate->prefs, path); 1313 CFRelease(path); 1314 1315 if (ok) { 1316 SC_log(LOG_DEBUG, "SCNetworkServiceRemove(): %@", service); 1317 } 1318 1319 return ok; 1320} 1321 1322 1323Boolean 1324SCNetworkServiceRemoveProtocolType(SCNetworkServiceRef service, CFStringRef protocolType) 1325{ 1326 CFDictionaryRef entity; 1327 Boolean ok = FALSE; 1328 CFStringRef path; 1329 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service; 1330 1331 if (!isA_SCNetworkService(service) || (servicePrivate->prefs == NULL)) { 1332 _SCErrorSet(kSCStatusInvalidArgument); 1333 return FALSE; 1334 } 1335 1336 if (!__SCNetworkServiceExists(service)) { 1337 SC_log(LOG_ERR, "SCNetworkServiceRemoveProtocolType() w/removed service\n service = %@\n protocol = %@", 1338 service, 1339 protocolType); 1340 _SC_crash_once("SCNetworkServiceRemoveProtocolType() w/removed service", NULL, NULL); 1341 _SCErrorSet(kSCStatusInvalidArgument); 1342 return FALSE; 1343 } 1344 1345 if (!__SCNetworkProtocolIsValidType(protocolType)) { 1346 _SCErrorSet(kSCStatusInvalidArgument); 1347 return FALSE; 1348 } 1349 1350 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator 1351 servicePrivate->serviceID, // service 1352 protocolType); // entity 1353 1354 entity = SCPreferencesPathGetValue(servicePrivate->prefs, path); 1355 if (entity == NULL) { 1356 // if "protocol" does not exist 1357 _SCErrorSet(kSCStatusNoKey); 1358 goto done; 1359 } 1360 1361 ok = SCPreferencesPathRemoveValue(servicePrivate->prefs, path); 1362 1363 done : 1364 1365 if (ok) { 1366 SC_log(LOG_DEBUG, "SCNetworkServiceRemoveProtocolType(): %@, %@", service, protocolType); 1367 } 1368 1369 CFRelease(path); 1370 return ok; 1371} 1372 1373 1374Boolean 1375SCNetworkServiceSetEnabled(SCNetworkServiceRef service, Boolean enabled) 1376{ 1377 Boolean ok; 1378 CFStringRef path; 1379 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service; 1380 1381 if (!isA_SCNetworkService(service) || (servicePrivate->prefs == NULL)) { 1382 _SCErrorSet(kSCStatusInvalidArgument); 1383 return FALSE; 1384 } 1385 1386 if (!__SCNetworkServiceExists(service)) { 1387 SC_log(LOG_ERR, "SCNetworkServiceSetEnabled() w/removed service\n service = %@", service); 1388 _SC_crash_once("SCNetworkProtocolSetEnabled() w/removed service", NULL, NULL); 1389 _SCErrorSet(kSCStatusInvalidArgument); 1390 return FALSE; 1391 } 1392 1393 // make sure that we do not enable a network service if the 1394 // associated interface is a member of a bond or bridge. 1395 if (enabled) { 1396 SCNetworkInterfaceRef interface; 1397 1398 interface = SCNetworkServiceGetInterface(service); 1399 if ((interface != NULL) && 1400 __SCNetworkInterfaceIsMember(servicePrivate->prefs, interface)) { 1401 _SCErrorSet(kSCStatusKeyExists); 1402 return FALSE; 1403 } 1404 } 1405 1406 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator 1407 servicePrivate->serviceID, // service 1408 NULL); // entity 1409 ok = __setPrefsEnabled(servicePrivate->prefs, path, enabled); 1410 CFRelease(path); 1411 1412 if (ok) { 1413 SC_log(LOG_DEBUG, "SCNetworkServiceSetEnabled(): %@ -> %s", 1414 service, 1415 enabled ? "Enabled" : "Disabled"); 1416 } 1417 1418 return ok; 1419} 1420 1421 1422Boolean 1423SCNetworkServiceSetName(SCNetworkServiceRef service, CFStringRef name) 1424{ 1425 CFDictionaryRef entity; 1426 Boolean ok = FALSE; 1427 CFStringRef path; 1428 CFStringRef saveName = NULL; 1429 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service; 1430 1431 if (!isA_SCNetworkService(service) || (servicePrivate->prefs == NULL)) { 1432 _SCErrorSet(kSCStatusInvalidArgument); 1433 return FALSE; 1434 } 1435 1436 if (!__SCNetworkServiceExists(service)) { 1437 SC_log(LOG_ERR, "SCNetworkServiceSetName() w/removed service\n service = %@\n name = %@", 1438 service, 1439 name != NULL ? name : CFSTR("<NULL>")); 1440 _SC_crash_once("SCNetworkServiceSetName() w/removed service", NULL, NULL); 1441 _SCErrorSet(kSCStatusInvalidArgument); 1442 return FALSE; 1443 } 1444 1445 if (name != NULL) { 1446 if (!isA_CFString(name)) { 1447 _SCErrorSet(kSCStatusInvalidArgument); 1448 return FALSE; 1449 } 1450 saveName = CFRetain(name); 1451 } 1452 1453 if (name != NULL) { 1454 SCNetworkInterfaceRef interface; 1455 1456 interface = SCNetworkServiceGetInterface(service); 1457 while (interface != NULL) { 1458 SCNetworkInterfaceRef childInterface; 1459 1460 childInterface = SCNetworkInterfaceGetInterface(interface); 1461 if (childInterface == NULL) { 1462 break; 1463 } 1464 1465 interface = childInterface; 1466 } 1467 1468 if (interface != NULL) { 1469 CFStringRef interface_name; 1470 1471 interface_name = SCNetworkInterfaceGetLocalizedDisplayName(interface); 1472 if (interface_name != NULL) { 1473 if (CFEqual(name, interface_name)) { 1474 // if service name matches the localized interface name 1475 // then store the non-localized name. 1476 interface_name = __SCNetworkInterfaceGetNonLocalizedDisplayName(interface); 1477 if (interface_name != NULL) { 1478 CFRelease(saveName); 1479 saveName = CFRetain(interface_name); 1480 } 1481 } else if (CFStringHasPrefix(name, interface_name)) { 1482 CFIndex prefixLen = CFStringGetLength(interface_name); 1483 CFStringRef suffix; 1484 CFIndex suffixLen = CFStringGetLength(name); 1485 1486 // if service name matches the localized interface name plus 1487 // a few extra characters) then store the non-localized name with 1488 // the same suffix. 1489 suffix = CFStringCreateWithSubstring(NULL, 1490 name, 1491 CFRangeMake(prefixLen, suffixLen - prefixLen)); 1492 interface_name = __SCNetworkInterfaceGetNonLocalizedDisplayName(interface); 1493 if (interface_name != NULL) { 1494 CFRelease(saveName); 1495 saveName = CFStringCreateWithFormat(NULL, 1496 NULL, 1497 CFSTR("%@%@"), 1498 interface_name, 1499 suffix); 1500 } 1501 CFRelease(suffix); 1502 } 1503 } 1504 } 1505 } 1506 1507#define PREVENT_DUPLICATE_SERVICE_NAMES 1508#ifdef PREVENT_DUPLICATE_SERVICE_NAMES 1509 if (name != NULL) { 1510 CFArrayRef sets; 1511 1512 // ensure that each service is uniquely named within its sets 1513 1514 sets = SCNetworkSetCopyAll(servicePrivate->prefs); 1515 if (sets != NULL) { 1516 CFIndex set_index; 1517 CFIndex set_count; 1518 1519 set_count = CFArrayGetCount(sets); 1520 for (set_index = 0; set_index < set_count; set_index++) { 1521 CFIndex service_index; 1522 Boolean isDup = FALSE; 1523 Boolean isMember = FALSE; 1524 CFIndex service_count; 1525 CFArrayRef services; 1526 SCNetworkSetRef set = CFArrayGetValueAtIndex(sets, set_index); 1527 1528 services = SCNetworkSetCopyServices(set); 1529 1530 service_count = CFArrayGetCount(services); 1531 for (service_index = 0; service_index < service_count; service_index++) { 1532 CFStringRef otherID; 1533 CFStringRef otherName; 1534 SCNetworkServiceRef otherService; 1535 1536 otherService = CFArrayGetValueAtIndex(services, service_index); 1537 1538 otherID = SCNetworkServiceGetServiceID(otherService); 1539 if (CFEqual(servicePrivate->serviceID, otherID)) { 1540 // if the service is a member of this set 1541 isMember = TRUE; 1542 continue; 1543 } 1544 1545 otherName = SCNetworkServiceGetName(otherService); 1546 if ((otherName != NULL) && CFEqual(name, otherName)) { 1547 isDup = TRUE; 1548 continue; 1549 } 1550 } 1551 1552 CFRelease(services); 1553 1554 if (isMember && isDup) { 1555 /* 1556 * if this service is a member of the set and 1557 * the "name" is not unique. 1558 */ 1559 CFRelease(sets); 1560 if (saveName != NULL) CFRelease(saveName); 1561 _SCErrorSet(kSCStatusKeyExists); 1562 return FALSE; 1563 } 1564 } 1565 1566 CFRelease(sets); 1567 } 1568 } 1569#endif /* PREVENT_DUPLICATE_SERVICE_NAMES */ 1570 1571 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator 1572 servicePrivate->serviceID, // service 1573 NULL); // entity 1574 entity = SCPreferencesPathGetValue(servicePrivate->prefs, path); 1575 if (isA_CFDictionary(entity) || 1576 ((entity == NULL) && (name != NULL))) { 1577 CFMutableDictionaryRef newEntity; 1578 1579 if (entity != NULL) { 1580 newEntity = CFDictionaryCreateMutableCopy(NULL, 0, entity); 1581 } else { 1582 newEntity = CFDictionaryCreateMutable(NULL, 1583 0, 1584 &kCFTypeDictionaryKeyCallBacks, 1585 &kCFTypeDictionaryValueCallBacks); 1586 } 1587 if (saveName != NULL) { 1588 CFDictionarySetValue(newEntity, kSCPropUserDefinedName, saveName); 1589 } else { 1590 CFDictionaryRemoveValue(newEntity, kSCPropUserDefinedName); 1591 } 1592 ok = SCPreferencesPathSetValue(servicePrivate->prefs, path, newEntity); 1593 CFRelease(newEntity); 1594 } 1595 CFRelease(path); 1596 if (saveName != NULL) CFRelease(saveName); 1597 1598 if (servicePrivate->name != NULL) CFRelease(servicePrivate->name); 1599 if (name != NULL) CFRetain(name); 1600 servicePrivate->name = name; 1601 1602 if (ok) { 1603 SC_log(LOG_DEBUG, "SCNetworkServiceSetName(): %@", service); 1604 } 1605 1606 return ok; 1607} 1608 1609 1610#pragma mark - 1611#pragma mark SCNetworkService SPIs 1612 1613 1614__private_extern__ 1615Boolean 1616__SCNetworkServiceExists(SCNetworkServiceRef service) 1617{ 1618 CFDictionaryRef entity; 1619 CFStringRef path; 1620 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service; 1621 1622 if (servicePrivate->prefs == NULL) { 1623 // if no prefs 1624 return FALSE; 1625 } 1626 1627 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator 1628 servicePrivate->serviceID, // service 1629 kSCEntNetInterface); // entity 1630 entity = SCPreferencesPathGetValue(servicePrivate->prefs, path); 1631 CFRelease(path); 1632 1633 if (!isA_CFDictionary(entity)) { 1634 // a "service" must have an "interface" 1635 return FALSE; 1636 } 1637 1638 return TRUE; 1639} 1640 1641 1642SCNetworkServicePrimaryRank 1643SCNetworkServiceGetPrimaryRank(SCNetworkServiceRef service) 1644{ 1645 CFDictionaryRef entity; 1646 Boolean ok = TRUE; 1647 CFStringRef path; 1648 SCNetworkServicePrimaryRank rank = kSCNetworkServicePrimaryRankDefault; 1649 CFStringRef rankStr = NULL; 1650 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service; 1651 1652 if (!isA_SCNetworkService(service)) { 1653 _SCErrorSet(kSCStatusInvalidArgument); 1654 return rank; 1655 } 1656 1657 if (servicePrivate->prefs != NULL) { 1658 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, 1659 servicePrivate->serviceID, 1660 NULL); 1661 entity = SCPreferencesPathGetValue(servicePrivate->prefs, path); 1662 CFRelease(path); 1663 if (isA_CFDictionary(entity)) { 1664 rankStr = CFDictionaryGetValue(entity, kSCPropNetServicePrimaryRank); 1665 ok = __str_to_rank(rankStr, &rank); 1666 } 1667 } else if (servicePrivate->store != NULL) { 1668 path = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, 1669 kSCDynamicStoreDomainState, 1670 servicePrivate->serviceID, 1671 NULL); 1672 entity = SCDynamicStoreCopyValue(servicePrivate->store, path); 1673 CFRelease(path); 1674 if (entity != NULL) { 1675 if (isA_CFDictionary(entity)) { 1676 rankStr = CFDictionaryGetValue(entity, kSCPropNetServicePrimaryRank); 1677 ok = __str_to_rank(rankStr, &rank); 1678 } 1679 CFRelease(entity); 1680 } 1681 } else { 1682 _SCErrorSet(kSCStatusInvalidArgument); 1683 return rank; 1684 } 1685 1686 if (!ok) { 1687 rank = kSCNetworkServicePrimaryRankDefault; 1688 _SCErrorSet(kSCStatusInvalidArgument); 1689 } else if (rank == kSCNetworkServicePrimaryRankDefault) { 1690 _SCErrorSet(kSCStatusOK); 1691 } 1692 1693 return rank; 1694} 1695 1696 1697Boolean 1698SCNetworkServiceSetPrimaryRank(SCNetworkServiceRef service, 1699 SCNetworkServicePrimaryRank newRank) 1700{ 1701 Boolean ok; 1702 CFDictionaryRef entity; 1703 CFMutableDictionaryRef newEntity; 1704 CFStringRef path = NULL; 1705 CFStringRef rankStr = NULL; 1706 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service; 1707 1708 if (!isA_SCNetworkService(service)) { 1709 _SCErrorSet(kSCStatusInvalidArgument); 1710 return FALSE; 1711 } 1712 1713 if ((servicePrivate->prefs != NULL) && !__SCNetworkServiceExists(service)) { 1714 SC_log(LOG_ERR, "SCNetworkServiceSetPrimaryRank() w/removed\n service = %@", service); 1715 _SC_crash_once("SCNetworkServiceSetPrimaryRank() w/removed service", NULL, NULL); 1716 _SCErrorSet(kSCStatusInvalidArgument); 1717 return FALSE; 1718 } 1719 1720 ok = __rank_to_str(newRank, &rankStr); 1721 if (!ok) { 1722 _SCErrorSet(kSCStatusInvalidArgument); 1723 return FALSE; 1724 } 1725 1726 if (servicePrivate->prefs != NULL) { 1727 switch (newRank) { 1728 case kSCNetworkServicePrimaryRankDefault: 1729 case kSCNetworkServicePrimaryRankNever: 1730 case kSCNetworkServicePrimaryRankScoped: 1731 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, 1732 servicePrivate->serviceID, 1733 NULL); 1734 entity = SCPreferencesPathGetValue(servicePrivate->prefs, path); 1735 if (entity != NULL) { 1736 if (!isA_CFDictionary(entity)) { 1737 // if corrupt prefs 1738 _SCErrorSet(kSCStatusFailed); 1739 goto done; 1740 } 1741 newEntity = CFDictionaryCreateMutableCopy(NULL, 0, entity); 1742 } else { 1743 newEntity = CFDictionaryCreateMutable(NULL, 1744 0, 1745 &kCFTypeDictionaryKeyCallBacks, 1746 &kCFTypeDictionaryValueCallBacks); 1747 } 1748 if (rankStr != NULL) { 1749 CFDictionarySetValue(newEntity, kSCPropNetServicePrimaryRank, rankStr); 1750 } else { 1751 CFDictionaryRemoveValue(newEntity, kSCPropNetServicePrimaryRank); 1752 } 1753 if (CFDictionaryGetCount(newEntity) > 0) { 1754 ok = SCPreferencesPathSetValue(servicePrivate->prefs, path, newEntity); 1755 } else { 1756 ok = SCPreferencesPathRemoveValue(servicePrivate->prefs, path); 1757 } 1758 CFRelease(newEntity); 1759 if (!ok) { 1760 goto done; 1761 } 1762 break; 1763 default: 1764 _SCErrorSet(kSCStatusInvalidArgument); 1765 return FALSE; 1766 } 1767 } else if (servicePrivate->store != NULL) { 1768 path = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, 1769 kSCDynamicStoreDomainState, 1770 servicePrivate->serviceID, 1771 NULL); 1772 entity = SCDynamicStoreCopyValue(servicePrivate->store, path); 1773 if (entity != NULL) { 1774 if (!isA_CFDictionary(entity)) { 1775 // if corrupt prefs 1776 CFRelease(entity); 1777 _SCErrorSet(kSCStatusFailed); 1778 goto done; 1779 } 1780 newEntity = CFDictionaryCreateMutableCopy(NULL, 0, entity); 1781 CFRelease(entity); 1782 } else { 1783 newEntity = CFDictionaryCreateMutable(NULL, 1784 0, 1785 &kCFTypeDictionaryKeyCallBacks, 1786 &kCFTypeDictionaryValueCallBacks); 1787 } 1788 if (rankStr != NULL) { 1789 CFDictionarySetValue(newEntity, kSCPropNetServicePrimaryRank, rankStr); 1790 } else { 1791 CFDictionaryRemoveValue(newEntity, kSCPropNetServicePrimaryRank); 1792 } 1793 if (CFDictionaryGetCount(newEntity) > 0) { 1794 ok = SCDynamicStoreSetValue(servicePrivate->store, path, newEntity); 1795 } else { 1796 ok = SCDynamicStoreRemoveValue(servicePrivate->store, path); 1797 } 1798 CFRelease(newEntity); 1799 if (!ok) { 1800 goto done; 1801 } 1802 } else { 1803 _SCErrorSet(kSCStatusInvalidArgument); 1804 return FALSE; 1805 } 1806 1807 done : 1808 1809 if (path != NULL) CFRelease(path); 1810 return ok; 1811} 1812 1813 1814Boolean 1815_SCNetworkServiceIsVPN(SCNetworkServiceRef service) 1816{ 1817 SCNetworkInterfaceRef interface; 1818 CFStringRef interfaceType; 1819 1820 interface = SCNetworkServiceGetInterface(service); 1821 if (interface == NULL) { 1822 return FALSE; 1823 } 1824 1825 interfaceType = SCNetworkInterfaceGetInterfaceType(interface); 1826 if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) { 1827 interface = SCNetworkInterfaceGetInterface(interface); 1828 if (interface == NULL) { 1829 return FALSE; 1830 } 1831 1832 interfaceType = SCNetworkInterfaceGetInterfaceType(interface); 1833 if (CFEqual(interfaceType, kSCNetworkInterfaceTypeL2TP)) { 1834 return TRUE; 1835 } 1836#pragma GCC diagnostic push 1837#pragma GCC diagnostic ignored "-Wdeprecated" 1838 if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPTP)) { 1839 return TRUE; 1840 } 1841#pragma GCC diagnostic pop 1842 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeVPN)) { 1843 return TRUE; 1844 } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeIPSec)) { 1845 return TRUE; 1846 } 1847 1848 return FALSE; 1849} 1850 1851 1852Boolean 1853SCNetworkServiceSetExternalID(SCNetworkServiceRef service, CFStringRef identifierDomain, CFStringRef identifier) 1854{ 1855 CFStringRef prefs_path; 1856 CFDictionaryRef service_dictionary; 1857 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service; 1858 Boolean success = FALSE; 1859 CFStringRef prefixed_domain; 1860 1861 if (!isA_SCNetworkService(service) || (servicePrivate->prefs == NULL) || !isA_CFString(identifierDomain)) { 1862 _SCErrorSet(kSCStatusInvalidArgument); 1863 return FALSE; 1864 } 1865 1866 if (!__SCNetworkServiceExists(service)) { 1867 SC_log(LOG_ERR, "SCNetworkServiceSetExternalID() w/removed\n service = %@\n id = %@", 1868 service, 1869 identifier); 1870 _SC_crash_once("SCNetworkServiceSetExternalID() w/removed service", NULL, NULL); 1871 _SCErrorSet(kSCStatusInvalidArgument); 1872 return FALSE; 1873 } 1874 1875 if (identifier != NULL && !isA_CFString(identifier)) { 1876 _SCErrorSet(kSCStatusInvalidArgument); 1877 return FALSE; 1878 } 1879 1880 prefixed_domain = CFStringCreateWithFormat(NULL, 0, CFSTR("%s%@"), EXTERNAL_ID_DOMAIN_PREFIX, identifierDomain); 1881 1882 prefs_path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, 1883 servicePrivate->serviceID, 1884 NULL); 1885 1886 service_dictionary = SCPreferencesPathGetValue(servicePrivate->prefs, prefs_path); 1887 if (isA_CFDictionary(service_dictionary) || ((service_dictionary == NULL) && (identifier != NULL))) { 1888 CFMutableDictionaryRef new_service_dictionary; 1889 1890 if (service_dictionary != NULL) { 1891 new_service_dictionary = CFDictionaryCreateMutableCopy(NULL, 0, service_dictionary); 1892 } else { 1893 new_service_dictionary = CFDictionaryCreateMutable(NULL, 1894 0, 1895 &kCFTypeDictionaryKeyCallBacks, 1896 &kCFTypeDictionaryValueCallBacks); 1897 } 1898 1899 if (identifier != NULL) { 1900 CFDictionarySetValue(new_service_dictionary, prefixed_domain, identifier); 1901 } else { 1902 CFDictionaryRemoveValue(new_service_dictionary, prefixed_domain); 1903 } 1904 success = SCPreferencesPathSetValue(servicePrivate->prefs, prefs_path, new_service_dictionary); 1905 CFRelease(new_service_dictionary); 1906 } 1907 CFRelease(prefs_path); 1908 1909 if (identifier != NULL) { 1910 if (servicePrivate->externalIDs == NULL) { 1911 servicePrivate->externalIDs = CFDictionaryCreateMutable(NULL, 1912 0, 1913 &kCFTypeDictionaryKeyCallBacks, 1914 &kCFTypeDictionaryValueCallBacks); 1915 } 1916 CFDictionarySetValue(servicePrivate->externalIDs, prefixed_domain, identifier); 1917 } else { 1918 if (servicePrivate->externalIDs != NULL) { 1919 CFDictionaryRemoveValue(servicePrivate->externalIDs, prefixed_domain); 1920 } 1921 } 1922 1923 CFRelease(prefixed_domain); 1924 1925 if (!success) { 1926 _SCErrorSet(kSCStatusFailed); 1927 } 1928 1929 return success; 1930} 1931 1932 1933CFStringRef 1934SCNetworkServiceCopyExternalID(SCNetworkServiceRef service, CFStringRef identifierDomain) 1935{ 1936 CFStringRef identifier = NULL; 1937 CFStringRef prefixed_domain; 1938 SCNetworkServicePrivateRef service_private = (SCNetworkServicePrivateRef)service; 1939 1940 if (!isA_SCNetworkService(service) || (service_private->prefs == NULL) || !isA_CFString(identifierDomain)) { 1941 _SCErrorSet(kSCStatusInvalidArgument); 1942 return NULL; 1943 } 1944 1945 prefixed_domain = CFStringCreateWithFormat(NULL, 0, CFSTR("%s%@"), EXTERNAL_ID_DOMAIN_PREFIX, identifierDomain); 1946 1947 if (service_private->externalIDs != NULL) { 1948 identifier = CFDictionaryGetValue(service_private->externalIDs, prefixed_domain); 1949 if (identifier != NULL) { 1950 CFRetain(identifier); 1951 } 1952 } 1953 1954 if (identifier == NULL) { 1955 CFStringRef prefs_path; 1956 CFDictionaryRef service_dictionary; 1957 1958 prefs_path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, 1959 service_private->serviceID, 1960 NULL); 1961 1962 service_dictionary = SCPreferencesPathGetValue(service_private->prefs, prefs_path); 1963 if (isA_CFDictionary(service_dictionary)) { 1964 identifier = CFDictionaryGetValue(service_dictionary, prefixed_domain); 1965 if (identifier != NULL) { 1966 CFRetain(identifier); 1967 if (service_private->externalIDs == NULL) { 1968 service_private->externalIDs = CFDictionaryCreateMutable(NULL, 1969 0, 1970 &kCFTypeDictionaryKeyCallBacks, 1971 &kCFTypeDictionaryValueCallBacks); 1972 } 1973 CFDictionarySetValue(service_private->externalIDs, prefixed_domain, identifier); 1974 } 1975 } 1976 CFRelease(prefs_path); 1977 } 1978 1979 CFRelease(prefixed_domain); 1980 1981 if (identifier == NULL) { 1982 _SCErrorSet(kSCStatusNoKey); 1983 } 1984 1985 return identifier; 1986} 1987 1988 1989typedef struct { 1990 CFStringRef oldServiceID; 1991 CFStringRef newServiceID; 1992} serviceContext, *serviceContextRef; 1993 1994 1995static void 1996replaceServiceID(const void *value, void *context) 1997{ 1998 CFStringRef link = NULL; 1999 CFStringRef oldLink; 2000 CFMutableArrayRef newServiceOrder; 2001 CFStringRef path; 2002 serviceContextRef service_context = (serviceContextRef)context; 2003 CFArrayRef serviceOrder = NULL; 2004 SCNetworkSetRef set = (SCNetworkSetRef)value; 2005 SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set; 2006 2007 // update service order 2008 serviceOrder = SCNetworkSetGetServiceOrder(set); 2009 if ((isA_CFArray(serviceOrder) != NULL) && 2010 CFArrayContainsValue(serviceOrder, 2011 CFRangeMake(0, CFArrayGetCount(serviceOrder)), 2012 service_context->oldServiceID)) { 2013 CFIndex count; 2014 CFIndex serviceOrderIndex; 2015 2016 // replacing all instances of old service ID with new one 2017 newServiceOrder = CFArrayCreateMutableCopy(NULL, 0, serviceOrder); 2018 count = CFArrayGetCount(newServiceOrder); 2019 for (serviceOrderIndex = 0; serviceOrderIndex < count; serviceOrderIndex++) { 2020 CFStringRef serviceID; 2021 2022 serviceID = CFArrayGetValueAtIndex(newServiceOrder, serviceOrderIndex); 2023 if (CFEqual(serviceID, service_context->oldServiceID)) { 2024 CFArraySetValueAtIndex(newServiceOrder, serviceOrderIndex, service_context->newServiceID); 2025 } 2026 } 2027 SCNetworkSetSetServiceOrder(set, newServiceOrder); 2028 CFRelease(newServiceOrder); 2029 } 2030 2031 // check if service with old serviceID is part of the set 2032 path = SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL, // allocator 2033 setPrivate->setID, // set 2034 service_context->oldServiceID, // service 2035 NULL); // entity 2036 oldLink = SCPreferencesPathGetLink(setPrivate->prefs, path); 2037 if (oldLink == NULL) { 2038 // don't make any changes if service with old serviceID is not found 2039 goto done; 2040 } 2041 2042 // remove link between "set" and old "service" 2043 (void) SCPreferencesPathRemoveValue(setPrivate->prefs, path); 2044 CFRelease(path); 2045 2046 // create the link between "set" and the "service" 2047 path = SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL, // allocator 2048 setPrivate->setID, // set 2049 service_context->newServiceID, // service 2050 NULL); // entity 2051 link = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator 2052 service_context->newServiceID, // service 2053 NULL); // entity 2054 (void) SCPreferencesPathSetLink(setPrivate->prefs, path, link); 2055 2056 done: 2057 2058 if (path != NULL) { 2059 CFRelease(path); 2060 } 2061 if (link != NULL) { 2062 CFRelease(link); 2063 } 2064 2065 return; 2066} 2067 2068 2069Boolean 2070_SCNetworkServiceSetServiceID(SCNetworkServiceRef service, CFStringRef newServiceID) 2071{ 2072 CFArrayRef allSets = NULL; 2073 CFDictionaryRef entity; 2074 CFStringRef newPath; 2075 Boolean ok = FALSE; 2076 CFStringRef oldPath = NULL; 2077 serviceContext service_context; 2078 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service; 2079 2080 if (!isA_SCNetworkService(service) || (servicePrivate->prefs == NULL)) { 2081 _SCErrorSet(kSCStatusInvalidArgument); 2082 return FALSE; 2083 } 2084 2085 if (!isA_CFString(newServiceID)) { 2086 _SCErrorSet(kSCStatusInvalidArgument); 2087 return FALSE; 2088 } 2089 2090 if (CFEqual(newServiceID, servicePrivate->serviceID)) { 2091 // no work needs to be done if new service ID is equal to current service ID 2092 return TRUE; 2093 } 2094 2095 if (!__SCNetworkServiceExists(service)) { 2096 SC_log(LOG_ERR, "_SCNetworkServiceSetServiceID() w/removed service\n service = %@\n serviceID = %@", 2097 service, 2098 newServiceID); 2099 _SC_crash_once("_SCNetworkServiceSetServiceID() w/removed service", NULL, NULL); 2100 _SCErrorSet(kSCStatusInvalidArgument); 2101 return FALSE; 2102 } 2103 2104 newPath = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator 2105 newServiceID, // service 2106 NULL); // entity 2107 entity = SCPreferencesPathGetValue(servicePrivate->prefs, newPath); 2108 if (isA_CFDictionary(entity)) { 2109 // if the new service already exists 2110 _SCErrorSet(kSCStatusKeyExists); 2111 goto done; 2112 } 2113 2114 oldPath = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator 2115 servicePrivate->serviceID, // service 2116 NULL); // entity 2117 entity = SCPreferencesPathGetValue(servicePrivate->prefs, oldPath); 2118 if (!isA_CFDictionary(entity)) { 2119 // if the service has already been removed 2120 _SCErrorSet(kSCStatusNoKey); 2121 goto done; 2122 } 2123 2124 ok = SCPreferencesPathSetValue(servicePrivate->prefs, newPath, entity); 2125 if (!ok) goto done; 2126 2127 ok = SCPreferencesPathRemoveValue(servicePrivate->prefs, oldPath); 2128 if (!ok) goto done; 2129 2130 allSets = SCNetworkSetCopyAll(servicePrivate->prefs); 2131 2132 service_context.newServiceID = newServiceID; 2133 service_context.oldServiceID = servicePrivate->serviceID; 2134 2135 // find all sets w/oldServiceID and update 2136 // ... and update the serviceOrder 2137 CFArrayApplyFunction(allSets, 2138 CFRangeMake(0, CFArrayGetCount(allSets)), 2139 replaceServiceID, 2140 &service_context); 2141 2142 if (servicePrivate->interface != NULL) { 2143 SCNetworkInterfaceRef newInterface; 2144 2145 // duplicate the interface and associate the copy with the new service ID 2146 newInterface = (SCNetworkInterfaceRef)__SCNetworkInterfaceCreateCopy(NULL, 2147 servicePrivate->interface, 2148 servicePrivate->prefs, 2149 newServiceID); 2150 CFRelease(servicePrivate->interface); 2151 servicePrivate->interface = newInterface; 2152 } 2153 2154 SC_log(LOG_DEBUG, "_SCNetworkServiceSetServiceID(): %@ --> %@", service, newServiceID); 2155 2156 // replace serviceID with new one 2157 CFRetain(newServiceID); 2158 CFRelease(servicePrivate->serviceID); 2159 servicePrivate->serviceID = newServiceID; 2160 2161 done: 2162 2163 if (oldPath != NULL) { 2164 CFRelease(oldPath); 2165 } 2166 if (newPath != NULL) { 2167 CFRelease(newPath); 2168 } 2169 if (allSets != NULL) { 2170 CFRelease(allSets); 2171 } 2172 2173 return ok; 2174} 2175 2176#define kVPNProtocolPayloadInfo CFSTR("com.apple.payload") 2177#define kSCEntNetLoginWindowEAPOL CFSTR("EAPOL.LoginWindow") 2178 2179static void 2180copyInterfaceConfiguration(SCNetworkServiceRef oldService, SCNetworkServiceRef newService) 2181{ 2182 SCNetworkInterfaceRef oldInterface; 2183 SCNetworkInterfaceRef newInterface; 2184 2185 oldInterface = SCNetworkServiceGetInterface(oldService); 2186 newInterface = SCNetworkServiceGetInterface(newService); 2187 2188 while (oldInterface != NULL) { 2189 CFDictionaryRef configuration; 2190 CFStringRef interfaceType; 2191 2192 if (newInterface == NULL) { 2193 // oops ... interface layering does not match 2194 return; 2195 } 2196 2197 // copy interface configuration 2198 configuration = SCNetworkInterfaceGetConfiguration(oldInterface); 2199 2200 if ((configuration != NULL) || 2201 (SCError() == kSCStatusOK)) { 2202 if (!SCNetworkInterfaceSetConfiguration(newInterface, configuration)) { 2203 SC_log(LOG_INFO, "problem setting interface configuration"); 2204 } 2205 2206 } 2207 2208 // special case: PPP/L2TP + IPSec 2209 interfaceType = SCNetworkInterfaceGetInterfaceType(oldInterface); 2210 if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) { 2211 SCNetworkInterfaceRef childInterface; 2212 2213 childInterface = SCNetworkInterfaceGetInterface(oldInterface); 2214 if (childInterface != NULL) { 2215 CFStringRef childInterfaceType; 2216 2217 childInterfaceType = SCNetworkInterfaceGetInterfaceType(childInterface); 2218 2219 if (CFEqual(childInterfaceType, kSCNetworkInterfaceTypeL2TP)) { 2220 configuration = SCNetworkInterfaceGetExtendedConfiguration(oldInterface, kSCEntNetIPSec); 2221 if ((configuration != NULL) || 2222 (SCError() == kSCStatusOK)) { 2223 if (!SCNetworkInterfaceSetExtendedConfiguration(newInterface, kSCEntNetIPSec, configuration)) { 2224 SC_log(LOG_INFO, "problem setting child interface configuration"); 2225 } 2226 } 2227 } 2228 } 2229 } 2230 2231 // special case: 802.1x 2232 configuration = SCNetworkInterfaceGetExtendedConfiguration(oldInterface, kSCEntNetEAPOL); 2233 if ((configuration != NULL) || 2234 (SCError() == kSCStatusOK)) { 2235 (void) SCNetworkInterfaceSetExtendedConfiguration(newInterface, kSCEntNetEAPOL, configuration); 2236 } 2237 2238 // special case: Managed Client 2239 configuration = SCNetworkInterfaceGetExtendedConfiguration(oldInterface, kVPNProtocolPayloadInfo); 2240 if ((configuration != NULL) || 2241 (SCError() == kSCStatusOK)) { 2242 (void) SCNetworkInterfaceSetExtendedConfiguration(newInterface, kVPNProtocolPayloadInfo, configuration); 2243 } 2244 2245 // special case: Network Pref 2246 configuration = SCNetworkInterfaceGetExtendedConfiguration(oldInterface, kSCValNetPPPAuthProtocolEAP); 2247 if ((configuration != NULL) || 2248 (SCError() == kSCStatusOK)) { 2249 (void) SCNetworkInterfaceSetExtendedConfiguration(newInterface, kSCValNetPPPAuthProtocolEAP, configuration); 2250 } 2251 2252 // special case: Remote Pref 2253 configuration = SCNetworkInterfaceGetExtendedConfiguration(oldInterface, kSCEntNetLoginWindowEAPOL); 2254 if ((configuration != NULL) || 2255 (SCError() == kSCStatusOK)) { 2256 (void) SCNetworkInterfaceSetExtendedConfiguration(newInterface, kSCEntNetLoginWindowEAPOL, configuration); 2257 } 2258 2259 // special case: Network Extension 2260 configuration = SCNetworkInterfaceGetExtendedConfiguration(oldInterface, kSCNetworkInterfaceTypeIPSec); 2261 if ((configuration != NULL) || 2262 (SCError() == kSCStatusOK)) { 2263 (void) SCNetworkInterfaceSetExtendedConfiguration(newInterface, kSCNetworkInterfaceTypeIPSec, configuration); 2264 } 2265 2266 oldInterface = SCNetworkInterfaceGetInterface(oldInterface); 2267 newInterface = SCNetworkInterfaceGetInterface(newInterface); 2268 } 2269 2270 return; 2271} 2272 2273__private_extern__ 2274void 2275__SCNetworkServiceAddProtocolToService(SCNetworkServiceRef service, CFStringRef protocolType, CFDictionaryRef configuration, Boolean enabled) 2276{ 2277 Boolean ok; 2278 SCNetworkProtocolRef protocol; 2279 2280 protocol = SCNetworkServiceCopyProtocol(service, protocolType); 2281 2282 if ((protocol == NULL) && 2283 (SCError() == kSCStatusNoKey)) { 2284 ok = SCNetworkServiceAddProtocolType(service, protocolType); 2285 if (ok) { 2286 protocol = SCNetworkServiceCopyProtocol(service, protocolType); 2287 } 2288 } 2289 if (protocol != NULL) { 2290 SCNetworkProtocolSetConfiguration(protocol, configuration); 2291 SCNetworkProtocolSetEnabled(protocol, enabled); 2292 CFRelease(protocol); 2293 } 2294 return; 2295} 2296 2297 2298 2299__private_extern__ 2300Boolean 2301__SCNetworkServiceMigrateNew(SCPreferencesRef prefs, 2302 SCNetworkServiceRef service, 2303 CFDictionaryRef bsdMapping, 2304 CFDictionaryRef setMapping, 2305 CFDictionaryRef serviceSetMapping) 2306{ 2307 CFStringRef deviceName = NULL; 2308 Boolean enabled; 2309 SCNetworkInterfaceRef interface = NULL; 2310 CFDictionaryRef interfaceEntity = NULL; 2311 CFMutableDictionaryRef interfaceEntityMutable = NULL; 2312 SCNetworkSetRef newSet = NULL; 2313 SCPreferencesRef ni_prefs = NULL; 2314 SCNetworkInterfaceRef ni_interface = NULL; 2315 SCNetworkInterfaceRef oldInterface = NULL; 2316 SCNetworkSetRef oldSet = NULL; 2317 SCNetworkServiceRef newService = NULL; 2318 CFStringRef serviceID = NULL; 2319 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef) service; 2320 CFArrayRef setList = NULL; 2321 Boolean success = FALSE; 2322 CFStringRef targetDeviceName = NULL; 2323 CFStringRef userDefinedName = NULL; 2324 CFStringRef userDefinedNameInterface = NULL; 2325 CFArrayRef protocols = NULL; 2326 CFStringRef subType; 2327 2328 if ((isA_SCNetworkService(service) == NULL) || 2329 (isA_SCNetworkInterface(servicePrivate->interface) == NULL) || 2330 (servicePrivate->prefs == NULL)) { 2331 goto done; 2332 } 2333 serviceID = servicePrivate->serviceID; 2334 2335 newService = SCNetworkServiceCopy(prefs, serviceID); 2336 if (newService != NULL) { 2337 // Cannot add service if it already exists 2338 SC_log(LOG_INFO, "Service already exists"); 2339 goto done; 2340 } 2341 2342 oldInterface = SCNetworkServiceGetInterface(service); 2343 interfaceEntity = __SCNetworkInterfaceCopyInterfaceEntity(oldInterface); 2344 if (interfaceEntity == NULL) { 2345 SC_log(LOG_INFO, "No interface entity"); 2346 goto done; 2347 } 2348 interfaceEntityMutable = CFDictionaryCreateMutableCopy(NULL, 0, interfaceEntity); 2349 2350 if (isA_CFDictionary(bsdMapping) != NULL) { 2351 deviceName = CFDictionaryGetValue(interfaceEntityMutable, kSCPropNetInterfaceDeviceName); 2352 if (isA_CFString(deviceName) != NULL) { 2353 targetDeviceName = CFDictionaryGetValue(bsdMapping, deviceName); 2354 if (targetDeviceName != NULL) { 2355 // update mapping 2356 CFDictionarySetValue(interfaceEntityMutable, kSCPropNetInterfaceDeviceName, targetDeviceName); 2357 ni_prefs = __SCPreferencesCreateNIPrefsFromPrefs(prefs); 2358 ni_interface = __SCNetworkInterfaceCreateWithNIPreferencesUsingBSDName(NULL, ni_prefs, targetDeviceName); 2359 if (ni_interface != NULL) { 2360 userDefinedNameInterface = __SCNetworkInterfaceGetUserDefinedName(ni_interface); 2361 } 2362 } 2363 } 2364 if (userDefinedNameInterface == NULL) { 2365 userDefinedNameInterface = CFDictionaryGetValue(interfaceEntityMutable, kSCPropUserDefinedName); 2366 } 2367 } 2368 subType = CFDictionaryGetValue(interfaceEntityMutable, kSCPropNetInterfaceSubType); 2369 interface = _SCNetworkInterfaceCreateWithEntity(NULL, interfaceEntityMutable, NULL); 2370 if (userDefinedNameInterface != NULL) { 2371 __SCNetworkInterfaceSetUserDefinedName(interface, userDefinedNameInterface); 2372 } 2373 // Supporting PPPoE subtype 2374 if (subType != NULL && 2375 CFEqual(subType, kSCValNetInterfaceSubTypePPPoE)) { 2376 SCNetworkInterfaceRef childInterface = SCNetworkInterfaceGetInterface(interface); 2377 if (childInterface != NULL) { 2378 __SCNetworkInterfaceSetUserDefinedName(childInterface, userDefinedNameInterface); 2379 } 2380 } 2381 newService = SCNetworkServiceCreate(prefs, interface); 2382 if (newService == NULL) { 2383 SC_log(LOG_INFO, "SCNetworkServiceCreate() failed"); 2384 goto done; 2385 } 2386 2387 enabled = SCNetworkServiceGetEnabled(service); 2388 if (!SCNetworkServiceSetEnabled(newService, enabled)) { 2389 SCNetworkServiceRemove(newService); 2390 SC_log(LOG_INFO, "SCNetworkServiceSetEnabled() failed"); 2391 goto done; 2392 } 2393 2394 if (!SCNetworkServiceEstablishDefaultConfiguration(newService)) { 2395 SCNetworkServiceRemove(newService); 2396 SC_log(LOG_INFO, "SCNetworkServiceEstablishDefaultConfiguration() failed"); 2397 goto done; 2398 } 2399 2400 // Set service ID 2401 _SCNetworkServiceSetServiceID(newService, serviceID); 2402 2403 userDefinedName = SCNetworkServiceGetName(service); 2404 if ((userDefinedName != NULL) && 2405 !SCNetworkServiceSetName(newService, userDefinedName)) { 2406 SC_log(LOG_INFO, "SCNetworkServiceSetName(, %@) failed", userDefinedName); 2407 } 2408 2409 // Determine which sets to add service 2410 if (setMapping != NULL && 2411 serviceSetMapping != NULL) { 2412 setList = CFDictionaryGetValue(serviceSetMapping, service); 2413 if (setList != NULL) { 2414 for (CFIndex idx = 0; idx < CFArrayGetCount(setList); idx++) { 2415 oldSet = CFArrayGetValueAtIndex(setList, idx); 2416 newSet = CFDictionaryGetValue(setMapping, oldSet); 2417 if (newSet == NULL) { 2418 continue; 2419 } 2420 2421 if (!SCNetworkSetAddService(newSet, newService)) { 2422 SC_log(LOG_INFO, "SCNetworkSetAddService() failed"); 2423 } 2424 } 2425 } 2426 } 2427 2428 protocols = SCNetworkServiceCopyProtocols(service); 2429 if (protocols != NULL) { 2430 2431 for (CFIndex idx = 0; idx < CFArrayGetCount(protocols); idx++) { 2432 SCNetworkProtocolRef protocol = CFArrayGetValueAtIndex(protocols, idx); 2433 CFDictionaryRef configuration = SCNetworkProtocolGetConfiguration(protocol); 2434 CFStringRef protocolType = SCNetworkProtocolGetProtocolType(protocol); 2435 enabled = SCNetworkProtocolGetEnabled(protocol); 2436 __SCNetworkServiceAddProtocolToService(newService, protocolType, configuration, enabled); 2437 } 2438 CFRelease(protocols); 2439 } 2440 2441 copyInterfaceConfiguration(service, newService); 2442 2443 success = TRUE; 2444done: 2445 if (interface != NULL) { 2446 CFRelease(interface); 2447 } 2448 if (interfaceEntity != NULL) { 2449 CFRelease(interfaceEntity); 2450 } 2451 if (interfaceEntityMutable != NULL) { 2452 CFRelease(interfaceEntityMutable); 2453 } 2454 if (newService != NULL) { 2455 CFRelease(newService); 2456 } 2457 if (ni_prefs != NULL) { 2458 CFRelease(ni_prefs); 2459 } 2460 if (ni_interface != NULL) { 2461 CFRelease(ni_interface); 2462 } 2463 return success; 2464} 2465 2466 2467__private_extern__ 2468Boolean 2469__SCNetworkServiceCreate(SCPreferencesRef prefs, 2470 SCNetworkInterfaceRef interface, 2471 CFStringRef userDefinedName) 2472{ 2473 SCNetworkSetRef currentSet = NULL; 2474 Boolean ok = FALSE; 2475 SCNetworkServiceRef service = NULL; 2476 2477 if (interface == NULL) { 2478 goto done; 2479 } 2480 2481 if (userDefinedName == NULL) { 2482 userDefinedName = __SCNetworkInterfaceGetUserDefinedName(interface); 2483 if (userDefinedName == NULL) { 2484 SC_log(LOG_INFO, "No userDefinedName"); 2485 goto done; 2486 } 2487 } 2488 service = SCNetworkServiceCreate(prefs, interface); 2489 if (service == NULL) { 2490 SC_log(LOG_INFO, "SCNetworkServiceCreate() failed: %s", SCErrorString(SCError())); 2491 } else { 2492 ok = SCNetworkServiceSetName(service, userDefinedName); 2493 if (!ok) { 2494 SC_log(LOG_INFO, "SCNetworkServiceSetName() failed: %s", SCErrorString(SCError())); 2495 SCNetworkServiceRemove(service); 2496 goto done; 2497 } 2498 2499 ok = SCNetworkServiceEstablishDefaultConfiguration(service); 2500 if (!ok) { 2501 SC_log(LOG_INFO, "SCNetworkServiceEstablishDefaultConfiguration() failed: %s", SCErrorString(SCError())); 2502 SCNetworkServiceRemove(service); 2503 goto done; 2504 } 2505 } 2506 currentSet = SCNetworkSetCopyCurrent(prefs); 2507 if (currentSet == NULL) { 2508 SC_log(LOG_INFO, "No current set"); 2509 if (service != NULL) { 2510 SCNetworkServiceRemove(service); 2511 } 2512 goto done; 2513 } 2514 if (service != NULL) { 2515 ok = SCNetworkSetAddService(currentSet, service); 2516 if (!ok) { 2517 SC_log(LOG_INFO, "Could not add service to the current set"); 2518 SCNetworkServiceRemove(service); 2519 goto done; 2520 } 2521 } 2522 2523 done: 2524 if (service != NULL) { 2525 CFRelease(service); 2526 } 2527 if (currentSet != NULL) { 2528 CFRelease(currentSet); 2529 } 2530 return ok; 2531} 2532 2533__private_extern__ Boolean 2534__SCNetworkServiceIsPPTP(SCNetworkServiceRef service) 2535{ 2536 CFStringRef intfSubtype; 2537 SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service; 2538 2539 if (servicePrivate == NULL || servicePrivate->interface == NULL) { 2540 return FALSE; 2541 } 2542 2543 intfSubtype = __SCNetworkInterfaceGetEntitySubType(servicePrivate->interface); 2544 if (intfSubtype == NULL) { 2545 return FALSE; 2546 } 2547 2548#pragma GCC diagnostic push 2549#pragma GCC diagnostic ignored "-Wdeprecated" 2550 if (CFEqual(intfSubtype, kSCValNetInterfaceSubTypePPTP)) { 2551 return TRUE; 2552 } 2553#pragma GCC diagnostic pop 2554 2555 return FALSE; 2556}