|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1998-2000 Apple Computer, 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: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 24: * ! 25: * IONetworkStack.cpp - An IOKit proxy for the BSD network stack. ! 26: * ! 27: * HISTORY ! 28: * ! 29: * IONetworkStack abstracts certain essential network stack services. ! 30: * Those services include attaching/detaching network interfaces, and ! 31: * interface naming. Note that although BSD network stack does not assign ! 32: * interface names, it is the responsibility of this object to manage the ! 33: * interface name space. ! 34: * ! 35: * IONetworkStack is a client of IONetworkInterface. This object uses the ! 36: * standard IOKit matching mechanism to discover and attach to interface ! 37: * objects. Each interface object is expected to have only a single ! 38: * IONetworkStack client. Under IOKit, the stack object initiates the ! 39: * action to attach to an interface. And subsequently, detaches from an ! 40: * interface when signaled to do so. ! 41: * ! 42: * The packet flow bypasses this object for efficiency sake. The interface ! 43: * object interact directly with the 'real' network stack to send and ! 44: * receive packets. ! 45: */ ! 46: ! 47: #include <IOKit/assert.h> ! 48: #include <IOKit/IOLib.h> ! 49: #include <IOKit/IOBSD.h> ! 50: #include <IOKit/IOMessage.h> ! 51: #include <IOKit/network/IONetworkInterface.h> ! 52: #include <IOKit/network/IONetworkController.h> ! 53: #include "IONetworkStack.h" ! 54: ! 55: extern "C" { ! 56: #include <sys/param.h> ! 57: #include <sys/mbuf.h> ! 58: #include <sys/socket.h> ! 59: #include <net/bpf.h> ! 60: #include <net/if.h> ! 61: #include <netinet/if_ether.h> ! 62: } ! 63: ! 64: #define super IOService ! 65: ! 66: OSDefineMetaClassAndStructorsWithInit( IONetworkStack, ! 67: IOService, ! 68: IONetworkStack::initialize()) ! 69: ! 70: #ifdef DEBUG ! 71: #define DLOG(fmt, args...) IOLog(fmt, ## args) ! 72: #else ! 73: #define DLOG ! 74: #endif ! 75: ! 76: // Maintain a linked list of network interfaces. ! 77: // Each time a new interface is added, an unit number is assigned, ! 78: // and an interface entry is added to the list. When the interface ! 79: // goes away, the entry is removed from the list and deallocated. ! 80: // ! 81: static queue_head_t netifTable; ! 82: static IOLock * netifTableLock; ! 83: ! 84: typedef struct { ! 85: IONetworkInterface * netif; ! 86: const char * name; ! 87: short unit; ! 88: queue_chain_t link; ! 89: } netifEntry; ! 90: ! 91: #define BSD_IFNET_ENTRY ((IONetworkInterface *) 0) ! 92: #define NETIF_LOCK IOTakeLock(netifTableLock) ! 93: #define NETIF_UNLOCK IOUnlock(netifTableLock) ! 94: ! 95: #define LOCK IOTakeLock(_lock); ! 96: #define UNLOCK IOUnlock(_lock); ! 97: ! 98: // -------------------------------------------------------------------------- ! 99: // ! 100: // Add a new entry to the netifTable for the interface 'netif'. ! 101: // Return true if the entry was added successfully, otherwise ! 102: // returns false. ! 103: // ! 104: // The table lock must be held by the caller of this function. ! 105: // ! 106: static bool addNetworkInterfaceEntry(IONetworkInterface * netif, ! 107: const char * name, ! 108: short unit) ! 109: { ! 110: if (!netif || !name || (unit < 0)) return false; ! 111: ! 112: netifEntry * entry = (netifEntry *) IOMalloc(sizeof(netifEntry)); ! 113: if (!entry) ! 114: return false; ! 115: bzero(entry, sizeof(*entry)); ! 116: ! 117: entry->netif = netif; ! 118: entry->unit = unit; ! 119: entry->name = name; ! 120: ! 121: queue_enter(&netifTable, entry, netifEntry *, link); ! 122: ! 123: return true; ! 124: } ! 125: ! 126: // -------------------------------------------------------------------------- ! 127: // ! 128: // Release the table entry occupied by the 'netif' instance. ! 129: // Returns true if an entry was found and removed, otherwise ! 130: // return false. ! 131: // ! 132: static bool releaseNetworkInterfaceEntry(IONetworkInterface * netif) ! 133: { ! 134: netifEntry * foundEntry = 0; ! 135: ! 136: if (!netif) return false; ! 137: ! 138: NETIF_LOCK; ! 139: if (!queue_empty(&netifTable)) { ! 140: netifEntry * entry; ! 141: queue_iterate(&netifTable, entry, netifEntry *, link) { ! 142: if (entry->netif == netif) { ! 143: foundEntry = entry; ! 144: break; ! 145: } ! 146: } ! 147: } ! 148: if (foundEntry) { ! 149: queue_remove(&netifTable, foundEntry, netifEntry *, link); ! 150: IOFree(foundEntry, sizeof(*foundEntry)); ! 151: } ! 152: NETIF_UNLOCK; ! 153: ! 154: return (foundEntry ? true : false); ! 155: } ! 156: ! 157: // -------------------------------------------------------------------------- ! 158: // ! 159: // Initialize the table, and preload it with any existing BSD network ! 160: // interfaces. ! 161: // ! 162: static void initNetifTable() ! 163: { ! 164: netifTableLock = IOLockAlloc(); ! 165: assert(netifTableLock); ! 166: ! 167: IOLockInitWithState(netifTableLock, kIOLockStateUnlocked); ! 168: ! 169: queue_init(&netifTable); ! 170: ! 171: // Insert entries for all existing 'BSD' network interfaces into the ! 172: // netifTable. Hopefully only lo0 will be found. ! 173: // ! 174: #if 1 // FreeBSD 3.2 ! 175: for (struct ifnet * ifp = ifnet.tqh_first; ! 176: ifp; ! 177: ifp = ifp->if_link.tqe_next) ! 178: addNetworkInterfaceEntry(BSD_IFNET_ENTRY, ifp->if_name, ifp->if_unit); ! 179: #else ! 180: for (struct ifnet * ifp = ifnet; ifp; ifp = ifp->if_next) ! 181: addNetworkInterfaceEntry(BSD_IFNET_ENTRY, ifp->if_name, ifp->if_unit); ! 182: #endif ! 183: } ! 184: ! 185: // -------------------------------------------------------------------------- ! 186: // ! 187: // Add a entry for the interface object 'netif', with name prefix 'name'. ! 188: // The chosen unit number is returned in 'unit'. Returns true on success. ! 189: // ! 190: static bool reserveNetworkInterfaceEntry(IONetworkInterface * netif, ! 191: const char * name, ! 192: short * unit) ! 193: { ! 194: bool ret = true; ! 195: bool addEntry = true; // add new entry to list. ! 196: bool error = false; ! 197: ! 198: if (!netif || !name || !unit || (*unit < 0)) return false; ! 199: ! 200: NETIF_LOCK; ! 201: ! 202: if (!queue_empty(&netifTable)) { ! 203: bool rescan; ! 204: netifEntry * entry; ! 205: ! 206: do { ! 207: rescan = false; ! 208: ! 209: // Scan through the interface list and search for duplicates ! 210: // and conflicts. If a conflict is found, increment the unit ! 211: // number and rescan. ! 212: // ! 213: queue_iterate(&netifTable, entry, netifEntry *, link) { ! 214: if (entry->netif == netif) { // can't have duplicates ! 215: addEntry = false; // re-use existing entry ! 216: *unit = entry->unit; ! 217: break; ! 218: } ! 219: if ((entry->unit == *unit) && !strcmp(entry->name, name)) { ! 220: // name conflict detected. ! 221: if (++(*unit) > 0) ! 222: rescan = true; ! 223: else ! 224: error = true; ! 225: break; ! 226: } ! 227: } ! 228: } while (rescan); ! 229: } ! 230: ! 231: if (error) ! 232: ret = false; ! 233: else if (addEntry) ! 234: ret = addNetworkInterfaceEntry(netif, name, *unit); ! 235: ! 236: NETIF_UNLOCK; ! 237: ! 238: return ret; ! 239: } ! 240: ! 241: // -------------------------------------------------------------------------- ! 242: // ! 243: // IONetworkStack class initializer. ! 244: ! 245: void IONetworkStack::initialize() ! 246: { ! 247: initNetifTable(); ! 248: } ! 249: ! 250: // -------------------------------------------------------------------------- ! 251: // ! 252: // init method. ! 253: ! 254: bool IONetworkStack::init(OSDictionary * properties) ! 255: { ! 256: _netif = 0; // IONetworkInterface instance (provider). ! 257: _ifp = 0; // ifnet struct for the interface. ! 258: _lock = 0; // big serialization lock. ! 259: _state = kIONetworkStackStateInit; // default state. ! 260: ! 261: if (!super::init()) ! 262: return false; ! 263: ! 264: // Allocate a lock which will protect all accesses to this object. ! 265: // ! 266: _lock = IOLockAlloc(); ! 267: if (!_lock) ! 268: return false; ! 269: ! 270: return true; ! 271: } ! 272: ! 273: // -------------------------------------------------------------------------- ! 274: // ! 275: // probe. the score forces the probe and start in IONetworkStack to occur ! 276: // before the notification from IONetworkInterface is sent. We need to delay ! 277: // that until the network stack object has assigned a BSD name to the ! 278: // interface. ! 279: ! 280: IOService * IONetworkStack::probe(IOService * provider, ! 281: SInt32 * score) ! 282: { ! 283: if (!super::probe(provider, score)) ! 284: return 0; ! 285: ! 286: // We are not picky about our provider, but it must be an ! 287: // IONetworkInterface instance. ! 288: // ! 289: IONetworkInterface * netif = OSDynamicCast(IONetworkInterface, provider); ! 290: if (!netif) ! 291: return 0; ! 292: ! 293: *score = 32; // must be larger than notification score. ! 294: ! 295: // Query interface for any requirements before qualifying the probe. ! 296: // For now, there is nothing that needs to be done. Return 'this' to ! 297: // indicate successful probe. ! 298: ! 299: return this; ! 300: } ! 301: ! 302: // -------------------------------------------------------------------------- ! 303: // ! 304: // start method. We have attached to our provider, now start ourselve up. ! 305: ! 306: bool IONetworkStack::start(IOService * provider) ! 307: { ! 308: IONetworkInterface * netif = OSDynamicCast(IONetworkInterface, provider); ! 309: bool ret = false; ! 310: bool opened = false; ! 311: ! 312: if (!netif) return false; ! 313: ! 314: LOCK; ! 315: ! 316: do { ! 317: // Catch illegal state transitions. ! 318: // ! 319: if (_state != kIONetworkStackStateInit) ! 320: break; ! 321: ! 322: // Our provider must reveal its ifnet structure. ! 323: // ! 324: _netif = netif; ! 325: _ifp = _netif->getIfnet(); ! 326: if (!_ifp || (_netif != (IONetworkInterface *) _ifp->if_private)) ! 327: break; ! 328: ! 329: // Pass start() to our superclass. ! 330: // ! 331: if (!super::start(provider)) ! 332: break; ! 333: ! 334: // Open our provider. ! 335: // ! 336: if (!_netif->open(this)) ! 337: break; ! 338: opened = true; ! 339: ! 340: // Assign a name for the interface. Must do this before the ! 341: // if_attach() call. Remember to release the OSString object ! 342: // obtained through this call. ! 343: // ! 344: OSString * ifname = _assignInterfaceName(_netif); ! 345: if (!ifname) { ! 346: releaseNetworkInterfaceEntry(_netif); ! 347: break; ! 348: } ! 349: ifname->release(); ! 350: ! 351: // When IONetworkStack gets probed, we assume that BSD is already ! 352: // up and running. So it is safe to call BSD to attach the network ! 353: // interface. ! 354: // ! 355: // FIXME: This will only work with Ethernet interfaces. Switch to ! 356: // new DLIL API once that is available. ! 357: // ! 358: _netif->lock(); ! 359: ! 360: // Set the if_free() function pointer in the ifnet to point to our ! 361: // detachCallBack() static function. ! 362: // ! 363: // _ifp->if_free = detachCallBackHandler; ! 364: // _netif->_stack = this; ! 365: ! 366: #if 1 // FreeBSD 3.2 ! 367: bpfattach(_ifp, DLT_EN10MB,sizeof(struct ether_header)); ! 368: #else ! 369: bpfattach(&_ifp->if_bpf, _ifp, DLT_EN10MB,sizeof(struct ether_header)); ! 370: #endif ! 371: ! 372: ether_ifattach(_ifp); ! 373: ! 374: _netif->unlock(); ! 375: ! 376: // Network stack is now attached to the interface. ! 377: // ! 378: _state = kIONetworkStackStateAttached; ! 379: ! 380: ret = true; ! 381: } ! 382: while (0); ! 383: ! 384: if (!ret) ! 385: { ! 386: // start failed, undo any actions performed. ! 387: // ! 388: if (opened) ! 389: _netif->close(this); ! 390: ! 391: _netif = 0; ! 392: _ifp = 0; ! 393: } ! 394: ! 395: UNLOCK; ! 396: ! 397: return ret; ! 398: } ! 399: ! 400: // -------------------------------------------------------------------------- ! 401: // ! 402: // stop method. ! 403: ! 404: void IONetworkStack::stop(IOService * provider) ! 405: { ! 406: LOCK; ! 407: ! 408: // Catch an illegal stop. ! 409: // ! 410: assert((_state == kIONetworkStackStateInit) || ! 411: (_state == kIONetworkStackStateDetached)); ! 412: ! 413: // Remove the interface from linked list. ! 414: // ! 415: if (_netif) { ! 416: assert(_netif == (IONetworkInterface *) provider); ! 417: releaseNetworkInterfaceEntry(_netif); ! 418: } ! 419: ! 420: _netif = 0; ! 421: _ifp = 0; ! 422: _state = kIONetworkStackStateInit; ! 423: ! 424: UNLOCK; ! 425: ! 426: super::stop(provider); ! 427: } ! 428: ! 429: // -------------------------------------------------------------------------- ! 430: // ! 431: // sendIfDetachRequest ! 432: // ! 433: // Handle a detach request from our provider and signal to the network stack ! 434: // that the interface wishes to detach. The network stack will callback when ! 435: // the interface is allowed to proceed with the detach. There is no hard ! 436: // limit on how soon the callback will occur. ! 437: // ! 438: // Returns true if the request was handled. Otherwise, returns false. ! 439: ! 440: bool IONetworkStack::sendIfDetachRequest() ! 441: { ! 442: bool ret = false; ! 443: ! 444: DLOG("IONetworkStack::sendIfDetachRequest() called state = %d\n", _state); ! 445: ! 446: LOCK; ! 447: ! 448: if (_state == kIONetworkStackStateAttached) { ! 449: ! 450: // Send a detach request to the network stack and wait for ! 451: // a callback indicating detach operation complete. ! 452: // ! 453: // if_detach() is a new proposed DLIL call and does not exist yet. ! 454: ! 455: _state = kIONetworkStackStateDetaching; ! 456: ! 457: ret = true; // detach request handled. ! 458: } ! 459: ! 460: UNLOCK; ! 461: ! 462: return ret; ! 463: } ! 464: ! 465: // -------------------------------------------------------------------------- ! 466: // ! 467: // ifDetachCallback method. ! 468: ! 469: void IONetworkStack::ifDetachCallback() ! 470: { ! 471: LOCK; ! 472: ! 473: if (_state == kIONetworkStackStateDetaching) { ! 474: ! 475: // We previously sent a detach request, the network stack is now ! 476: // calling back to indicate detach completion. ! 477: // ! 478: assert(_netif && _ifp); ! 479: ! 480: // Close our provider. ! 481: // ! 482: _netif->close(this); ! 483: ! 484: // Detach is now complete. ! 485: // ! 486: _state = kIONetworkStackStateDetached; ! 487: } ! 488: else { ! 489: DLOG("%s: Unexpected detach callback\n", getName()); ! 490: } ! 491: ! 492: UNLOCK; ! 493: } ! 494: ! 495: // -------------------------------------------------------------------------- ! 496: // ! 497: // This static member function is registered as the if_free() handler in ! 498: // the ifnet structure of our provider. The IONetworkStack instance is ! 499: // discovered and its ifFreeCallback() method is called. ! 500: ! 501: void IONetworkStack::ifDetachCallbackHandler(struct ifnet * ifp) ! 502: { ! 503: IONetworkInterface * netif; ! 504: IONetworkStack * stack; ! 505: ! 506: netif = OSDynamicCast(IONetworkInterface, ! 507: (IONetworkInterface *) ifp->if_private); ! 508: assert(netif); ! 509: ! 510: netif->lockForArbitration(); ! 511: ! 512: stack = (IONetworkStack *) netif->_client; ! 513: if (stack) ! 514: stack->ifDetachCallback(); ! 515: else ! 516: DLOG("IONetworkStack: No target for ifDetachCallback\n"); ! 517: ! 518: netif->unlockForArbitration(); ! 519: } ! 520: ! 521: // -------------------------------------------------------------------------- ! 522: // ! 523: // Release allocated resources. ! 524: ! 525: void IONetworkStack::free() ! 526: { ! 527: assert(_state == kIONetworkStackStateInit); ! 528: ! 529: if (_lock) ! 530: IOLockFree(_lock); ! 531: } ! 532: ! 533: // -------------------------------------------------------------------------- ! 534: // ! 535: // Facility provided by IOService for general purpose provider-to-client ! 536: // notification. We catch the kIOMessageServiceIsTerminated message. ! 537: ! 538: IOReturn IONetworkStack::message(UInt32 type, IOService * provider, ! 539: void * argument = 0) ! 540: { ! 541: // Our provider has gone into an inactive state, we should begin the ! 542: // tear-down process by signalling the network stack to unregister ! 543: // and detach the network interface. ! 544: // ! 545: // We do not look at the argument, which contains the options given ! 546: // to the terminate() method. ! 547: // ! 548: if (type == kIOMessageServiceIsTerminated) { ! 549: sendIfDetachRequest(); ! 550: return kIOReturnSuccess; ! 551: } ! 552: ! 553: return kIOReturnUnsupported; ! 554: } ! 555: ! 556: // -------------------------------------------------------------------------- ! 557: // ! 558: // Assign a BSD friendly name to the network interface. The interface ! 559: // object has to assist in this process by returning its name prefix, ! 560: // i.e. "en". This routine will pick an unit number that does not ! 561: // conflict with any existing interface. ! 562: ! 563: OSString * IONetworkStack::_assignInterfaceName(IONetworkInterface * netif) ! 564: { ! 565: SInt16 unit = 0; ! 566: UInt32 index = 0; ! 567: const char * namePrefix = netif->getNamePrefix(); ! 568: char nameBuf[40]; ! 569: OSString * nameString; ! 570: IONetworkController * ctlr = OSDynamicCast(IONetworkController, ! 571: netif->getProvider()); ! 572: ! 573: if (!ctlr || !namePrefix || !*namePrefix) ! 574: return 0; ! 575: ! 576: // First, we need to determine the initial interface unit number. ! 577: // The current scheme needs a lot of work. Currently, motherboard ! 578: // devices gets unit 0, while add-on PCI cards are assigned ! 579: // unit 1 and up. Here, we need to determine whether this is an ! 580: // onboard or a PCI network controller. ! 581: // ! 582: if (ctlr->getProvider()) { ! 583: OSObject * propObject = ctlr->getProvider()->getProperty("built-in"); ! 584: ! 585: if (!propObject) { ! 586: propObject = ctlr->getProvider()->getProperty("AAPL,slot-name"); ! 587: if (propObject) { ! 588: unit = 1; // PCI add-on card ! 589: ! 590: // If we have an index number, increment ! 591: // the unit by the index number. ! 592: // (for multiport PCI cards). ! 593: ctlr->doGetControllerIndex(this, &index); ! 594: unit += index; ! 595: } ! 596: } ! 597: } ! 598: ! 599: // "unit" is now the initial unit number requested by the interface. ! 600: // If this unit number is already taken by an existing interface, we ! 601: // will automatically increment the unit number until there are no ! 602: // conflicts. We don't want to confuse BSD with identical names. ! 603: // ! 604: // Now try to reserve the chosen name. ! 605: // ! 606: if (!reserveNetworkInterfaceEntry(netif, namePrefix, &unit)) ! 607: return 0; ! 608: ! 609: // Update the interface object with its assigned name. ! 610: // ! 611: sprintf(nameBuf, "%s%d", namePrefix, unit); ! 612: nameString = OSString::withCString(nameBuf); ! 613: if (nameString) { ! 614: // ! 615: // Now fill in the ifnet name fields. ! 616: // ! 617: netif->setInterfaceNameInt(namePrefix); ! 618: netif->setUnitNumberInt(unit); ! 619: ! 620: // Set the interface's kIOBSDName property. ! 621: // ! 622: netif->setProperty(kIOBSDName, nameString); ! 623: } ! 624: ! 625: return nameString; ! 626: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.