this repo has no description
at fixPythonPipStalling 1379 lines 36 kB view raw
1/* 2 * Copyright (c) 2009-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 * July 27, 2009 Allan Nathanson <ajn@apple.com> 28 * - initial revision 29 */ 30 31 32#include <CoreFoundation/CoreFoundation.h> 33#include <CoreFoundation/CFRuntime.h> 34 35#include "SCNetworkConfigurationInternal.h" 36#include "SCPreferencesInternal.h" 37 38#include <ifaddrs.h> 39#include <pthread.h> 40#include <unistd.h> 41#include <sys/types.h> 42#include <sys/ioctl.h> 43#include <sys/socket.h> 44#include <sys/sysctl.h> 45#include <net/ethernet.h> 46#define KERNEL_PRIVATE 47#include <net/if.h> 48#include <net/if_var.h> 49#undef KERNEL_PRIVATE 50#include <net/if_types.h> 51#include <net/if_media.h> 52#include <net/route.h> 53 54#ifdef IFT_BRIDGE 55#include <net/if_bridgevar.h> 56#endif // IFT_BRIDGE 57 58/* ---------- Bridge support ---------- */ 59 60static int 61inet_dgram_socket() 62{ 63 int s; 64 65 s = socket(AF_INET, SOCK_DGRAM, 0); 66 if (s == -1) { 67 SC_log(LOG_ERR, "socket() failed: %s", strerror(errno)); 68 } 69 70 return s; 71} 72 73#ifdef IFT_BRIDGE 74static struct ifbifconf * 75ifbifconf_copy(int s, const char * ifname) 76{ 77 void * buf; 78 size_t buflen; 79 struct ifbifconf * ibc_p = NULL; 80 struct ifdrv ifd; 81 uint32_t len = sizeof(struct ifbreq) * 16; 82 83 memset(&ifd, 0, sizeof(ifd)); 84 strlcpy(ifd.ifd_name, ifname, sizeof(ifd.ifd_name)); 85 ifd.ifd_cmd = BRDGGIFS; 86 87 buflen = sizeof(struct ifbifconf) + len; 88 buf = malloc(buflen); 89 while (buf != NULL) { 90 memset(buf, 0, buflen); 91 ibc_p = (struct ifbifconf *)buf; 92 ibc_p->ifbic_len = len; 93 ibc_p->ifbic_buf = buf + sizeof(*ibc_p); 94 95 ifd.ifd_len = sizeof(*ibc_p); 96 ifd.ifd_data = ibc_p; 97 if (ioctl(s, SIOCGDRVSPEC, (caddr_t)&ifd) == -1) { 98 goto failed; 99 } 100 101 if ((ibc_p->ifbic_len + sizeof(struct ifbreq)) < len) { 102 // if we have room for all of the member interfaces 103 break; 104 } 105 106 len *= 2; 107 buflen = sizeof(struct ifbifconf) + len; 108 buf = reallocf(buf, buflen); 109 } 110 111 if (buf == NULL) { 112 goto failed; 113 } 114 115 return ibc_p; 116 117 failed: 118 if (buf != NULL) { 119 free(buf); 120 } 121 return NULL; 122} 123#endif // IFT_BRIDGE 124 125 126static void 127add_interface(CFMutableArrayRef *interfaces, CFStringRef if_name, SCPreferencesRef ni_prefs) 128{ 129 SCNetworkInterfaceRef interface = NULL; 130 131 if (*interfaces == NULL) { 132 *interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 133 } 134 if (ni_prefs != NULL) { 135 interface = __SCNetworkInterfaceCreateWithNIPreferencesUsingBSDName(NULL, ni_prefs, if_name); 136 } 137 if (interface == NULL) { 138 interface = _SCNetworkInterfaceCreateWithBSDName(NULL, if_name, 139 kIncludeNoVirtualInterfaces); 140 } 141 142 if (interface != NULL) { 143 CFArrayAppendValue(*interfaces, interface); 144 CFRelease(interface); 145 } 146} 147 148typedef struct { 149 CFMutableArrayRef bridges; 150 SCPreferencesRef ni_prefs; 151 SCPreferencesRef prefs; 152} addContext, *addContextRef; 153 154 155static void 156add_configured_interface(const void *key, const void *value, void *context) 157{ 158 SCBridgeInterfaceRef bridge; 159 CFStringRef bridge_if = (CFStringRef)key; 160 CFDictionaryRef bridge_info = (CFDictionaryRef)value; 161 CFDictionaryRef bridge_options; 162 CFIndex i; 163 CFArrayRef interfaces; 164 SCNetworkInterfacePrivateRef interfacePrivate; 165 CFMutableArrayRef members = NULL; 166 addContextRef myContext = (addContextRef)context; 167 CFStringRef name; 168 CFStringRef name_auto = NULL; 169 CFIndex n; 170 171 // create the bridge interface 172 bridge = (SCBridgeInterfaceRef)_SCBridgeInterfaceCreatePrivate(NULL, bridge_if); 173 assert(bridge != NULL); 174 175 // estabish link to the stored configuration 176 interfacePrivate = (SCNetworkInterfacePrivateRef)bridge; 177 interfacePrivate->prefs = CFRetain(myContext->prefs); 178 179 // add member interfaces 180 interfaces = CFDictionaryGetValue(bridge_info, kSCPropVirtualNetworkInterfacesBridgeInterfaces); 181 n = isA_CFArray(interfaces) ? CFArrayGetCount(interfaces) : 0; 182 for (i = 0; i < n; i++) { 183 CFStringRef member; 184 185 member = CFArrayGetValueAtIndex(interfaces, i); 186 if (isA_CFString(member)) { 187 add_interface(&members, member, myContext->ni_prefs); 188 } 189 } 190 if (members != NULL) { 191 __SCBridgeInterfaceSetMemberInterfaces(bridge, members); 192 CFRelease(members); 193 } 194 195 // set options 196 bridge_options = CFDictionaryGetValue(bridge_info, kSCPropVirtualNetworkInterfacesBridgeOptions); 197 if (isA_CFDictionary(bridge_options)) { 198 SCBridgeInterfaceSetOptions(bridge, bridge_options); 199 name_auto = CFDictionaryGetValue(bridge_options, CFSTR("__AUTO__")); 200 } 201 202 // set display name 203 name = CFDictionaryGetValue(bridge_info, kSCPropUserDefinedName); 204 if (isA_CFString(name)) { 205 SCBridgeInterfaceSetLocalizedDisplayName(bridge, name); 206 } else if (isA_CFString(name_auto)) { 207 interfacePrivate->localized_key = name_auto; 208 if (interfacePrivate->localized_arg1 != NULL) { 209 CFRelease(interfacePrivate->localized_arg1); 210 interfacePrivate->localized_arg1 = NULL; 211 } 212 } 213 214 CFArrayAppendValue(myContext->bridges, bridge); 215 CFRelease(bridge); 216 217 return; 218} 219 220 221#pragma mark - 222#pragma mark SCBridgeInterface APIs 223 224 225static __inline__ void 226my_CFDictionaryApplyFunction(CFDictionaryRef theDict, 227 CFDictionaryApplierFunction applier, 228 void *context) 229{ 230 CFAllocatorRef myAllocator; 231 CFDictionaryRef myDict; 232 233 myAllocator = CFGetAllocator(theDict); 234 myDict = CFDictionaryCreateCopy(myAllocator, theDict); 235 CFDictionaryApplyFunction(myDict, applier, context); 236 CFRelease(myDict); 237 return; 238} 239 240 241CFArrayRef 242SCBridgeInterfaceCopyAll(SCPreferencesRef prefs) 243{ 244 addContext context; 245 CFDictionaryRef dict; 246 SCPreferencesRef ni_prefs; 247 CFStringRef path; 248 249 if (__SCPreferencesUsingDefaultPrefs(prefs)) { 250 ni_prefs = NULL; 251 } else { 252 ni_prefs = __SCPreferencesCreateNIPrefsFromPrefs(prefs); 253 } 254 context.bridges = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 255 context.prefs = prefs; 256 context.ni_prefs = ni_prefs; 257 258 path = CFStringCreateWithFormat(NULL, 259 NULL, 260 CFSTR("/%@/%@"), 261 kSCPrefVirtualNetworkInterfaces, 262 kSCNetworkInterfaceTypeBridge); 263 dict = SCPreferencesPathGetValue(prefs, path); 264 if (isA_CFDictionary(dict)) { 265 my_CFDictionaryApplyFunction(dict, add_configured_interface, &context); 266 } 267 CFRelease(path); 268 if (ni_prefs != NULL) { 269 CFRelease(ni_prefs); 270 } 271 return context.bridges; 272} 273 274 275__private_extern__ void 276__SCBridgeInterfaceListCollectMembers(CFArrayRef interfaces, CFMutableSetRef set) 277{ 278 CFIndex i; 279 CFIndex n; 280 281 n = CFArrayGetCount(interfaces); 282 for (i = 0; i < n; i++) { 283 SCBridgeInterfaceRef bridgeInterface; 284 CFArrayRef members; 285 286 bridgeInterface = CFArrayGetValueAtIndex(interfaces, i); 287 members = SCBridgeInterfaceGetMemberInterfaces(bridgeInterface); 288 if (members != NULL) { 289 CFIndex j; 290 CFIndex n_members; 291 292 // exclude the member interfaces of this bridge 293 n_members = CFArrayGetCount(members); 294 for (j = 0; j < n_members; j++) { 295 SCNetworkInterfaceRef member; 296 297 member = CFArrayGetValueAtIndex(members, j); 298 CFSetAddValue(set, member); 299 } 300 } 301 302 } 303 return; 304} 305 306 307CFArrayRef /* of SCNetworkInterfaceRef's */ 308SCBridgeInterfaceCopyAvailableMemberInterfaces(SCPreferencesRef prefs) 309{ 310 CFMutableArrayRef available; 311 CFMutableSetRef excluded; 312 CFArrayRef interfaces; 313 314 available = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 315 excluded = CFSetCreateMutable (NULL, 0, &kCFTypeSetCallBacks); 316 317#if !TARGET_OS_IPHONE 318 // exclude Bond [member] interfaces 319 interfaces = SCBondInterfaceCopyAll(prefs); 320 if (interfaces != NULL) { 321 __SCBondInterfaceListCollectMembers(interfaces, excluded); 322 CFRelease(interfaces); 323 } 324#endif // !TARGET_OS_IPHONE 325 326 // exclude Bridge [member] interfaces 327 interfaces = SCBridgeInterfaceCopyAll(prefs); 328 if (interfaces != NULL) { 329 __SCBridgeInterfaceListCollectMembers(interfaces, excluded); 330 CFRelease(interfaces); 331 } 332 333 // exclude VLAN [physical] interfaces 334 interfaces = SCVLANInterfaceCopyAll(prefs); 335 if (interfaces != NULL) { 336 CFIndex i; 337 CFIndex n; 338 339 n = CFArrayGetCount(interfaces); 340 for (i = 0; i < n; i++) { 341 SCVLANInterfaceRef vlanInterface; 342 SCNetworkInterfaceRef physical; 343 344 // exclude the physical interface of this VLAN 345 vlanInterface = CFArrayGetValueAtIndex(interfaces, i); 346 physical = SCVLANInterfaceGetPhysicalInterface(vlanInterface); 347 CFSetAddValue(excluded, physical); 348 } 349 CFRelease(interfaces); 350 } 351 352 // identify available interfaces 353 interfaces = __SCNetworkInterfaceCopyAll_IONetworkInterface(FALSE); 354 if (interfaces != NULL) { 355 CFIndex i; 356 CFIndex n; 357 358 n = CFArrayGetCount(interfaces); 359 for (i = 0; i < n; i++) { 360 SCNetworkInterfaceRef interface; 361 SCNetworkInterfacePrivateRef interfacePrivate; 362 363 interface = CFArrayGetValueAtIndex(interfaces, i); 364 interfacePrivate = (SCNetworkInterfacePrivateRef)interface; 365 366 if (!interfacePrivate->supportsBridge) { 367 // if this interface is not available 368 continue; 369 } 370 371 if (CFSetContainsValue(excluded, interface)) { 372 // if excluded 373 continue; 374 } 375 376 CFArrayAppendValue(available, interface); 377 } 378 CFRelease(interfaces); 379 } 380 381 CFRelease(excluded); 382 383 return available; 384} 385 386 387CFArrayRef 388_SCBridgeInterfaceCopyActive(void) 389{ 390 struct ifaddrs *ifap; 391 struct ifaddrs *ifp; 392 int s; 393 CFMutableArrayRef bridges = NULL; 394 395 if (getifaddrs(&ifap) == -1) { 396 _SCErrorSet(errno); 397 SC_log(LOG_NOTICE, "getifaddrs() failed: %s", strerror(errno)); 398 return NULL; 399 } 400 401 s = inet_dgram_socket(); 402 if (s == -1) { 403 _SCErrorSet(errno); 404 goto done; 405 } 406 407 bridges = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 408 409 for (ifp = ifap; ifp != NULL; ifp = ifp->ifa_next) { 410#ifdef IFT_BRIDGE 411 SCBridgeInterfaceRef bridge; 412 CFStringRef bridge_if; 413 struct ifbifconf *ibc_p; 414 struct if_data *if_data; 415 CFMutableArrayRef members = NULL; 416 size_t n; 417 418 if_data = (struct if_data *)ifp->ifa_data; 419 if (if_data == NULL 420 || ifp->ifa_addr->sa_family != AF_LINK 421 || if_data->ifi_type != IFT_BRIDGE) { 422 continue; 423 } 424 425 // make sure that we leave non-SC configured bridge 426 // interfaces (those with unit #'s >= 100) alone. 427 n = strlen(ifp->ifa_name); 428 if ((n > 3) && 429 isdigit(ifp->ifa_name[n - 1]) && 430 isdigit(ifp->ifa_name[n - 2]) && 431 isdigit(ifp->ifa_name[n - 3])) { 432 // if not SC managed bridge interface 433 continue; 434 } 435 436 ibc_p = ifbifconf_copy(s, ifp->ifa_name); 437 if (ibc_p == NULL) { 438 if (errno == EBUSY) { 439 continue; 440 } 441 _SCErrorSet(errno); 442 SC_log(LOG_NOTICE, "ifbifconf_copy(%s) failed: %s", 443 ifp->ifa_name, 444 strerror(errno)); 445 CFRelease(bridges); 446 bridges = NULL; 447 goto done; 448 } 449 450 // create the bridge interface 451 bridge_if = CFStringCreateWithCString(NULL, ifp->ifa_name, kCFStringEncodingASCII); 452 bridge = (SCBridgeInterfaceRef)_SCBridgeInterfaceCreatePrivate(NULL, bridge_if); 453 CFRelease(bridge_if); 454 455 // add member interfaces 456 if (ibc_p->ifbic_len > 0) { 457 // iterate over each member interface 458 for (size_t i = 0; i < ibc_p->ifbic_len / sizeof(struct ifbreq); i++) { 459 struct ifbreq *ibr_p; 460 CFStringRef member; 461 462 ibr_p = ibc_p->ifbic_req + i; 463 member = CFStringCreateWithCString(NULL, ibr_p->ifbr_ifsname, kCFStringEncodingASCII); 464 add_interface(&members, member, NULL); 465 CFRelease(member); 466 } 467 } 468 free(ibc_p); 469 470 if (members != NULL) { 471 __SCBridgeInterfaceSetMemberInterfaces(bridge, members); 472 CFRelease(members); 473 } 474 475 // add bridge 476 CFArrayAppendValue(bridges, bridge); 477 CFRelease(bridge); 478#endif // IFT_BRIDGE 479 } 480 481 done : 482 483 if (s != -1) { 484 (void) close(s); 485 } 486 freeifaddrs(ifap); 487 return bridges; 488} 489 490 491SCBridgeInterfaceRef 492SCBridgeInterfaceCreate(SCPreferencesRef prefs) 493{ 494 CFAllocatorRef allocator; 495 SCBridgeInterfaceRef bridge = NULL; 496 CFIndex i; 497 498 if (prefs == NULL) { 499 _SCErrorSet(kSCStatusInvalidArgument); 500 return NULL; 501 } 502 503 allocator = CFGetAllocator(prefs); 504 505 // create a new bridge using an unused interface name 506 for (i = 0; bridge == NULL; i++) { 507 CFDictionaryRef dict; 508 CFStringRef bridge_if; 509 SCNetworkInterfacePrivateRef interfacePrivate; 510 CFMutableDictionaryRef newDict; 511 CFArrayRef newInterfaces; 512 Boolean ok; 513 CFStringRef path; 514 515 bridge_if = CFStringCreateWithFormat(allocator, NULL, CFSTR("bridge%ld"), i); 516 path = CFStringCreateWithFormat(allocator, 517 NULL, 518 CFSTR("/%@/%@/%@"), 519 kSCPrefVirtualNetworkInterfaces, 520 kSCNetworkInterfaceTypeBridge, 521 bridge_if); 522 dict = SCPreferencesPathGetValue(prefs, path); 523 if (dict != NULL) { 524 // if bridge interface name not available 525 CFRelease(path); 526 CFRelease(bridge_if); 527 continue; 528 } 529 530 // add the bridge to the stored preferences 531 newDict = CFDictionaryCreateMutable(allocator, 532 0, 533 &kCFTypeDictionaryKeyCallBacks, 534 &kCFTypeDictionaryValueCallBacks); 535 newInterfaces = CFArrayCreate(allocator, NULL, 0, &kCFTypeArrayCallBacks); 536 CFDictionaryAddValue(newDict, kSCPropVirtualNetworkInterfacesBridgeInterfaces, newInterfaces); 537 CFRelease(newInterfaces); 538 ok = SCPreferencesPathSetValue(prefs, path, newDict); 539 CFRelease(newDict); 540 CFRelease(path); 541 if (!ok) { 542 // if the bridge could not be saved 543 CFRelease(bridge_if); 544 break; 545 } 546 547 // create the SCBridgeInterfaceRef 548 bridge = (SCBridgeInterfaceRef)_SCBridgeInterfaceCreatePrivate(allocator, bridge_if); 549 CFRelease(bridge_if); 550 551 // estabish link to the stored configuration 552 interfacePrivate = (SCNetworkInterfacePrivateRef)bridge; 553 interfacePrivate->prefs = CFRetain(prefs); 554 } 555 556 return bridge; 557} 558 559 560Boolean 561SCBridgeInterfaceRemove(SCBridgeInterfaceRef bridge) 562{ 563 CFStringRef bridge_if; 564 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)bridge; 565 Boolean ok; 566 CFStringRef path; 567 568 if (!isA_SCBridgeInterface(bridge)) { 569 _SCErrorSet(kSCStatusInvalidArgument); 570 return FALSE; 571 } 572 573 if (interfacePrivate->prefs == NULL) { 574 _SCErrorSet(kSCStatusInvalidArgument); 575 return FALSE; 576 } 577 578 bridge_if = SCNetworkInterfaceGetBSDName(bridge); 579 path = CFStringCreateWithFormat(NULL, 580 NULL, 581 CFSTR("/%@/%@/%@"), 582 kSCPrefVirtualNetworkInterfaces, 583 kSCNetworkInterfaceTypeBridge, 584 bridge_if); 585 ok = SCPreferencesPathRemoveValue(interfacePrivate->prefs, path); 586 CFRelease(path); 587 588 return ok; 589} 590 591 592CFArrayRef 593SCBridgeInterfaceGetMemberInterfaces(SCBridgeInterfaceRef bridge) 594{ 595 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)bridge; 596 597 if (!isA_SCBridgeInterface(bridge)) { 598 _SCErrorSet(kSCStatusInvalidArgument); 599 return NULL; 600 } 601 602 return interfacePrivate->bridge.interfaces; 603} 604 605 606CFDictionaryRef 607SCBridgeInterfaceGetOptions(SCBridgeInterfaceRef bridge) 608{ 609 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)bridge; 610 611 if (!isA_SCBridgeInterface(bridge)) { 612 _SCErrorSet(kSCStatusInvalidArgument); 613 return NULL; 614 } 615 616 return interfacePrivate->bridge.options; 617} 618 619 620__private_extern__ 621Boolean 622__SCBridgeInterfaceSetMemberInterfaces(SCBridgeInterfaceRef bridge, CFArrayRef members) 623{ 624 CFIndex i; 625 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)bridge; 626 CFIndex n; 627 CFMutableArrayRef newMembers; 628 Boolean ok = TRUE; 629 630 n = (members != NULL) ? CFArrayGetCount(members) : 0; 631 632 // set member interfaces in the stored preferences 633 if (interfacePrivate->prefs != NULL) { 634 CFDictionaryRef dict; 635 CFMutableDictionaryRef newDict; 636 CFStringRef path; 637 638 path = CFStringCreateWithFormat(NULL, 639 NULL, 640 CFSTR("/%@/%@/%@"), 641 kSCPrefVirtualNetworkInterfaces, 642 kSCNetworkInterfaceTypeBridge, 643 interfacePrivate->entity_device); 644 dict = SCPreferencesPathGetValue(interfacePrivate->prefs, path); 645 if (!isA_CFDictionary(dict)) { 646 // if the prefs are confused 647 CFRelease(path); 648 _SCErrorSet(kSCStatusFailed); 649 return FALSE; 650 } 651 652 newMembers = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 653 for (i = 0; i < n; i++) { 654 SCNetworkInterfaceRef interface; 655 CFStringRef memberName; 656 657 interface = CFArrayGetValueAtIndex(members, i); 658 memberName = SCNetworkInterfaceGetBSDName(interface); 659 CFArrayAppendValue(newMembers, memberName); 660 } 661 662 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict); 663 CFDictionarySetValue(newDict, kSCPropVirtualNetworkInterfacesBridgeInterfaces, newMembers); 664 CFRelease(newMembers); 665 if (!CFEqual(dict, newDict)) { 666 ok = SCPreferencesPathSetValue(interfacePrivate->prefs, path, newDict); 667 } 668 CFRelease(newDict); 669 CFRelease(path); 670 } 671 672 if (ok) { 673 newMembers = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 674 for (i = 0; i < n; i++) { 675 SCNetworkInterfaceRef member; 676 SCNetworkInterfacePrivateRef newMember; 677 678 member = CFArrayGetValueAtIndex(members, i); 679 newMember = __SCNetworkInterfaceCreateCopy(NULL, 680 member, 681 interfacePrivate->prefs, 682 interfacePrivate->serviceID); 683 CFArrayAppendValue(newMembers, newMember); 684 CFRelease(newMember); 685 } 686 CFRelease(interfacePrivate->bridge.interfaces); 687 interfacePrivate->bridge.interfaces = newMembers; 688 } 689 690 return ok; 691} 692 693 694Boolean 695SCBridgeInterfaceSetMemberInterfaces(SCBridgeInterfaceRef bridge, CFArrayRef members) 696{ 697 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)bridge; 698 Boolean ok; 699 int sc_status = kSCStatusOK; 700 701 if (!isA_SCBridgeInterface(bridge)) { 702 _SCErrorSet(kSCStatusInvalidArgument); 703 return FALSE; 704 } 705 706 if (members != NULL) { 707 CFIndex n_members; 708 709 if (!isA_CFArray(members)) { 710 _SCErrorSet(kSCStatusInvalidArgument); 711 return FALSE; 712 } 713 714 n_members = CFArrayGetCount(members); 715 for (CFIndex i = 0; i < n_members; i++) { 716 SCNetworkInterfaceRef member; 717 CFStringRef memberName; 718 719 member = CFArrayGetValueAtIndex(members, i); 720 if (!isA_SCNetworkInterface(member)) { 721 _SCErrorSet(kSCStatusInvalidArgument); 722 return FALSE; 723 } 724 725 memberName = SCNetworkInterfaceGetBSDName(member); 726 if (memberName == NULL) { 727 _SCErrorSet(kSCStatusInvalidArgument); 728 return FALSE; 729 } 730 } 731 } 732 733 if (interfacePrivate->prefs != NULL) { 734 CFArrayRef available; 735 CFArrayRef current; 736 CFIndex n_available; 737 CFIndex n_current; 738 CFIndex n_members; 739 CFArrayRef services = NULL; 740 741 current = SCBridgeInterfaceGetMemberInterfaces(bridge); 742 n_current = (current != NULL) ? CFArrayGetCount(current) : 0; 743 744 available = SCBridgeInterfaceCopyAvailableMemberInterfaces(interfacePrivate->prefs); 745 n_available = (available != NULL) ? CFArrayGetCount(available) : 0; 746 747 n_members = (members != NULL) ? CFArrayGetCount(members) : 0; 748 for (CFIndex i = 0; i < n_members; i++) { 749 SCNetworkInterfaceRef member; 750 751 member = CFArrayGetValueAtIndex(members, i); 752 753 if ((current != NULL) && 754 CFArrayContainsValue(current, CFRangeMake(0, n_current), member)) { 755 // current members are allowed 756 continue; 757 } 758 759 if ((available != NULL) && 760 CFArrayContainsValue(available, CFRangeMake(0, n_available), member)) { 761 // available members are allowed but cannot be associated 762 // with any other network services. 763 764 if (services == NULL) { 765 services = __SCNetworkServiceCopyAllEnabled(interfacePrivate->prefs); 766 } 767 if ((services != NULL) && 768 __SCNetworkServiceExistsForInterface(services, member)) { 769 sc_status = kSCStatusKeyExists; 770 break; 771 } 772 773 // if available 774 continue; 775 } 776 777 // if member not allowed 778 sc_status = kSCStatusInvalidArgument; 779 break; 780 } 781 782 if (available != NULL) CFRelease(available); 783 if (services != NULL) CFRelease(services); 784 } 785 786 if (sc_status != kSCStatusOK) { 787 _SCErrorSet(sc_status); 788 return FALSE; 789 } 790 791 ok = __SCBridgeInterfaceSetMemberInterfaces(bridge, members); 792 return ok; 793} 794 795 796Boolean 797SCBridgeInterfaceSetLocalizedDisplayName(SCBridgeInterfaceRef bridge, CFStringRef newName) 798{ 799 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)bridge; 800 Boolean ok = TRUE; 801 802 if (!isA_SCBridgeInterface(bridge)) { 803 _SCErrorSet(kSCStatusInvalidArgument); 804 return FALSE; 805 } 806 807 if ((newName != NULL) && !isA_CFString(newName)) { 808 _SCErrorSet(kSCStatusInvalidArgument); 809 return FALSE; 810 } 811 812 // set name in the stored preferences 813 if (interfacePrivate->prefs != NULL) { 814 CFDictionaryRef dict; 815 CFMutableDictionaryRef newDict; 816 CFStringRef path; 817 818 path = CFStringCreateWithFormat(NULL, 819 NULL, 820 CFSTR("/%@/%@/%@"), 821 kSCPrefVirtualNetworkInterfaces, 822 kSCNetworkInterfaceTypeBridge, 823 interfacePrivate->entity_device); 824 dict = SCPreferencesPathGetValue(interfacePrivate->prefs, path); 825 if (!isA_CFDictionary(dict)) { 826 // if the prefs are confused 827 CFRelease(path); 828 _SCErrorSet(kSCStatusFailed); 829 return FALSE; 830 } 831 832 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict); 833 if (newName != NULL) { 834 CFDictionarySetValue(newDict, kSCPropUserDefinedName, newName); 835 } else { 836 CFDictionaryRemoveValue(newDict, kSCPropUserDefinedName); 837 } 838 if (!CFEqual(dict, newDict)) { 839 ok = SCPreferencesPathSetValue(interfacePrivate->prefs, path, newDict); 840 } 841 CFRelease(newDict); 842 CFRelease(path); 843 } 844 845 // set name in the SCBridgeInterfaceRef 846 if (ok) { 847 if (interfacePrivate->localized_name != NULL) { 848 CFRelease(interfacePrivate->localized_name); 849 interfacePrivate->localized_name = NULL; 850 } 851 if (newName != NULL) { 852 interfacePrivate->localized_name = CFStringCreateCopy(NULL, newName); 853 } 854 } 855 856 return ok; 857} 858 859 860Boolean 861SCBridgeInterfaceSetOptions(SCBridgeInterfaceRef bridge, CFDictionaryRef newOptions) 862{ 863 SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)bridge; 864 Boolean ok = TRUE; 865 866 if (!isA_SCBridgeInterface(bridge)) { 867 _SCErrorSet(kSCStatusInvalidArgument); 868 return FALSE; 869 } 870 871 if ((newOptions != NULL) && !isA_CFDictionary(newOptions)) { 872 _SCErrorSet(kSCStatusInvalidArgument); 873 return FALSE; 874 } 875 876 // set options in the stored preferences 877 if (interfacePrivate->prefs != NULL) { 878 CFDictionaryRef dict; 879 CFMutableDictionaryRef newDict; 880 CFStringRef path; 881 882 path = CFStringCreateWithFormat(NULL, 883 NULL, 884 CFSTR("/%@/%@/%@"), 885 kSCPrefVirtualNetworkInterfaces, 886 kSCNetworkInterfaceTypeBridge, 887 interfacePrivate->entity_device); 888 dict = SCPreferencesPathGetValue(interfacePrivate->prefs, path); 889 if (!isA_CFDictionary(dict)) { 890 // if the prefs are confused 891 CFRelease(path); 892 _SCErrorSet(kSCStatusFailed); 893 return FALSE; 894 } 895 896 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict); 897 if (newOptions != NULL) { 898 CFDictionarySetValue(newDict, kSCPropVirtualNetworkInterfacesBridgeOptions, newOptions); 899 } else { 900 CFDictionaryRemoveValue(newDict, kSCPropVirtualNetworkInterfacesBridgeOptions); 901 } 902 if (!CFEqual(dict, newDict)) { 903 ok = SCPreferencesPathSetValue(interfacePrivate->prefs, path, newDict); 904 } 905 CFRelease(newDict); 906 CFRelease(path); 907 } 908 909 // set options in the SCBridgeInterfaceRef 910 if (ok) { 911 if (interfacePrivate->bridge.options != NULL) { 912 CFRelease(interfacePrivate->bridge.options); 913 interfacePrivate->bridge.options = NULL; 914 } 915 if (newOptions != NULL) { 916 CFStringRef name_auto = NULL; 917 918 interfacePrivate->bridge.options = CFDictionaryCreateCopy(NULL, newOptions); 919 920 // set [auto] display name from options 921 if ((interfacePrivate->localized_name == NULL) && 922 CFDictionaryGetValueIfPresent(newOptions, 923 CFSTR("__AUTO__"), 924 (const void **)&name_auto) && 925 isA_CFString(name_auto)) { 926 // set display name 927 interfacePrivate->localized_key = name_auto; 928 if (interfacePrivate->localized_arg1 != NULL) { 929 CFRelease(interfacePrivate->localized_arg1); 930 interfacePrivate->localized_arg1 = NULL; 931 } 932 } 933 } 934 } 935 936 return ok; 937} 938 939 940#pragma mark - 941#pragma mark SCBridgeInterface management 942 943 944#ifdef IFT_BRIDGE 945static Boolean 946__bridge_add_interface(int s, CFStringRef bridge_if, CFStringRef interface_if) 947{ 948 struct ifbreq breq; 949 struct ifdrv ifd; 950 951 // bridge interface 952 memset(&ifd, 0, sizeof(ifd)); 953 (void) _SC_cfstring_to_cstring(bridge_if, 954 ifd.ifd_name, 955 sizeof(ifd.ifd_name), 956 kCFStringEncodingASCII); 957 ifd.ifd_cmd = BRDGADD; 958 ifd.ifd_len = sizeof(breq); 959 ifd.ifd_data = (caddr_t)&breq; 960 961 // new bridge member 962 memset(&breq, 0, sizeof(breq)); 963 (void) _SC_cfstring_to_cstring(interface_if, 964 breq.ifbr_ifsname, 965 sizeof(breq.ifbr_ifsname), 966 kCFStringEncodingASCII); 967 968 // add new bridge member 969 if (ioctl(s, SIOCSDRVSPEC, (caddr_t)&ifd) == -1) { 970 _SCErrorSet(errno); 971 SC_log(LOG_ERR, "could not add interface \"%@\" to bridge \"%@\": %s", 972 interface_if, 973 bridge_if, 974 strerror(errno)); 975 return FALSE; 976 } 977 978 SC_log(LOG_INFO, "%@: added bridge member: %@", bridge_if, interface_if); 979 return TRUE; 980} 981 982 983static Boolean 984__bridge_remove_interface(int s, CFStringRef bridge_if, CFStringRef interface_if) 985{ 986 struct ifbreq breq; 987 struct ifdrv ifd; 988 989 // bridge interface 990 memset(&ifd, 0, sizeof(ifd)); 991 (void) _SC_cfstring_to_cstring(bridge_if, 992 ifd.ifd_name, 993 sizeof(ifd.ifd_name), 994 kCFStringEncodingASCII); 995 ifd.ifd_cmd = BRDGDEL; 996 ifd.ifd_len = sizeof(breq); 997 ifd.ifd_data = (caddr_t)&breq; 998 999 // bridge member to remove 1000 memset(&breq, 0, sizeof(breq)); 1001 (void) _SC_cfstring_to_cstring(interface_if, 1002 breq.ifbr_ifsname, 1003 sizeof(breq.ifbr_ifsname), 1004 kCFStringEncodingASCII); 1005 1006 // remove bridge member 1007 if (ioctl(s, SIOCSDRVSPEC, (caddr_t)&ifd) == -1) { 1008 _SCErrorSet(errno); 1009 SC_log(LOG_ERR, "could not remove interface \"%@\" from bridge \"%@\": %s", 1010 interface_if, 1011 bridge_if, 1012 strerror(errno)); 1013 return FALSE; 1014 } 1015 1016 SC_log(LOG_INFO, "%@: removed bridge member: %@", bridge_if, interface_if); 1017 return TRUE; 1018} 1019 1020 1021static Boolean 1022__bridge_set_mac(int s, CFStringRef bridge_if, CFDataRef macAddr) 1023{ 1024 struct ifreq ifr; 1025 1026 memset(&ifr, 0, sizeof(ifr)); 1027 (void) _SC_cfstring_to_cstring(bridge_if, 1028 ifr.ifr_name, 1029 sizeof(ifr.ifr_name), 1030 kCFStringEncodingASCII); 1031 ifr.ifr_addr.sa_len = CFDataGetLength(macAddr); 1032 if (ifr.ifr_addr.sa_len > sizeof(ifr.ifr_addr.sa_data)) { 1033 _SCErrorSet(kSCStatusInvalidArgument); 1034 SC_log(LOG_ERR, "%@: maformed MAC address (%d > %lu)", 1035 bridge_if, 1036 ifr.ifr_addr.sa_len, 1037 sizeof(ifr.ifr_addr.sa_data)); 1038 return FALSE; 1039 } 1040 CFDataGetBytes(macAddr, CFRangeMake(0, ifr.ifr_addr.sa_len), (UInt8 *)ifr.ifr_addr.sa_data); 1041 1042 if (ioctl(s, SIOCSIFLLADDR, &ifr) == -1) { 1043 _SCErrorSet(errno); 1044 SC_log(LOG_ERR, "%@: could not set MAC address: %s", 1045 bridge_if, 1046 strerror(errno)); 1047 return FALSE; 1048 } 1049 1050 SC_log(LOG_INFO, "%@: updated MAC address: %{ private }@", bridge_if, macAddr); 1051 return TRUE; 1052} 1053#endif // IFT_BRIDGE 1054 1055 1056Boolean 1057_SCBridgeInterfaceUpdateConfiguration(SCPreferencesRef prefs) 1058{ 1059#ifdef IFT_BRIDGE 1060 CFArrayRef active = NULL; 1061 CFArrayRef config = NULL; 1062 CFIndex i; 1063 CFIndex nActive; 1064 CFIndex nConfig; 1065 Boolean ok = TRUE; 1066 int s = -1; 1067 1068 if (prefs == NULL) { 1069 _SCErrorSet(kSCStatusInvalidArgument); 1070 return FALSE; 1071 } 1072 1073 /* configured Bridges */ 1074 config = SCBridgeInterfaceCopyAll(prefs); 1075 nConfig = (config != NULL) ? CFArrayGetCount(config) : 0; 1076 1077 /* active Bridges */ 1078 active = _SCBridgeInterfaceCopyActive(); 1079 nActive = (active != NULL) ? CFArrayGetCount(active) : 0; 1080 1081 /* 1082 * remove any no-longer-configured bridge interfaces and 1083 * any members associated with a bridge that are no longer 1084 * associated with a bridge. 1085 */ 1086 for (i = 0; i < nActive; i++) { 1087 SCBridgeInterfaceRef a_bridge; 1088 CFStringRef a_bridge_if; 1089 CFIndex j; 1090 Boolean found = FALSE; 1091 1092 a_bridge = CFArrayGetValueAtIndex(active, i); 1093 a_bridge_if = SCNetworkInterfaceGetBSDName(a_bridge); 1094 1095 for (j = 0; j < nConfig; j++) { 1096 SCBridgeInterfaceRef c_bridge; 1097 CFStringRef c_bridge_if; 1098 1099 c_bridge = CFArrayGetValueAtIndex(config, j); 1100 c_bridge_if = SCNetworkInterfaceGetBSDName(c_bridge); 1101 1102 if (CFEqual(a_bridge_if, c_bridge_if)) { 1103 CFIndex a; 1104 CFArrayRef a_bridge_interfaces; 1105 CFIndex a_count; 1106 CFArrayRef c_bridge_interfaces; 1107 CFIndex c_count; 1108 1109 c_bridge_interfaces = SCBridgeInterfaceGetMemberInterfaces(c_bridge); 1110 c_count = (c_bridge_interfaces != NULL) ? CFArrayGetCount(c_bridge_interfaces) : 0; 1111 1112 a_bridge_interfaces = SCBridgeInterfaceGetMemberInterfaces(a_bridge); 1113 a_count = (a_bridge_interfaces != NULL) ? CFArrayGetCount(a_bridge_interfaces) : 0; 1114 1115 for (a = 0; a < a_count; a++) { 1116 SCNetworkInterfaceRef a_interface; 1117 CFStringRef a_interface_if; 1118 1119 a_interface = CFArrayGetValueAtIndex(a_bridge_interfaces, a); 1120 if ((c_count == 0) || 1121 !CFArrayContainsValue(c_bridge_interfaces, 1122 CFRangeMake(0, c_count), 1123 a_interface)) { 1124 /* 1125 * if this member is no longer part 1126 * of the bridge. 1127 */ 1128 if (s == -1) { 1129 s = inet_dgram_socket(); 1130 if (s == -1) { 1131 _SCErrorSet(errno); 1132 ok = FALSE; 1133 goto done; 1134 } 1135 } 1136 1137 a_interface_if = SCNetworkInterfaceGetBSDName(a_interface); 1138 if (!__bridge_remove_interface(s, a_bridge_if, a_interface_if)) { 1139 ok = FALSE; 1140 } 1141 } 1142 } 1143 1144 found = TRUE; 1145 break; 1146 } 1147 } 1148 1149 if (!found) { 1150 /* 1151 * if this interface is no longer configured 1152 */ 1153 if (s == -1) { 1154 s = inet_dgram_socket(); 1155 if (s == -1) { 1156 _SCErrorSet(errno); 1157 ok = FALSE; 1158 goto done; 1159 } 1160 } 1161 1162 if (!__destroyInterface(s, a_bridge_if)) { 1163 _SCErrorSet(errno); 1164 ok = FALSE; 1165 } 1166 } 1167 } 1168 1169 /* 1170 * add any newly-configured bridge interfaces and add any 1171 * members that should now be associated with the bridge. 1172 */ 1173 for (i = 0; i < nConfig; i++) { 1174 SCBridgeInterfaceRef c_bridge; 1175 CFArrayRef c_bridge_interfaces; 1176 CFStringRef c_bridge_if; 1177 CFIndex c_count; 1178 Boolean found = FALSE; 1179 CFIndex j; 1180 Boolean setMAC = FALSE; 1181 1182 c_bridge = CFArrayGetValueAtIndex(config, i); 1183 c_bridge_if = SCNetworkInterfaceGetBSDName(c_bridge); 1184 c_bridge_interfaces = SCBridgeInterfaceGetMemberInterfaces(c_bridge); 1185 c_count = (c_bridge_interfaces != NULL) ? CFArrayGetCount(c_bridge_interfaces) : 0; 1186 1187 for (j = 0; j < nActive; j++) { 1188 SCBridgeInterfaceRef a_bridge; 1189 CFArrayRef a_bridge_interfaces; 1190 CFStringRef a_bridge_if; 1191 CFIndex a_count; 1192 1193 a_bridge = CFArrayGetValueAtIndex(active, j); 1194 a_bridge_if = SCNetworkInterfaceGetBSDName(a_bridge); 1195 a_bridge_interfaces = SCBridgeInterfaceGetMemberInterfaces(a_bridge); 1196 a_count = (a_bridge_interfaces != NULL) ? CFArrayGetCount(a_bridge_interfaces) : 0; 1197 1198 if (CFEqual(c_bridge_if, a_bridge_if)) { 1199 CFIndex c; 1200 1201 found = TRUE; 1202 1203 if (_SC_CFEqual(c_bridge_interfaces, a_bridge_interfaces)) { 1204 break; // if no change 1205 } 1206 1207 if (s == -1) { 1208 s = inet_dgram_socket(); 1209 if (s == -1) { 1210 _SCErrorSet(errno); 1211 ok = FALSE; 1212 goto done; 1213 } 1214 } 1215 1216 /* 1217 * ensure that the first member of the bridge matches, if 1218 * not then we remove all current members and add them 1219 * back in the preferred order. 1220 */ 1221 if ((c_count > 0) && 1222 (a_count > 0) && 1223 !CFEqual(CFArrayGetValueAtIndex(c_bridge_interfaces, 0), 1224 CFArrayGetValueAtIndex(a_bridge_interfaces, 0))) { 1225 CFIndex a; 1226 1227 for (a = 0; a < a_count; a++) { 1228 SCNetworkInterfaceRef a_interface; 1229 CFStringRef a_interface_if; 1230 1231 a_interface = CFArrayGetValueAtIndex(a_bridge_interfaces, a); 1232 if (!CFArrayContainsValue(c_bridge_interfaces, 1233 CFRangeMake(0, c_count), 1234 a_interface)) { 1235 continue; // if already removed 1236 } 1237 1238 a_interface_if = SCNetworkInterfaceGetBSDName(a_interface); 1239 if (!__bridge_remove_interface(s, a_bridge_if, a_interface_if)) { 1240 ok = FALSE; 1241 } 1242 } 1243 1244 a_count = 0; // all active members have been removed 1245 } 1246 1247 if (a_count == 0) { 1248 setMAC = TRUE; 1249 } 1250 1251 /* 1252 * add any members which are not currently associated 1253 * with the bridge interface. 1254 */ 1255 for (c = 0; c < c_count; c++) { 1256 SCNetworkInterfaceRef c_interface; 1257 SCNetworkInterfacePrivateRef c_interfacePrivate; 1258 CFStringRef c_interface_if; 1259 1260 c_interface = CFArrayGetValueAtIndex(c_bridge_interfaces, c); 1261 if ((a_count == 0) || 1262 !CFArrayContainsValue(a_bridge_interfaces, 1263 CFRangeMake(0, a_count), 1264 c_interface)) { 1265 /* 1266 * check if this member interface can be added to a bridge. 1267 */ 1268 c_interfacePrivate = (SCNetworkInterfacePrivateRef)c_interface; 1269 if (!c_interfacePrivate->supportsBridge) { 1270 // if member not supported 1271 continue; 1272 } 1273 1274 /* 1275 * if this is the first member interface, set the MAC address 1276 * of the bridge. 1277 */ 1278 if (setMAC) { 1279 CFDataRef macAddr; 1280 1281 macAddr = _SCNetworkInterfaceGetHardwareAddress(c_interface); 1282 if (!__bridge_set_mac(s, c_bridge_if, macAddr)) { 1283 // if bridge MAC could not be set 1284 ok = FALSE; 1285 } 1286 setMAC = FALSE; 1287 } 1288 1289 /* 1290 * add the member interface to the bridge. 1291 */ 1292 c_interface_if = SCNetworkInterfaceGetBSDName(c_interface); 1293 if (!__bridge_add_interface(s, c_bridge_if, c_interface_if)) { 1294 // if member could not be added 1295 ok = FALSE; 1296 } 1297 } 1298 } 1299 1300 break; 1301 } 1302 } 1303 1304 if (!found) { 1305 CFIndex c; 1306 1307 if (s == -1) { 1308 s = inet_dgram_socket(); 1309 if (s == -1) { 1310 _SCErrorSet(errno); 1311 ok = FALSE; 1312 goto done; 1313 } 1314 } 1315 1316 /* 1317 * establish the new bridge interface. 1318 */ 1319 if (!__createInterface(s, c_bridge_if)) { 1320 _SCErrorSet(errno); 1321 ok = FALSE; 1322 continue; 1323 } 1324 1325 setMAC = TRUE; 1326 1327 /* 1328 * add the member interfaces 1329 */ 1330 for (c = 0; c < c_count; c++) { 1331 SCNetworkInterfaceRef c_interface; 1332 SCNetworkInterfacePrivateRef c_interfacePrivate; 1333 CFStringRef c_interface_if; 1334 1335 c_interface = CFArrayGetValueAtIndex(c_bridge_interfaces, c); 1336 c_interfacePrivate = (SCNetworkInterfacePrivateRef)c_interface; 1337 if (!c_interfacePrivate->supportsBridge) { 1338 // if member not supported 1339 continue; 1340 } 1341 1342 /* 1343 * if this is the first member interface, set the MAC address 1344 * of the bridge. 1345 */ 1346 if (setMAC) { 1347 CFDataRef macAddr; 1348 1349 macAddr = _SCNetworkInterfaceGetHardwareAddress(c_interface); 1350 if (!__bridge_set_mac(s, c_bridge_if, macAddr)) { 1351 // if bridge MAC could not be set 1352 ok = FALSE; 1353 } 1354 setMAC = FALSE; 1355 } 1356 1357 /* 1358 * add the member interface to the bridge. 1359 */ 1360 c_interface_if = SCNetworkInterfaceGetBSDName(c_interface); 1361 if (!__bridge_add_interface(s, c_bridge_if, c_interface_if)) { 1362 // if member could not be added 1363 ok = FALSE; 1364 } 1365 } 1366 } 1367 } 1368 1369 done : 1370 1371 if (active != NULL) CFRelease(active); 1372 if (config != NULL) CFRelease(config); 1373 if (s != -1) (void) close(s); 1374 1375 return ok; 1376#else // IFT_BRIDGE 1377 return TRUE; 1378#endif // IFT_BRIDGE 1379}