1/* 2 * Copyright (c) 1998-2011 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * The contents of this file constitute Original Code as defined in and 7 * are subject to the Apple Public Source License Version 1.1 (the 8 * "License"). You may not use this file except in compliance with the 9 * License. Please obtain a copy of the License at 10 * http://www.apple.com/publicsource and read it before using this file. 11 * 12 * This Original Code and all software distributed under the License are 13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 * License for the specific language governing rights and limitations 18 * under the License. 19 * 20 * @APPLE_LICENSE_HEADER_END@ 21 */ 22/* 23 * IONetworkStack.cpp - An IOKit proxy for the BSD networking stack. 24 * 25 * HISTORY 26 * 27 * IONetworkStack abstracts essential network stack services. These 28 * include registering/unregistering network interfaces, and interface 29 * name space management. 30 * 31 * Only a single IONetworkStack object is instantiated. This object will 32 * register to receive a notification when a network interface object is 33 * first published. The notification handler is responsible for attaching 34 * the network stack object to the interface object as a client. When the 35 * interface is terminated, this linkage is severed. 36 * 37 * This object does not participate in the data/packet flow. The interface 38 * object will interact directly with DLIL to send and to receive packets. 39 */ 40 41extern "C" { 42#include <net/if.h> 43#include <sys/sockio.h> 44} 45 46#include <IOKit/assert.h> 47#include <IOKit/IOLib.h> 48#include <IOKit/IOBSD.h> 49#include <IOKit/IOKitKeys.h> 50#include <IOKit/network/IONetworkInterface.h> 51#include <IOKit/network/IOEthernetController.h> // for setAggressiveness() 52#include "IONetworkStack.h" 53#include "IONetworkDebug.h" 54 55#define super IOService 56OSDefineMetaClassAndFinalStructors( IONetworkStack, IOService ) 57 58#define NIF_VAR(n) ((n)->_clientVar[0]) 59#define NIF_SET(n, x) (NIF_VAR(n) |= (x)) 60#define NIF_CLR(n, x) (NIF_VAR(n) &= ~(x)) 61#define NIF_TEST(n, x) (NIF_VAR(n) & (x)) 62 63#define NIF_CAST(x) ((IONetworkInterface *) x) 64#define NIF_SAFECAST(x) (OSDynamicCast(IONetworkInterface, x)) 65 66#define NIF_NO_BSD_ATTACH(n) ((n)->_clientVar[2]) 67 68#define LOCK() IOLockLock(_stateLock) 69#define UNLOCK() IOLockUnlock(_stateLock) 70 71#define kDetachStateKey "detach state" 72 73static IONetworkStack * gIONetworkStack = 0; 74 75// Flags encoded on the interface object. 76// 77enum { 78 kInterfaceStateInactive = 0x01, // terminated 79 kInterfaceStatePublished = 0x02, // waiting to be named 80 kInterfaceStateNamed = 0x04, // name and unit assigned 81 kInterfaceStateAttaching = 0x08, // will attach to BSD 82 kInterfaceStateAttached = 0x10, // attached to BSD 83 kInterfaceStateAbandoned = 0x20 // failed to attach to BSD 84}; 85 86// IONetworkStackUserClient definition 87// 88#include <IOKit/IOUserClient.h> 89 90class IONetworkStackUserClient : public IOUserClient 91{ 92 OSDeclareFinalStructors( IONetworkStackUserClient ) 93 94protected: 95 IONetworkStack * _provider; 96 97public: 98 virtual bool initWithTask( task_t owningTask, 99 void * securityID, 100 UInt32 type, 101 OSDictionary * properties ); 102 virtual bool start( IOService * provider ); 103 virtual IOReturn clientClose( void ); 104 virtual IOReturn clientDied( void ); 105 virtual IOReturn setProperties( OSObject * properties ); 106}; 107 108//------------------------------------------------------------------------------ 109 110bool IONetworkStack::start( IOService * provider ) 111{ 112 OSDictionary * matching; 113 IOService * rootDomain; 114 const OSSymbol * ucClassName; 115 116 DLOG("IONetworkStack::start(%p) %p\n", provider, this); 117 118 // Only a single IONetworkStack object is created, and a reference 119 // to this object is stored in a global variable. 120 // When the boot process is VERY VERY slow for some unknown reason 121 // we get two instances of IONetworkStack and theassert below fires. 122 // so I am commenting the assert and replacing it with an if statement. 123 // assert( gIONetworkStack == 0 ); 124 125 if (gIONetworkStack) 126 goto fail; 127 128 if (super::start(provider) == false) 129 goto fail; 130 131 _stateLock = IOLockAlloc(); 132 if (!_stateLock) 133 goto fail; 134 135 _ifListNaming = OSSet::withCapacity(8); 136 if (!_ifListNaming) 137 goto fail; 138 139 _ifPrefixDict = OSDictionary::withCapacity(4); 140 if (!_ifPrefixDict) 141 goto fail; 142 143 _asyncThread = thread_call_allocate( 144 OSMemberFunctionCast(thread_call_func_t, this, 145 &IONetworkStack::asyncWork), this); 146 if (!_asyncThread) 147 goto fail; 148 149 _noBSDAttachSymbol = OSSymbol::withCStringNoCopy(kIONetworkNoBSDAttachKey); 150 if (!_noBSDAttachSymbol) 151 goto fail; 152 153 // Call the IOPMrootDomain object, which sits at the root of the 154 // power management hierarchy, to set the default Ethernet WOL 155 // settings. Setting the WOL through setAggressiveness rather 156 // than on each interface object makes it easy to handle an 157 // IOPMSetAggressiveness() call from loginwindow since it will 158 // simply override the default value set here. 159 160 if ((rootDomain = (IOService *) getPMRootDomain())) 161 { 162 rootDomain->IOService::setAggressiveness(kPMEthernetWakeOnLANSettings, 163 kIOEthernetWakeOnMagicPacket | kIOEthernetWakeOnPacketAddressMatch); 164 } 165 166 // Sign up for a notification when a network interface is published. 167 168 matching = serviceMatching(kIONetworkInterfaceClass); 169 if (!matching) 170 goto fail; 171 172 gIONetworkStack = this; 173 174 _ifNotifier = addMatchingNotification( 175 /* type */ gIOPublishNotification, 176 /* match */ matching, 177 /* action */ OSMemberFunctionCast( 178 IOServiceMatchingNotificationHandler, 179 this, &IONetworkStack::interfacePublished), 180 /* target */ this, 181 /* refCon */ this, 182 /* priority */ 1000 ); 183 184 matching->release(); 185 if (!_ifNotifier) 186 goto fail; 187 188 ucClassName = OSSymbol::withCStringNoCopy("IONetworkStackUserClient"); 189 if (ucClassName) 190 { 191 setProperty(gIOUserClientClassKey, (OSObject *) ucClassName); 192 ucClassName->release(); 193 } 194 195 registerService(); 196 return true; 197 198fail: 199 LOG("IONetworkStack::start(%p) %p failed\n", provider, this); 200 return false; 201} 202 203//------------------------------------------------------------------------------ 204 205void IONetworkStack::free( void ) 206{ 207 LOG("IONetworkStack::free() %p\n", this); 208 209 if (this == gIONetworkStack) 210 gIONetworkStack = 0; 211 212 if ( _ifNotifier ) 213 { 214 _ifNotifier->remove(); 215 _ifNotifier = 0; 216 } 217 218 if (_ifPrefixDict) 219 { 220 _ifPrefixDict->release(); 221 _ifPrefixDict = 0; 222 } 223 224 if (_ifListNaming) 225 { 226 _ifListNaming->release(); 227 _ifListNaming = 0; 228 } 229 230 if (_ifListDetach) 231 { 232 _ifListDetach->release(); 233 _ifListDetach = 0; 234 } 235 236 if (_ifListAttach) 237 { 238 _ifListAttach->release(); 239 _ifListAttach = 0; 240 } 241 242 if (_noBSDAttachSymbol) 243 { 244 _noBSDAttachSymbol->release(); 245 _noBSDAttachSymbol = 0; 246 } 247 248 if (_asyncThread) 249 { 250 thread_call_free(_asyncThread); 251 _asyncThread = 0; 252 } 253 254 if (_stateLock) 255 { 256 IOLockFree(_stateLock); 257 _stateLock = 0; 258 } 259 260 super::free(); 261} 262 263//------------------------------------------------------------------------------ 264 265bool IONetworkStack::insertNetworkInterface( IONetworkInterface * netif ) 266{ 267 const char * prefix = netif->getNamePrefix(); 268 OSOrderedSet * set; 269 bool ok = true; 270 271 if (prefix == 0) 272 return false; 273 274 // Look for a Set object associated with the name prefix. 275 276 set = (OSOrderedSet *) _ifPrefixDict->getObject(prefix); 277 278 // If not found, then create one and add it to the dictionary. 279 280 if (!set && ((set = OSOrderedSet::withCapacity(8, orderNetworkInterfaces)))) 281 { 282 ok = _ifPrefixDict->setObject(prefix, set); 283 set->release(); 284 } 285 286 // Add the interface object to the named set. 287 // All objects in a set will have the same name prefix. 288 289 ok = (set && ok) ? set->setObject(netif) : false; 290 291 if (set && (set->getCount() == 0)) 292 { 293 _ifPrefixDict->removeObject(prefix); 294 } 295 296 return ok; 297} 298 299void IONetworkStack::removeNetworkInterface( IONetworkInterface * netif ) 300{ 301 const char * prefix = netif->getNamePrefix(); 302 OSOrderedSet * set; 303 304 if ( prefix ) 305 { 306 set = (OSOrderedSet *) _ifPrefixDict->getObject(prefix); 307 if ( set ) 308 { 309 // Remove interface from set 310 311 set->removeObject(netif); 312 DLOG("IONetworkStack::removeNetworkInterface %s count = %d\n", 313 prefix, set->getCount()); 314 315 // Remove the empty set from the dictionary 316 317 if (set->getCount() == 0) 318 _ifPrefixDict->removeObject(prefix); 319 } 320 } 321} 322 323//------------------------------------------------------------------------------ 324// Get the next available unit number in the set of registered interfaces 325// with the specified prefix. 326 327uint32_t IONetworkStack::getNextAvailableUnitNumber( 328 const char * prefix, 329 uint32_t startingUnit ) 330{ 331 IONetworkInterface * netif; 332 OSOrderedSet * set; 333 334 assert(prefix); 335 336 set = (OSOrderedSet *) _ifPrefixDict->getObject(prefix); 337 netif = set ? NIF_CAST(set->getLastObject()) : 0; 338 339 if (!netif || (netif->getUnitNumber() < startingUnit)) 340 { 341 // The unit number provided is acceptable. 342 } 343 else if (netif->getUnitNumber() == startingUnit) 344 { 345 // Conflict, bump proposed unit number by one. 346 startingUnit++; 347 } 348 else if (set) 349 { 350 for ( uint32_t index = 0; ; index++ ) 351 { 352 netif = NIF_CAST(set->getObject(index)); 353 354 if (!netif || (netif->getUnitNumber() > startingUnit)) 355 break; 356 else if (netif->getUnitNumber() < startingUnit) 357 continue; 358 else /* == */ 359 startingUnit = netif->getUnitNumber() + 1; 360 } 361 } 362 363 return startingUnit; 364} 365 366//------------------------------------------------------------------------------ 367 368bool IONetworkStack::interfacePublished( 369 void * refCon __unused, 370 IOService * service, 371 IONotifier * notifier __unused ) 372{ 373 IONetworkInterface * netif = NIF_SAFECAST(service); 374 bool isNew, ok = false; 375 376 if (!netif) 377 return false; 378 379 DLOG("IONetworkStack::interfacePublished(%p, state 0x%x, parent %d, noattach %d)\n", 380 netif, (uint32_t) NIF_VAR(netif), isParent(netif, gIOServicePlane), 381 (uint32_t) NIF_NO_BSD_ATTACH(netif)); 382 383 isNew = (false == isParent(netif, gIOServicePlane)); 384 if (isNew && !attach(netif)) 385 return false; 386 387 LOCK(); 388 389 do { 390 if (isNew) 391 { 392 // Must be a new network interface 393 if (NIF_VAR(netif) != 0) 394 break; 395 396 // Stop if interface is waiting for a name 397 if (_ifListNaming->containsObject(netif)) 398 { 399 ok = true; 400 break; 401 } 402 403 _ifListNaming->setObject(netif); 404 405 if (netif->getProperty(_noBSDAttachSymbol) == kOSBooleanTrue) 406 { 407 NIF_NO_BSD_ATTACH(netif) = true; 408 } 409 410 // Initialize private interface state 411 NIF_VAR(netif) = kInterfaceStatePublished; 412 ok = true; 413 } 414 else 415 { 416 ok = true; 417 if (NIF_NO_BSD_ATTACH(netif) == false) 418 break; 419 420 // bail if still not allowed to BSD attach 421 if (netif->getProperty(_noBSDAttachSymbol) == kOSBooleanTrue) 422 break; 423 424 // reject invalid interface states 425 if (NIF_TEST(netif, 426 kInterfaceStateInactive | kInterfaceStateAttached | 427 kInterfaceStateAttaching | kInterfaceStateAbandoned )) 428 break; 429 430 NIF_NO_BSD_ATTACH(netif) = false; 431 if (!NIF_TEST(netif, kInterfaceStateNamed)) 432 { 433 // simple case if interface has not received a name yet 434 break; 435 } 436 437 NIF_SET(netif, kInterfaceStateAttaching); 438 if (!_ifListAttach) 439 _ifListAttach = OSArray::withCapacity(1); 440 if (_ifListAttach) 441 { 442 _ifListAttach->setObject(netif); 443 thread_call_enter(_asyncThread); 444 } 445 } 446 } 447 while (false); 448 449 UNLOCK(); 450 451 if (isNew && !ok) 452 { 453 netif->setProperty(kDetachStateKey, NIF_VAR(netif), 32); 454 detach(netif); 455 } 456 457 return ok; 458} 459 460//------------------------------------------------------------------------------ 461 462void IONetworkStack::asyncWork( void ) 463{ 464 IONetworkInterface * d_netif; 465 IONetworkInterface * a_netif; 466 uint32_t varBits; 467 468 while (1) 469 { 470 d_netif = a_netif = 0; 471 472 LOCK(); 473 if (_ifListDetach) 474 { 475 d_netif = NIF_CAST(_ifListDetach->getObject(0)); 476 if (d_netif) 477 { 478 d_netif->retain(); 479 _ifListDetach->removeObject(0); 480 varBits = NIF_VAR(d_netif); 481 } 482 } 483 if (_ifListAttach) 484 { 485 a_netif = NIF_CAST(_ifListAttach->getObject(0)); 486 if (a_netif) 487 { 488 a_netif->retain(); 489 _ifListAttach->removeObject(0); 490 } 491 } 492 UNLOCK(); 493 494 if (!d_netif && !a_netif) 495 break; 496 497 if (d_netif) 498 { 499 DLOG("IONetworkStack::asyncWork detach %s %p, state 0x%x\n", 500 d_netif->getName(), d_netif, varBits); 501 502 // Interface must be named, but may not have attached to BSD 503 504 if (varBits & kInterfaceStateAttached) 505 { 506 // Interface is about to detach from DLIL 507 d_netif->setInterfaceState( 0, kIONetworkInterfaceRegisteredState ); 508 509 // detachFromDataLinkLayer will block until BSD detach is complete 510 d_netif->detachFromDataLinkLayer(0, 0); 511 } 512 513 LOCK(); 514 515 assert(NIF_TEST(d_netif, kInterfaceStateInactive)); 516 assert(NIF_TEST(d_netif, kInterfaceStateNamed)); 517 assert(!NIF_TEST(d_netif, kInterfaceStateAttaching)); 518 519 // Drop interface from list of attached interfaces. 520 // Unit number assigned to interface is up for grabs. 521 522 removeNetworkInterface(d_netif); 523 524 UNLOCK(); 525 526 // Close interface and allow it to proceed with termination 527 d_netif->close( this ); 528 d_netif->release(); 529 } 530 531 if (a_netif) 532 { 533 DLOG("IONetworkStack::asyncWork attach %s %p, state 0x%x\n", 534 a_netif->getName(), a_netif, (uint32_t) NIF_VAR(a_netif)); 535 536 assert(NIF_TEST(a_netif, kInterfaceStateAttaching)); 537 attachNetworkInterfaceToBSD(a_netif); 538 a_netif->release(); 539 } 540 } 541} 542 543//------------------------------------------------------------------------------ 544 545bool IONetworkStack::didTerminate( 546 IOService * provider, IOOptionBits options, bool * defer ) 547{ 548 IONetworkInterface * netif = NIF_SAFECAST(provider); 549 bool wakeThread = false; 550 551 DLOG("IONetworkStack::didTerminate(%s %p state 0x%x, 0x%x)\n", 552 provider->getName(), provider, (uint32_t) options, 553 (uint32_t) NIF_VAR(netif)); 554 555 if (!netif) 556 return true; 557 558 LOCK(); 559 560 do { 561 // Interface has become inactive, it is no longer possible 562 // to open or to attach to the interface object. 563 // Mark the interface as unfit for naming / BSD attach. 564 565 NIF_SET(netif, kInterfaceStateInactive); 566 _ifListNaming->removeObject(netif); 567 568 // Interface is attaching to BSD. Postpone termination until 569 // the attach is complete. 570 571 if (NIF_TEST(netif, kInterfaceStateAttaching)) 572 break; 573 574 // If interface was never named or attached to BSD, we are done 575 // since we don't have an open on the interface. 576 577 if (NIF_TEST(netif, kInterfaceStateAttached) || 578 NIF_TEST(netif, kInterfaceStateNamed)) 579 { 580 // Detach interface from BSD asynchronously. 581 // The interface termination will be waiting for our close. 582 583 if (!_ifListDetach) 584 _ifListDetach = OSArray::withCapacity(8); 585 if (_ifListDetach) 586 { 587 _ifListDetach->setObject(netif); 588 wakeThread = true; 589 } 590 } 591 } 592 while ( false ); 593 594 UNLOCK(); 595 596 if (wakeThread) 597 thread_call_enter(_asyncThread); 598 599 return true; 600} 601 602//------------------------------------------------------------------------------ 603 604bool IONetworkStack::reserveInterfaceUnitNumber( 605 IONetworkInterface * netif, 606 uint32_t unit, 607 bool isUnitFixed, 608 bool * attachToBSD ) 609{ 610 const char * prefix = netif->getNamePrefix(); 611 uint32_t inUnit = unit; 612 bool opened = false; 613 bool ok = false; 614 615 DLOG("IONetworkStack::reserveInterfaceUnitNumber(%p, %s, %u)\n", 616 netif, prefix ? prefix : "", unit); 617 618 *attachToBSD = false; 619 620 LOCK(); 621 622 // netif retained by caller 623 _ifListNaming->removeObject(netif); 624 625 do { 626 if (!prefix) 627 { 628 LOG("interface name prefix is null\n"); 629 break; 630 } 631 632 // Interface must be in the published state. 633 634 if (NIF_VAR(netif) != kInterfaceStatePublished) 635 { 636 LOG("unable to name interface in state 0x%x as %s%u\n", 637 (uint32_t) NIF_VAR(netif), prefix, inUnit); 638 break; 639 } 640 641 // The unit argument provided is a hint to indicate the lowest unit 642 // number that can be assigned to the interface. We are allowed to 643 // increment the unit number provided if the number is already 644 // taken. 645 646 unit = getNextAvailableUnitNumber(prefix, unit); 647 if ((isUnitFixed == true) && (unit != inUnit)) 648 { 649 LOG("interface name %s%u is unavailable\n", prefix, inUnit); 650 break; 651 } 652 653 // Open the interface object. This will fail if the interface 654 // object has become inactive. 655 656 UNLOCK(); 657 ok = netif->open(this); 658 LOCK(); 659 660 if (!ok) 661 { 662 LOG("interface %s%u open failed\n", prefix, inUnit); 663 break; 664 } 665 opened = true; 666 ok = false; 667 668 // Must not reserve an unit number or attempt to BSD attach 669 // if preempted by interface termination. 670 671 if (NIF_TEST(netif, kInterfaceStateInactive)) 672 { 673 LOG("interface %s%u became inactive\n", prefix, inUnit); 674 break; 675 } 676 677 // Update interface unit and add the interface to the named 678 // collection to reserve its assigned unit number. 679 680 if ((netif->setUnitNumber(unit) == false) || 681 (insertNetworkInterface(netif) == false)) 682 { 683 LOG("interface %s%u name assigment failed\n", prefix, inUnit); 684 break; 685 } 686 687 ok = true; 688 } 689 while ( false ); 690 691 if (ok) 692 { 693 NIF_SET(netif, kInterfaceStateNamed); 694 if (NIF_NO_BSD_ATTACH(netif) == false) 695 { 696 NIF_SET(netif, kInterfaceStateAttaching); 697 *attachToBSD = true; 698 } 699 } 700 701 UNLOCK(); 702 703 if (!ok && opened) 704 { 705 netif->close(this); 706 } 707 708 return ok; 709} 710 711//------------------------------------------------------------------------------ 712 713IOReturn IONetworkStack::attachNetworkInterfaceToBSD( IONetworkInterface * netif ) 714{ 715 bool attachOK = false; 716 bool detachWakeup = false; 717 bool pingMatching = false; 718 char ifname[32]; 719 IOReturn result; 720 721 assert( netif ); 722 if ((result = netif->attachToDataLinkLayer(0, 0)) == kIOReturnSuccess) 723 { 724 // Hack to sync up the interface flags. The UP flag may already 725 // be set, and this will issue an SIOCSIFFLAGS to the interface. 726 727 ifnet_ioctl(netif->getIfnet(), 0, SIOCSIFFLAGS, 0); 728 729 // Interface is now attached to BSD. 730 netif->setInterfaceState( kIONetworkInterfaceRegisteredState ); 731 732 // Add a kIOBSDNameKey property to the interface AFTER the interface 733 // has attached to BSD. The order is very important to avoid rooting 734 // from an interface which is not yet known by BSD. 735 736 snprintf(ifname, sizeof(ifname), "%s%u", 737 netif->getNamePrefix(), netif->getUnitNumber()); 738 netif->setProperty(kIOBSDNameKey, ifname); 739 attachOK = true; 740 } 741 742 // Update state bits and detect for untimely interface termination. 743 744 LOCK(); 745 assert(NIF_TEST(netif, kInterfaceStateNamed)); 746 assert(( NIF_VAR(netif) & 747 ( kInterfaceStateAttaching | kInterfaceStateAttached )) == 748 kInterfaceStateAttaching ); 749 NIF_CLR( netif, kInterfaceStateAttaching ); 750 751 if (attachOK) 752 { 753 NIF_SET( netif, kInterfaceStateAttached ); 754 pingMatching = true; 755 756 if (NIF_TEST(netif, kInterfaceStateInactive)) 757 { 758 if (!_ifListDetach) 759 _ifListDetach = OSArray::withCapacity(8); 760 if (_ifListDetach) 761 { 762 _ifListDetach->setObject(netif); 763 detachWakeup = true; 764 } 765 pingMatching = false; 766 } 767 } 768 else 769 { 770 // BSD attach failed, drop from list of attached interfaces 771 removeNetworkInterface(netif); 772 NIF_SET(netif, kInterfaceStateAbandoned); 773 } 774 775 UNLOCK(); 776 777 if (!attachOK) 778 { 779 netif->setProperty(kDetachStateKey, NIF_VAR(netif), 32); 780 netif->close( this ); 781 detach(netif); 782 } 783 784 if (detachWakeup) 785 { 786 // In the event that an interface was terminated while attaching 787 // to BSD, re-schedule the BSD detach and interface close. 788 thread_call_enter(_asyncThread); 789 } 790 791 if (pingMatching) 792 { 793 // Re-register interface after setting kIOBSDNameKey. 794 netif->registerService(); 795 } 796 797 return result; 798} 799 800//------------------------------------------------------------------------------ 801 802IOReturn IONetworkStack::registerAllNetworkInterfaces( void ) 803{ 804 IONetworkInterface * netif; 805 OSSet * list; 806 bool attachToBSD; 807 808 LOCK(); 809 810 if (!_ifListNaming || (_ifListNaming->getCount() == 0)) 811 { 812 UNLOCK(); 813 return kIOReturnSuccess; 814 } 815 816 list = OSSet::withSet( _ifListNaming ); 817 818 UNLOCK(); 819 820 if (list == 0) 821 { 822 return kIOReturnNoMemory; 823 } 824 825 while ((netif = NIF_CAST(list->getAnyObject()))) 826 { 827 if (reserveInterfaceUnitNumber( netif, 0, false, &attachToBSD ) && 828 attachToBSD) 829 attachNetworkInterfaceToBSD( netif ); 830 831 list->removeObject(netif); 832 } 833 834 list->release(); 835 836 return kIOReturnSuccess; 837} 838 839//------------------------------------------------------------------------------ 840 841IOReturn IONetworkStack::registerNetworkInterface( 842 IONetworkInterface * netif, 843 uint32_t unit, 844 bool isUnitFixed ) 845{ 846 IOReturn result = kIOReturnNoSpace; 847 bool attachToBSD = false; 848 849 if (reserveInterfaceUnitNumber( netif, unit, isUnitFixed, &attachToBSD )) 850 { 851 result = (attachToBSD) ? attachNetworkInterfaceToBSD( netif ) : 852 kIOReturnSuccess; 853 } 854 855 return result; 856} 857 858//------------------------------------------------------------------------------ 859// Registered interfaces are ordered by their assigned unit number. Those with 860// larger unit numbers will be placed behind those with smaller unit numbers. 861// This ordering makes it easier to hunt for an available unit number slot for 862// a new interface. 863 864SInt32 IONetworkStack::orderNetworkInterfaces( 865 const OSMetaClassBase * obj1, 866 const OSMetaClassBase * obj2, 867 void * ref ) 868{ 869 const IONetworkInterface * netif1 = (const IONetworkInterface *) obj1; 870 const IONetworkInterface * netif2 = (const IONetworkInterface *) obj2; 871 872 assert( netif1 && netif2 ); 873 return (netif2->getUnitNumber() - netif1->getUnitNumber()); 874} 875 876//------------------------------------------------------------------------------ 877 878IOReturn IONetworkStack::setProperties( OSObject * properties ) 879{ 880 IONetworkInterface * netif = 0; 881 OSDictionary * dict = OSDynamicCast(OSDictionary, properties); 882 OSString * path; 883 OSNumber * num; 884 OSNumber * unit; 885 OSData * data; 886 uint32_t cmdType; 887 IOReturn error = kIOReturnBadArgument; 888 889 do { 890 if (!dict) 891 break; 892 893 // [optional] Type of interface naming operation 894 // IORegisterNetworkInterface() does not set this for netboot case. 895 896 num = OSDynamicCast( OSNumber, 897 dict->getObject(kIONetworkStackUserCommandKey)); 898 if (num) 899 cmdType = num->unsigned32BitValue(); 900 else 901 cmdType = kIONetworkStackRegisterInterfaceWithLowestUnit; 902 903 if (kIONetworkStackRegisterInterfaceAll == cmdType) 904 { 905 error = registerAllNetworkInterfaces(); 906 break; 907 } 908 909 // [required] Interface unit number 910 unit = OSDynamicCast(OSNumber, dict->getObject(kIOInterfaceUnit)); 911 if (!unit) 912 break; 913 914 // [optional] Registry entry ID for interface object 915 data = OSDynamicCast(OSData, dict->getObject(kIORegistryEntryIDKey)); 916 917 // [optional] Device path to interface objecy 918 path = OSDynamicCast(OSString, dict->getObject(kIOPathMatchKey)); 919 920 if (data && (data->getLength() == sizeof(uint64_t))) 921 { 922 OSDictionary * matching; 923 OSIterator * iter; 924 uint64_t entryID = *(uint64_t *) data->getBytesNoCopy(); 925 926 matching = registryEntryIDMatching(entryID); 927 if (!matching) 928 { 929 error = kIOReturnNoMemory; 930 break; 931 } 932 933 iter = getMatchingServices(matching); 934 matching->release(); 935 if (!iter) 936 { 937 error = kIOReturnNotFound; 938 break; 939 } 940 941 if (iter) 942 { 943 netif = OSDynamicCast(IONetworkInterface, iter->getNextObject()); 944 if (netif) 945 netif->retain(); 946 iter->release(); 947 } 948 } 949 else if (path) 950 { 951 IORegistryEntry * entry; 952 953 entry = IORegistryEntry::fromPath(path->getCStringNoCopy()); 954 if (entry && OSDynamicCast(IONetworkInterface, entry)) 955 netif = (IONetworkInterface *) entry; 956 else if (entry) 957 entry->release(); 958 } 959 else 960 { 961 // no path nor registry entry ID provided 962 break; 963 } 964 965 if (!netif) 966 { 967 error = kIOReturnNoDevice; 968 break; 969 } 970 971 switch ( cmdType ) 972 { 973 case kIONetworkStackRegisterInterfaceWithUnit: 974 error = registerNetworkInterface( 975 netif, 976 unit->unsigned32BitValue(), 977 true /* fixedUnit */ ); 978 break; 979 980 case kIONetworkStackRegisterInterfaceWithLowestUnit: 981 error = registerNetworkInterface( 982 netif, 983 unit->unsigned32BitValue(), 984 false /* fixedUnit */ ); 985 break; 986 987 default: 988 error = kIOReturnUnsupported; 989 break; 990 } 991 } while (false); 992 993 if (netif) 994 netif->release(); 995 996 return error; 997} 998 999//------------------------------------------------------------------------------ 1000// IONetworkStackUserClient 1001 1002#undef super 1003#define super IOUserClient 1004OSDefineMetaClassAndFinalStructors( IONetworkStackUserClient, IOUserClient ) 1005 1006bool IONetworkStackUserClient::initWithTask( task_t owningTask, 1007 void * securityID, 1008 UInt32 type, 1009 OSDictionary * properties ) 1010{ 1011 if (!super::initWithTask(owningTask, securityID, type, properties)) 1012 return false; 1013 1014 if (IOUserClient::clientHasPrivilege( 1015 securityID, kIOClientPrivilegeAdministrator) != kIOReturnSuccess) 1016 return false; 1017 1018 return true; 1019} 1020 1021bool IONetworkStackUserClient::start( IOService * provider ) 1022{ 1023 if ( super::start(provider) == false ) 1024 return false; 1025 1026 if ( provider->open(this) == false ) 1027 return false; 1028 1029 _provider = OSDynamicCast(IONetworkStack, provider); 1030 if (!_provider) 1031 { 1032 provider->close(this); 1033 return false; 1034 } 1035 1036 return true; 1037} 1038 1039IOReturn IONetworkStackUserClient::clientClose( void ) 1040{ 1041 if (_provider) 1042 { 1043 _provider->close(this); 1044 detach(_provider); 1045 } 1046 return kIOReturnSuccess; 1047} 1048 1049IOReturn IONetworkStackUserClient::clientDied( void ) 1050{ 1051 return clientClose(); 1052} 1053 1054IOReturn IONetworkStackUserClient::setProperties( OSObject * properties ) 1055{ 1056 if (kIOReturnSuccess != IOUserClient::clientHasPrivilege( 1057 current_task(), kIOClientPrivilegeAdministrator)) 1058 { 1059 return kIOReturnNotPrivileged; 1060 } 1061 1062 return ( _provider ) ? 1063 _provider->setProperties( properties ) : 1064 kIOReturnNotReady; 1065} 1066