this repo has no description
at fixPythonPipStalling 715 lines 19 kB view raw
1/* 2 * Copyright (c) 2000-2004, 2006-2013, 2015, 2016 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 18, 2001 Allan Nathanson <ajn@apple.com> 28 * - initial revision 29 */ 30 31#include <TargetConditionals.h> 32#include <SystemConfiguration/SystemConfiguration.h> 33#include <SystemConfiguration/SCValidation.h> 34#include <SystemConfiguration/SCPrivate.h> 35#include <SystemConfiguration/VPNAppLayerPrivate.h> 36 37#include <netdb.h> 38#if !TARGET_OS_SIMULATOR 39#include <ne_session.h> 40#endif // !TARGET_OS_SIMULATOR 41 42CFStringRef 43SCDynamicStoreKeyCreateProxies(CFAllocatorRef allocator) 44{ 45 return SCDynamicStoreKeyCreateNetworkGlobalEntity(allocator, 46 kSCDynamicStoreDomainState, 47 kSCEntNetProxies); 48} 49 50 51static void 52validate_proxy_content(CFMutableDictionaryRef proxies, 53 CFStringRef proxy_enable, 54 CFStringRef proxy_host, 55 CFStringRef proxy_port, 56 const char * proxy_service, 57 int proxy_defaultport) 58{ 59 int enabled = 0; 60 CFNumberRef num; 61 62 num = CFDictionaryGetValue(proxies, proxy_enable); 63 if (num != NULL) { 64 if (!isA_CFNumber(num) || 65 !CFNumberGetValue(num, kCFNumberIntType, &enabled)) { 66 goto disable; // if we don't like the enabled key/value 67 } 68 } 69 70 if (proxy_host != NULL) { 71 CFStringRef host; 72 73 host = CFDictionaryGetValue(proxies, proxy_host); 74 if ((enabled == 0) && (host != NULL)) { 75 goto disable; // if not enabled, remove provided key/value 76 } 77 78 if ((enabled != 0) && 79 (!isA_CFString(host) || (CFStringGetLength(host) == 0))) { 80 goto disable; // if enabled, not provided (or not valid) 81 } 82 } 83 84 if (proxy_port != NULL) { 85 CFNumberRef port; 86 int s_port = 0; 87 88 port = CFDictionaryGetValue(proxies, proxy_port); 89 if ((enabled == 0) && (port != NULL)) { 90 goto disable; // if not enabled, remove provided key/value 91 } 92 93 if ((enabled != 0) && (port != NULL)) { 94 if (!isA_CFNumber(port) || 95 !CFNumberGetValue(port, kCFNumberIntType, &s_port) || 96 (s_port > UINT16_MAX)) { 97 goto disable; // if enabled, not provided (or not valid) 98 } 99 100 if (s_port == 0) { 101 port = NULL; // if no port # provided, use default 102 } 103 } 104 105 if ((enabled != 0) && (port == NULL)) { 106 struct servent *service; 107 108 service = getservbyname(proxy_service, "tcp"); 109 if (service != NULL) { 110 s_port = ntohs(service->s_port); 111 } else { 112 s_port = proxy_defaultport; 113 } 114 num = CFNumberCreate(NULL, kCFNumberIntType, &s_port); 115 CFDictionarySetValue(proxies, proxy_port, num); 116 CFRelease(num); 117 } 118 } 119 120 return; 121 122 disable : 123 124 enabled = 0; 125 num = CFNumberCreate(NULL, kCFNumberIntType, &enabled); 126 CFDictionarySetValue(proxies, proxy_enable, num); 127 CFRelease(num); 128 if (proxy_host != NULL) { 129 CFDictionaryRemoveValue(proxies, proxy_host); 130 } 131 if (proxy_port != NULL) { 132 CFDictionaryRemoveValue(proxies, proxy_port); 133 } 134 135 return; 136} 137 138 139static void 140normalize_scoped_proxy(const void *key, const void *value, void *context); 141 142 143static void 144normalize_services_proxy(const void *key, const void *value, void *context); 145 146 147static void 148normalize_supplemental_proxy(const void *value, void *context); 149 150 151static CF_RETURNS_RETAINED CFDictionaryRef 152__SCNetworkProxiesCopyNormalized(CFDictionaryRef proxy) 153{ 154 CFArrayRef array; 155 CFMutableDictionaryRef newProxy; 156 CFNumberRef num; 157 CFDictionaryRef scoped; 158 CFDictionaryRef services; 159 CFArrayRef supplemental; 160 161 if (!isA_CFDictionary(proxy)) { 162 proxy = CFDictionaryCreate(NULL, 163 NULL, 164 NULL, 165 0, 166 &kCFTypeDictionaryKeyCallBacks, 167 &kCFTypeDictionaryValueCallBacks); 168 return proxy; 169 } 170 171 newProxy = CFDictionaryCreateMutableCopy(NULL, 0, proxy); 172 173 validate_proxy_content(newProxy, 174 kSCPropNetProxiesFTPEnable, 175 kSCPropNetProxiesFTPProxy, 176 kSCPropNetProxiesFTPPort, 177 "ftp", 178 21); 179 validate_proxy_content(newProxy, 180 kSCPropNetProxiesGopherEnable, 181 kSCPropNetProxiesGopherProxy, 182 kSCPropNetProxiesGopherPort, 183 "gopher", 184 70); 185 validate_proxy_content(newProxy, 186 kSCPropNetProxiesHTTPEnable, 187 kSCPropNetProxiesHTTPProxy, 188 kSCPropNetProxiesHTTPPort, 189 "http", 190 80); 191 validate_proxy_content(newProxy, 192 kSCPropNetProxiesHTTPSEnable, 193 kSCPropNetProxiesHTTPSProxy, 194 kSCPropNetProxiesHTTPSPort, 195 "https", 196 443); 197 validate_proxy_content(newProxy, 198 kSCPropNetProxiesRTSPEnable, 199 kSCPropNetProxiesRTSPProxy, 200 kSCPropNetProxiesRTSPPort, 201 "rtsp", 202 554); 203 validate_proxy_content(newProxy, 204 kSCPropNetProxiesSOCKSEnable, 205 kSCPropNetProxiesSOCKSProxy, 206 kSCPropNetProxiesSOCKSPort, 207 "socks", 208 1080); 209 if (CFDictionaryContainsKey(newProxy, kSCPropNetProxiesProxyAutoConfigURLString)) { 210 validate_proxy_content(newProxy, 211 kSCPropNetProxiesProxyAutoConfigEnable, 212 kSCPropNetProxiesProxyAutoConfigURLString, 213 NULL, 214 NULL, 215 0); 216 217 // and we can't have both URLString and JavaScript keys 218 CFDictionaryRemoveValue(newProxy, kSCPropNetProxiesProxyAutoConfigJavaScript); 219 } else { 220 validate_proxy_content(newProxy, 221 kSCPropNetProxiesProxyAutoConfigEnable, 222 kSCPropNetProxiesProxyAutoConfigJavaScript, 223 NULL, 224 NULL, 225 0); 226 } 227 validate_proxy_content(newProxy, 228 kSCPropNetProxiesProxyAutoDiscoveryEnable, 229 NULL, 230 NULL, 231 NULL, 232 0); 233 234 validate_proxy_content(newProxy, 235 kSCPropNetProxiesFallBackAllowed, 236 NULL, 237 NULL, 238 NULL, 239 0); 240 241 // validate FTP passive setting 242 num = CFDictionaryGetValue(newProxy, kSCPropNetProxiesFTPPassive); 243 if (num != NULL) { 244 int enabled = 0; 245 246 if (!isA_CFNumber(num) || 247 !CFNumberGetValue(num, kCFNumberIntType, &enabled)) { 248 // if we don't like the enabled key/value 249 enabled = 1; 250 num = CFNumberCreate(NULL, kCFNumberIntType, &enabled); 251 CFDictionarySetValue(newProxy, 252 kSCPropNetProxiesFTPPassive, 253 num); 254 CFRelease(num); 255 } 256 } 257 258 // validate proxy exception list 259 array = CFDictionaryGetValue(newProxy, kSCPropNetProxiesExceptionsList); 260 if (array != NULL) { 261 CFIndex i; 262 CFIndex n; 263 264 n = isA_CFArray(array) ? CFArrayGetCount(array) : 0; 265 for (i = 0; i < n; i++) { 266 CFStringRef str; 267 268 str = CFArrayGetValueAtIndex(array, i); 269 if (!isA_CFString(str) || (CFStringGetLength(str) == 0)) { 270 // if we don't like the array contents 271 n = 0; 272 break; 273 } 274 } 275 276 if (n == 0) { 277 CFDictionaryRemoveValue(newProxy, kSCPropNetProxiesExceptionsList); 278 } 279 } 280 281 // validate exclude simple hostnames setting 282 num = CFDictionaryGetValue(newProxy, kSCPropNetProxiesExcludeSimpleHostnames); 283 if (num != NULL) { 284 int enabled; 285 286 if (!isA_CFNumber(num) || 287 !CFNumberGetValue(num, kCFNumberIntType, &enabled)) { 288 // if we don't like the enabled key/value 289 enabled = 0; 290 num = CFNumberCreate(NULL, kCFNumberIntType, &enabled); 291 CFDictionarySetValue(newProxy, 292 kSCPropNetProxiesExcludeSimpleHostnames, 293 num); 294 CFRelease(num); 295 } 296 } 297 298 // cleanup scoped proxies 299 scoped = CFDictionaryGetValue(newProxy, kSCPropNetProxiesScoped); 300 if (isA_CFDictionary(scoped)) { 301 CFMutableDictionaryRef newScoped; 302 303 newScoped = CFDictionaryCreateMutable(NULL, 304 0, 305 &kCFTypeDictionaryKeyCallBacks, 306 &kCFTypeDictionaryValueCallBacks); 307 CFDictionaryApplyFunction(scoped, 308 normalize_scoped_proxy, 309 newScoped); 310 CFDictionarySetValue(newProxy, kSCPropNetProxiesScoped, newScoped); 311 CFRelease(newScoped); 312 } 313 314 // cleanup services proxies 315 services = CFDictionaryGetValue(newProxy, kSCPropNetProxiesServices); 316 if (isA_CFDictionary(services)) { 317 CFMutableDictionaryRef newServices; 318 319 newServices = CFDictionaryCreateMutable(NULL, 320 0, 321 &kCFTypeDictionaryKeyCallBacks, 322 &kCFTypeDictionaryValueCallBacks); 323 CFDictionaryApplyFunction(services, 324 normalize_services_proxy, 325 newServices); 326 CFDictionarySetValue(newProxy, kSCPropNetProxiesServices, newServices); 327 CFRelease(newServices); 328 } 329 330 // cleanup split/supplemental proxies 331 supplemental = CFDictionaryGetValue(newProxy, kSCPropNetProxiesSupplemental); 332 if (isA_CFArray(supplemental)) { 333 CFMutableArrayRef newSupplemental; 334 335 newSupplemental = CFArrayCreateMutable(NULL, 336 0, 337 &kCFTypeArrayCallBacks); 338 CFArrayApplyFunction(supplemental, 339 CFRangeMake(0, CFArrayGetCount(supplemental)), 340 normalize_supplemental_proxy, 341 newSupplemental); 342 CFDictionarySetValue(newProxy, kSCPropNetProxiesSupplemental, newSupplemental); 343 CFRelease(newSupplemental); 344 } 345 346 proxy = CFDictionaryCreateCopy(NULL,newProxy); 347 CFRelease(newProxy); 348 349 return proxy; 350} 351 352 353static void 354normalize_scoped_proxy(const void *key, const void *value, void *context) 355{ 356 CFStringRef interface = (CFStringRef)key; 357 CFDictionaryRef proxy = (CFDictionaryRef)value; 358 CFMutableDictionaryRef newScoped = (CFMutableDictionaryRef)context; 359 360 proxy = __SCNetworkProxiesCopyNormalized(proxy); 361 CFDictionarySetValue(newScoped, interface, proxy); 362 CFRelease(proxy); 363 364 return; 365} 366 367static void 368normalize_services_proxy(const void *key, const void *value, void *context) 369{ 370 CFNumberRef serviceIndex = (CFNumberRef)key; 371 CFDictionaryRef proxy = (CFDictionaryRef)value; 372 CFMutableDictionaryRef newServices = (CFMutableDictionaryRef)context; 373 374 proxy = __SCNetworkProxiesCopyNormalized(proxy); 375 CFDictionarySetValue(newServices, serviceIndex, proxy); 376 CFRelease(proxy); 377 378 return; 379} 380 381static void 382normalize_supplemental_proxy(const void *value, void *context) 383{ 384 CFDictionaryRef proxy = (CFDictionaryRef)value; 385 CFMutableArrayRef newSupplemental = (CFMutableArrayRef)context; 386 387 proxy = __SCNetworkProxiesCopyNormalized(proxy); 388 CFArrayAppendValue(newSupplemental, proxy); 389 CFRelease(proxy); 390 391 return; 392} 393 394CFDictionaryRef 395SCDynamicStoreCopyProxies(SCDynamicStoreRef store) 396{ 397 return SCDynamicStoreCopyProxiesWithOptions(store, NULL); 398} 399 400const CFStringRef kSCProxiesNoGlobal = CFSTR("NO_GLOBAL"); 401 402CFDictionaryRef 403SCDynamicStoreCopyProxiesWithOptions(SCDynamicStoreRef store, CFDictionaryRef options) 404{ 405 Boolean bypass = FALSE; 406 CFStringRef key; 407 CFDictionaryRef proxies = NULL; 408 409 if (options != NULL) { 410 CFBooleanRef bypassGlobalOption; 411 412 if (!isA_CFDictionary(options)) { 413 _SCErrorSet(kSCStatusInvalidArgument); 414 return NULL; 415 } 416 417 bypassGlobalOption = CFDictionaryGetValue(options, kSCProxiesNoGlobal); 418 if (isA_CFBoolean(bypassGlobalOption) && CFBooleanGetValue(bypassGlobalOption)) { 419 bypass = TRUE; 420 } 421 } 422 423 424 /* copy proxy information from dynamic store */ 425 426 key = SCDynamicStoreKeyCreateProxies(NULL); 427 proxies = SCDynamicStoreCopyValue(store, key); 428 CFRelease(key); 429 430 if (isA_CFDictionary(proxies) && 431 CFDictionaryContainsKey(proxies, kSCPropNetProxiesBypassAllowed)) { 432 CFMutableDictionaryRef newProxies; 433 434 newProxies = CFDictionaryCreateMutableCopy(NULL, 0, proxies); 435 CFRelease(proxies); 436 437 /* 438 * Remove kSCPropNetProxiesBypassAllowed property from network 439 * service based configurations. 440 */ 441 CFDictionaryRemoveValue(newProxies, kSCPropNetProxiesBypassAllowed); 442 proxies = newProxies; 443 } 444 445 446 if (proxies != NULL) { 447 CFDictionaryRef base = proxies; 448 449 proxies = __SCNetworkProxiesCopyNormalized(base); 450 CFRelease(base); 451 } else { 452 proxies = CFDictionaryCreate(NULL, 453 NULL, 454 NULL, 455 0, 456 &kCFTypeDictionaryKeyCallBacks, 457 &kCFTypeDictionaryValueCallBacks); 458 } 459 460 return proxies; 461} 462 463 464static CFArrayRef 465_SCNetworkProxiesCopyMatchingInternal(CFDictionaryRef globalConfiguration, 466 CFStringRef server, 467 CFStringRef interface, 468 CFDictionaryRef options) 469{ 470 CFMutableDictionaryRef newProxy; 471 uuid_t match_uuid; 472 CFArrayRef proxies = NULL; 473 CFDictionaryRef proxy; 474 int sc_status = kSCStatusOK; 475 CFStringRef trimmed = NULL; 476 477 478 if (!isA_CFDictionary(globalConfiguration)) { 479 // if no proxy configuration 480 _SCErrorSet(kSCStatusOK); 481 return NULL; 482 } 483 484 uuid_clear(match_uuid); 485 486 if (isA_CFDictionary(options)) { 487 CFUUIDRef euuid; 488 489 interface = CFDictionaryGetValue(options, kSCProxiesMatchInterface); 490 interface = isA_CFString(interface); 491 492 server = CFDictionaryGetValue(options, kSCProxiesMatchServer); 493 server = isA_CFString(server); 494 495 euuid = CFDictionaryGetValue(options, kSCProxiesMatchExecutableUUID); 496 euuid = isA_CFType(euuid, CFUUIDGetTypeID()); 497 if (euuid != NULL) { 498 CFUUIDBytes uuid_bytes = CFUUIDGetUUIDBytes(euuid); 499 uuid_copy(match_uuid, (const uint8_t *)&uuid_bytes); 500 } 501 } 502 503 if (interface != NULL) { 504 CFDictionaryRef scoped; 505 506 if (!isA_CFString(interface) || 507 (CFStringGetLength(interface) == 0)) { 508 _SCErrorSet(kSCStatusInvalidArgument); 509 return NULL; 510 } 511 512 scoped = CFDictionaryGetValue(globalConfiguration, kSCPropNetProxiesScoped); 513 if (scoped == NULL) { 514#if !TARGET_OS_SIMULATOR 515 if (CFDictionaryContainsKey(globalConfiguration, kSCPropNetProxiesBypassAllowed) && 516 ne_session_always_on_vpn_configs_present()) { 517 /* 518 * The kSCPropNetProxiesBypassAllowed key will be present 519 * for managed proxy configurations where bypassing is *not* 520 * allowed. 521 * 522 * Also (for now), forcing the use of the managed proxy 523 * configurations will only be done with AOVPN present. 524 */ 525 goto useDefault; 526 } 527#endif // !TARGET_OS_SIMULATOR 528 529 // if no scoped proxy configurations 530 _SCErrorSet(kSCStatusOK); 531 return NULL; 532 } 533 534 if (!isA_CFDictionary(scoped)) { 535 // if corrupt proxy configuration 536 _SCErrorSet(kSCStatusFailed); 537 return NULL; 538 } 539 540 proxy = CFDictionaryGetValue(scoped, interface); 541 if (proxy == NULL) { 542 // if no scoped proxy configuration for this interface 543 _SCErrorSet(kSCStatusOK); 544 return NULL; 545 } 546 547 if (!isA_CFDictionary(proxy)) { 548 // if corrupt proxy configuration 549 _SCErrorSet(kSCStatusFailed); 550 return NULL; 551 } 552 553 // return per-interface proxy configuration 554 proxies = CFArrayCreate(NULL, (const void **)&proxy, 1, &kCFTypeArrayCallBacks); 555 return proxies; 556 } 557 558 559 if (server != NULL) { 560 CFIndex i; 561 CFMutableArrayRef matching = NULL; 562 CFIndex n = 0; 563 CFIndex server_len; 564 CFArrayRef supplemental; 565 566 trimmed = _SC_trimDomain(server); 567 if (trimmed == NULL) { 568 _SCErrorSet(kSCStatusInvalidArgument); 569 return NULL; 570 } 571 572 server = trimmed; 573 server_len = CFStringGetLength(server); 574 575 supplemental = CFDictionaryGetValue(globalConfiguration, kSCPropNetProxiesSupplemental); 576 if (supplemental != NULL) { 577 if (!isA_CFArray(supplemental)) { 578 // if corrupt proxy configuration 579 sc_status = kSCStatusFailed; 580 goto done; 581 } 582 583 n = CFArrayGetCount(supplemental); 584 } 585 586 for (i = 0; i < n; i++) { 587 CFStringRef domain; 588 CFIndex domain_len; 589 CFIndex n_matching; 590 591 proxy = CFArrayGetValueAtIndex(supplemental, i); 592 if (!isA_CFDictionary(proxy)) { 593 // if corrupt proxy configuration 594 continue; 595 } 596 597 domain = CFDictionaryGetValue(proxy, kSCPropNetProxiesSupplementalMatchDomain); 598 if (!isA_CFString(domain)) { 599 // if corrupt proxy configuration 600 continue; 601 } 602 603 domain_len = CFStringGetLength(domain); 604 if (domain_len > 0) { 605 if (!CFStringFindWithOptions(server, 606 domain, 607 CFRangeMake(0, server_len), 608 kCFCompareCaseInsensitive|kCFCompareAnchored|kCFCompareBackwards, 609 NULL)) { 610 // if server does not match this proxy domain (or host) 611 continue; 612 } 613 614 if ((server_len > domain_len) && 615 !CFStringFindWithOptions(server, 616 CFSTR("."), 617 CFRangeMake(0, server_len - domain_len), 618 kCFCompareCaseInsensitive|kCFCompareAnchored|kCFCompareBackwards, 619 NULL)) { 620 // if server does not match this proxy domain 621 continue; 622 } 623// } else { 624// // if this is a "default" (match all) proxy domain 625 } 626 627 if (matching == NULL) { 628 matching = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 629 } 630 n_matching = CFArrayGetCount(matching); 631 632 newProxy = CFDictionaryCreateMutableCopy(NULL, 0, proxy); 633 CFDictionaryRemoveValue(newProxy, kSCPropNetProxiesSupplementalMatchDomain); 634 if ((n_matching == 0) || 635 !CFArrayContainsValue(matching, CFRangeMake(0, n_matching), newProxy)) { 636 // add this matching proxy 637 CFArrayAppendValue(matching, newProxy); 638 } 639 CFRelease(newProxy); 640 } 641 642 if (matching != NULL) { 643 // if we have any supplemental match domains 644 proxies = CFArrayCreateCopy(NULL, matching); 645 CFRelease(matching); 646 goto done; 647 } 648 } 649 650 // no matches, return "global" proxy configuration 651 652#if !TARGET_OS_SIMULATOR 653 useDefault : 654#endif // !TARGET_OS_SIMULATOR 655 656 newProxy = CFDictionaryCreateMutableCopy(NULL, 0, globalConfiguration); 657 CFDictionaryRemoveValue(newProxy, kSCPropNetProxiesScoped); 658 CFDictionaryRemoveValue(newProxy, kSCPropNetProxiesServices); 659 CFDictionaryRemoveValue(newProxy, kSCPropNetProxiesSupplemental); 660 proxies = CFArrayCreate(NULL, (const void **)&newProxy, 1, &kCFTypeArrayCallBacks); 661 CFRelease(newProxy); 662 663 done : 664 665 if (sc_status != kSCStatusOK) { 666 _SCErrorSet(sc_status); 667 668// Note: if we are returning an error then we must 669// return w/proxies==NULL. At present, there 670// is no code (above) that would get here with 671// proxies!=NULL so we don't need to take any 672// action but future coder's should beware :-) 673// if (proxies != NULL) { 674// CFRelease(proxies); 675// proxies = NULL; 676// } 677 } 678 if (trimmed != NULL) CFRelease(trimmed); 679 680 return proxies; 681} 682 683CFDataRef 684SCNetworkProxiesCreateProxyAgentData(CFDictionaryRef proxyConfig) 685{ 686 CFDataRef result = NULL; 687 CFArrayRef newProxy = NULL; 688 689 if (!isA_CFDictionary(proxyConfig)) { 690 SC_log(LOG_ERR, "Invalid proxy configuration"); 691 _SCErrorSet(kSCStatusInvalidArgument); 692 return NULL; 693 } 694 695 newProxy = CFArrayCreate(NULL, (const void **)&proxyConfig, 1, &kCFTypeArrayCallBacks); 696 (void)_SCSerialize(newProxy, &result, NULL, NULL); 697 CFRelease(newProxy); 698 699 return result; 700} 701 702CFArrayRef 703SCNetworkProxiesCopyMatching(CFDictionaryRef globalConfiguration, 704 CFStringRef server, 705 CFStringRef interface) 706{ 707 return _SCNetworkProxiesCopyMatchingInternal(globalConfiguration, server, interface, NULL); 708} 709 710CFArrayRef 711SCNetworkProxiesCopyMatchingWithOptions(CFDictionaryRef globalConfiguration, 712 CFDictionaryRef options) 713{ 714 return _SCNetworkProxiesCopyMatchingInternal(globalConfiguration, NULL, NULL, options); 715}