|
|
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: * IONetworkInterface.cpp ! 26: * ! 27: * HISTORY ! 28: * 8-Jan-1999 Joe Liu (jliu) created. ! 29: * ! 30: */ ! 31: ! 32: #include <IOKit/assert.h> ! 33: #include <IOKit/IOLib.h> ! 34: #include <IOKit/IOMessage.h> ! 35: #include <IOKit/network/IONetworkInterface.h> ! 36: #include <IOKit/network/IONetworkController.h> ! 37: #include <IOKit/network/IONetworkUserClient.h> ! 38: ! 39: extern "C" { ! 40: #include <sys/param.h> ! 41: #include <sys/mbuf.h> ! 42: #include <sys/socket.h> ! 43: #include <sys/sockio.h> ! 44: #include <net/bpf.h> ! 45: #include <net/if.h> ! 46: #include <netinet/if_ether.h> ! 47: #include <net/if_media.h> ! 48: #include <net/dlil.h> ! 49: int copyout(void *kaddr, void *udaddr, size_t len); ! 50: } ! 51: ! 52: //--------------------------------------------------------------------------- ! 53: ! 54: #define super IOService ! 55: ! 56: OSDefineMetaClass( IONetworkInterface, IOService ) ! 57: OSDefineAbstractStructors( IONetworkInterface, IOService ) ! 58: ! 59: //--------------------------------------------------------------------------- ! 60: // Macros ! 61: ! 62: #ifdef DEBUG ! 63: #define DLOG(fmt, args...) IOLog(fmt, ## args) ! 64: #else ! 65: #define DLOG ! 66: #endif ! 67: ! 68: //--------------------------------------------------------------------------- ! 69: // Initialize an IONetworkInterface instance. ! 70: // ! 71: // properties: A property dictionary. ! 72: // ! 73: // Returns true if initialized successfully, false otherwise. ! 74: ! 75: bool IONetworkInterface::init(OSDictionary * properties = 0) ! 76: { ! 77: _provider = 0; // single IONetworkController provider. ! 78: _ifLock = 0; // locks interface state and data accesses. ! 79: _clientSet = 0; // A set of all client objects. ! 80: _inputFilterFunc = 0; // input filter tap handler. ! 81: _outputFilterFunc = 0; // output filter tap handler. ! 82: _target = 0; // output target object. ! 83: _outAction = 0; // output packet action. ! 84: _dataDict = 0; // IONetworkData dict. ! 85: _registered = false; ! 86: ! 87: inputQHead = inputQTail = 0; ! 88: ! 89: // Propagate the init() call to our superclass. ! 90: // ! 91: if (!super::init(properties)) ! 92: return false; ! 93: ! 94: // Create interface lock. ! 95: // ! 96: _ifLock = IORecursiveLockAlloc(); ! 97: if (!_ifLock) ! 98: return false; ! 99: ! 100: // Create an OSSet to store client objects. Initial capacity ! 101: // (which can grow) is set at 2 clients. ! 102: // ! 103: _clientSet = OSSet::withCapacity(2); ! 104: if (!_clientSet) ! 105: return false; ! 106: ! 107: // Get the ifnet structure of the network interface. Subclasses must ! 108: // implement getIfnet() and expect this function to be called when ! 109: // they call IONetworkInterface::init(). ! 110: // ! 111: _ifp = getIfnet(); ! 112: if (!_ifp) ! 113: { ! 114: DLOG("%s: getIfnet() returned NULL\n", getName()); ! 115: return false; ! 116: } ! 117: ! 118: // Intialize the ifnet structure. ! 119: // ! 120: if (!initIfnet(_ifp)) ! 121: return false; ! 122: ! 123: // Create a data dictionary. ! 124: // ! 125: if ((_dataDict = OSDictionary::withCapacity(5)) == 0) ! 126: return false; ! 127: ! 128: IONetworkData * data = IONetworkData::withName( ! 129: kIONetworkStatsKey, ! 130: sizeof(IONetworkStats), ! 131: (UInt8 *) &(_ifp->if_data.ifi_ipackets)); ! 132: if (data) { ! 133: addNetworkData(data); ! 134: data->release(); ! 135: } ! 136: ! 137: // Set the default filter tap mode for both directions to ! 138: // kIOFilterTapModeInternal. Both taps will automatically receive all ! 139: // packets that flow through the interface in their respective ! 140: // directions. ! 141: // ! 142: _inputFilterTapMode = _outputFilterTapMode = kIOFilterTapModeInternal; ! 143: ! 144: return true; ! 145: } ! 146: ! 147: //--------------------------------------------------------------------------- ! 148: // Destroy the interface. Release all allocated resources. ! 149: ! 150: void IONetworkInterface::free() ! 151: { ! 152: DLOG("IONetworkInterface::free() called\n"); ! 153: ! 154: // Must never free a registered interface. ! 155: ! 156: assert(_registered == false); ! 157: ! 158: if (_clientSet) ! 159: { ! 160: // Should not have any clients. ! 161: // ! 162: assert(_clientSet->getCount() == 0); ! 163: _clientSet->release(); ! 164: } ! 165: ! 166: if (_ifLock) ! 167: { ! 168: IORecursiveLockFree(_ifLock); ! 169: _ifLock = 0; ! 170: } ! 171: ! 172: if (_dataDict) ! 173: _dataDict->release(); ! 174: ! 175: clearInputQueue(); ! 176: ! 177: super::free(); ! 178: } ! 179: ! 180: //--------------------------------------------------------------------------- ! 181: // Initialize the ifnet structure. Subclasses must override this ! 182: // method and initialize the ifnet structure given in a family specific ! 183: // manner. The implementation of this method in the subclass must call ! 184: // the version in super before it returns. The argument provided is a ! 185: // pointer to an ifnet structure obtained through getIfnet(). ! 186: // IONetworkInterface uses this method to initialize the function ! 187: // pointers in ifnet. ! 188: // ! 189: // ifp: Pointer to an ifnet structure obtained through an earlier ! 190: // getIfnet() call. ! 191: // ! 192: // Returns true if the initialization was successful. ! 193: ! 194: bool IONetworkInterface::initIfnet(struct ifnet * ifp) ! 195: { ! 196: lock(); ! 197: ! 198: // Register our 'shim' functions. These function pointers ! 199: // points to static member functions inside class. ! 200: ! 201: ifp->if_output = output_shim; ! 202: ifp->if_ioctl = ioctl_shim; ! 203: ifp->if_set_bpf_tap = set_bpf_tap_shim; ! 204: ifp->if_private = this; ! 205: ! 206: // Enable driver reentrancy. This allows the network stack ! 207: // to call the driver from the same thread that sent a received ! 208: // packet up to the stack. The netisr thread is bypassed. The context ! 209: // switch cost is eliminated, but how long will the driver have to wait ! 210: // before the thread can return to do driver work? ! 211: // ! 212: // Not enabled by default, do this on a per driver basis by calling, ! 213: // netif->setExtraFlags(IFEF_DVR_REENTRY_OK) from the driver's ! 214: // configureNetworkInterface() function. ! 215: // ! 216: // ifp->if_eflags |= IFEF_DVR_REENTRY_OK; ! 217: ! 218: unlock(); ! 219: ! 220: return true; ! 221: } ! 222: ! 223: //--------------------------------------------------------------------------- ! 224: // Take the interface lock (recursive lock). ! 225: ! 226: void IONetworkInterface::lock() ! 227: { ! 228: IORecursiveLockLock(_ifLock); ! 229: } ! 230: ! 231: //--------------------------------------------------------------------------- ! 232: // Release the interface lock (recursive lock). ! 233: ! 234: void IONetworkInterface::unlock() ! 235: { ! 236: IORecursiveLockUnlock(_ifLock); ! 237: } ! 238: ! 239: //--------------------------------------------------------------------------- ! 240: // Called by handleOpen() to configure our controller after we have just ! 241: // called he controller's open() method. We open the controller only when ! 242: // we receive the initial open request from a client. Subclasses should ! 243: // override this method and setup the controller before allowing the ! 244: // client open, and they must call this method and check the return ! 245: // value in their implementation. ! 246: // ! 247: // controller: Our controller object. ! 248: // ! 249: // Must return true in order for handleOpen() to accept the client open. ! 250: // If the return is false, then the controller will be closed and the client ! 251: // open will be rejected. ! 252: ! 253: bool IONetworkInterface::controllerDidOpen(IONetworkController * controller) ! 254: { ! 255: return true; // open approved. ! 256: } ! 257: ! 258: //--------------------------------------------------------------------------- ! 259: // Called by handleClose() after receiving a close from the ! 260: // last client, and just before the controller is closed. Subclasses ! 261: // can override this method to perform any cleanup action before the ! 262: // controller is closed. ! 263: // ! 264: // controller: The controller that will be closed. ! 265: ! 266: void IONetworkInterface::controllerWillClose(IONetworkController * controller) ! 267: { ! 268: } ! 269: ! 270: //--------------------------------------------------------------------------- ! 271: // Handle a client open on the interface. The open() method in IOService ! 272: // calls this method with the arbitration lock held. This method must ! 273: // return true to accept the client open. Subclasses should not override ! 274: // this method. ! 275: // ! 276: // client: See IOService. ! 277: // options: See IOService. ! 278: // argument: See IOService. ! 279: // ! 280: // Returns true to accept the client open. ! 281: ! 282: bool IONetworkInterface::handleOpen(IOService * client, ! 283: IOOptionBits options, ! 284: void * argument) ! 285: { ! 286: bool accept = false; ! 287: bool controllerOpen = false; ! 288: IONetworkController * controller = OSDynamicCast(IONetworkController, ! 289: getProvider()); ! 290: ! 291: do { ! 292: // Was this object already registered as our client? ! 293: // ! 294: if (_clientSet->containsObject(client)) ! 295: { ! 296: DLOG("%s: multiple opens from client %lx\n", ! 297: getName(), (UInt32) client); ! 298: accept = true; ! 299: break; ! 300: } ! 301: ! 302: // We can only provide services to a single client. ! 303: // IONetworkUserClient are excluded from this restriction. ! 304: // ! 305: bool isClient = (OSDynamicCast(IONetworkUserClient, client) == 0); ! 306: if (isClient && _client) ! 307: { ! 308: DLOG("%s: extra client %lx\n", getName(), (UInt32) client); ! 309: break; ! 310: } ! 311: ! 312: // If our provider has not yet been opened, then open it. ! 313: // However if the controller open fails, then we will not allow ! 314: // the new client to open us. ! 315: // ! 316: if (_provider == 0) { ! 317: if ((controller == 0) || ! 318: ((controllerOpen = controller->open(this)) == false) || ! 319: (controllerDidOpen(controller) == false)) ! 320: break; ! 321: } ! 322: ! 323: // Qualify the client. ! 324: // ! 325: if (!handleClientOpen(controller, client)) ! 326: break; ! 327: ! 328: // Add the new client object to our client set. ! 329: // ! 330: if (!_clientSet->setObject(client)) ! 331: { ! 332: handleClientClose(controller, client); ! 333: break; ! 334: } ! 335: ! 336: // Remember our client. ! 337: // ! 338: if (isClient) ! 339: _client = client; ! 340: ! 341: accept = true; ! 342: } ! 343: while (0); ! 344: ! 345: // If provider was opened above, but an error has caused us to refuse ! 346: // the client open, then close our provider. Otherwise, cache our ! 347: // provider. ! 348: // ! 349: if (controllerOpen) ! 350: { ! 351: if (accept) ! 352: { ! 353: _provider = controller; // cache our provider. ! 354: } ! 355: else { ! 356: controllerWillClose(controller); ! 357: controller->close(this); ! 358: } ! 359: } ! 360: ! 361: return accept; ! 362: } ! 363: ! 364: //--------------------------------------------------------------------------- ! 365: // Handle a close by one of our clients. We close the controller when ! 366: // we receive a close from our last client. The close() method in ! 367: // IOService calls this method with the arbitration lock held. ! 368: // Subclasses should not override this method. ! 369: // ! 370: // client: See IOService. ! 371: // options: See IOService. ! 372: ! 373: void IONetworkInterface::handleClose(IOService * client, IOOptionBits options) ! 374: { ! 375: // Remove the object from the client OSSet. ! 376: // ! 377: if (_clientSet->containsObject(client)) ! 378: { ! 379: bool isClient = (OSDynamicCast(IONetworkUserClient, client) == 0); ! 380: ! 381: // Call handleClientClose() to handle the client close. ! 382: // ! 383: assert(_provider); ! 384: handleClientClose(_provider, client); ! 385: ! 386: if (isClient) ! 387: _client = 0; ! 388: ! 389: // If this is the last client, then close our provider. ! 390: // ! 391: if (_clientSet->getCount() == 1) ! 392: { ! 393: controllerWillClose(_provider); ! 394: _provider->close(this); ! 395: _provider = 0; ! 396: } ! 397: ! 398: // Remove the client from our OSSet. ! 399: // ! 400: _clientSet->removeObject(client); ! 401: } ! 402: } ! 403: ! 404: //--------------------------------------------------------------------------- ! 405: // Returns true if the specified client, or any client if none if ! 406: // specified, presently has an open on this object. This function ! 407: // is called by IOService with the arbitration lock held. ! 408: // Subclasses should not override this method. ! 409: ! 410: bool IONetworkInterface::handleIsOpen(const IOService * client) const ! 411: { ! 412: if (client) ! 413: return _clientSet->containsObject(client); ! 414: else ! 415: return (_clientSet->getCount() > 0); ! 416: } ! 417: ! 418: //--------------------------------------------------------------------------- ! 419: // This method is called by handleOpen() to qualify a client ! 420: // object is trying to open us. This method must return true ! 421: // true to accept the client open. The provider of the ! 422: // interface object, an IONetworkController, is also provided. ! 423: ! 424: bool IONetworkInterface::handleClientOpen(IONetworkController * /*ctlr*/, ! 425: IOService * client) ! 426: { ! 427: bool allowOpen = true; ! 428: ! 429: // Always allow opens from IOUserClients. ! 430: // ! 431: if (OSDynamicCast(IONetworkUserClient, client)) ! 432: return true; ! 433: ! 434: lock(); ! 435: ! 436: // Packet output handler must be valid. ! 437: // ! 438: if (!_target || !_outAction) ! 439: allowOpen = false; ! 440: ! 441: // Transition state to registered. ! 442: // ! 443: if (allowOpen) ! 444: _registered = true; ! 445: ! 446: unlock(); ! 447: ! 448: return allowOpen; ! 449: } ! 450: ! 451: //--------------------------------------------------------------------------- ! 452: // Called by handleClose() to handle a client close. Both the provider ! 453: // and the client that performed the close are provided. ! 454: ! 455: void IONetworkInterface::handleClientClose(IONetworkController * /*ctlr*/, ! 456: IOService * client) ! 457: { ! 458: if (OSDynamicCast(IONetworkUserClient, client)) ! 459: return; ! 460: ! 461: lock(); ! 462: ! 463: // Transition state to unregistered. ! 464: // ! 465: _registered = false; ! 466: ! 467: unlock(); ! 468: } ! 469: ! 470: //--------------------------------------------------------------------------- ! 471: // Register the output handler. The interface will forward all output packets, ! 472: // sent from the network layer, to the output handler registered through ! 473: // this method. Until a handler is registered, handleClientOpen() ! 474: // will refuse all client opens. The output handler cannot be changed ! 475: // when the interface state is kIONetworkInterfaceStateRegistered. ! 476: // ! 477: // target: Target object that implements the output action. ! 478: // action: The action which handles output packets. ! 479: ! 480: bool IONetworkInterface::registerOutputHandler(OSObject * target, ! 481: IOOutputAction action) ! 482: { ! 483: target = OSDynamicCast(OSObject, target); ! 484: ! 485: lock(); ! 486: ! 487: // Sanity check on the arguments. ! 488: // ! 489: if (_registered || !target || !action) ! 490: { ! 491: unlock(); ! 492: return false; ! 493: } ! 494: ! 495: _target = target; ! 496: _outAction = action; ! 497: ! 498: unlock(); ! 499: ! 500: return true; ! 501: } ! 502: ! 503: //--------------------------------------------------------------------------- ! 504: // Functions to set and inspect the filter tap settings. These settings ! 505: // cannot change once the interface becomes registered. ! 506: ! 507: bool IONetworkInterface::_setFilterTapMode(IOFilterTapMode * modePtr, ! 508: IOFilterTapMode mode) ! 509: { ! 510: lock(); ! 511: ! 512: if (_registered) ! 513: { ! 514: unlock(); ! 515: return false; ! 516: } ! 517: *modePtr = mode; ! 518: ! 519: unlock(); ! 520: ! 521: return true; ! 522: } ! 523: ! 524: bool IONetworkInterface::setInputFilterTapMode(IOFilterTapMode mode) ! 525: { ! 526: return _setFilterTapMode(&_inputFilterTapMode, mode); ! 527: } ! 528: ! 529: bool IONetworkInterface::setOutputFilterTapMode(IOFilterTapMode mode) ! 530: { ! 531: return _setFilterTapMode(&_outputFilterTapMode, mode); ! 532: } ! 533: ! 534: IOFilterTapMode IONetworkInterface::getInputFilterTapMode() const ! 535: { ! 536: return _inputFilterTapMode; ! 537: } ! 538: ! 539: IOFilterTapMode IONetworkInterface::getOutputFilterTapMode() const ! 540: { ! 541: return _outputFilterTapMode; ! 542: } ! 543: ! 544: //--------------------------------------------------------------------------- ! 545: // Feed packets to the input/output BPF packet filter taps. ! 546: ! 547: static inline void _feedFilterTap(struct ifnet * ifp, ! 548: struct mbuf * m, ! 549: BPF_FUNC func, ! 550: int mode) ! 551: { ! 552: if (func) ! 553: func(ifp, m); ! 554: } ! 555: ! 556: //--------------------------------------------------------------------------- ! 557: // Feed a packet to the output filter tap. This method should not be called if ! 558: // the output filter tap mode is set to kIOFilterTapModeInternal, since the tap ! 559: // would already receive every output packet that flows through the interface. ! 560: // A further call to feedOutputFilterTap() would cause the tap to receive ! 561: // multiple copies of the same output packet. ! 562: // ! 563: // pkt: The packet mbuf to pass to the output tap. ! 564: ! 565: void IONetworkInterface::feedOutputFilterTap(struct mbuf * m) ! 566: { ! 567: assert(m); ! 568: _feedFilterTap(_ifp, m, _outputFilterFunc, BPF_TAP_OUTPUT); ! 569: } ! 570: ! 571: //--------------------------------------------------------------------------- ! 572: // Feed a packet to the input filter tap. This method should not be called if ! 573: // the input filter tap mode is set to kIOFilterTapModeInternal, since the tap ! 574: // would already receive every input packet that flows through the interface. ! 575: // A further call to feedInputFilterTap() would cause the tap to receive ! 576: // multiple copies of the same input packet ! 577: // ! 578: // pkt: The packet mbuf to pass to the input tap. The rcvif ! 579: // field in the mbuf is modified by this method. ! 580: ! 581: void IONetworkInterface::feedInputFilterTap(struct mbuf * m) ! 582: { ! 583: assert(m); ! 584: m->m_pkthdr.rcvif = _ifp; ! 585: _feedFilterTap(_ifp, m, _inputFilterFunc, BPF_TAP_INPUT); ! 586: } ! 587: ! 588: //--------------------------------------------------------------------------- ! 589: // Called by a controller to pass a received packet ! 590: // to the network layer. Packets received by this method can ! 591: // also be placed on a queue local to the interface, that the controller ! 592: // can use to delay the packet handoff to the network layer, until all ! 593: // received packets have been transferred to the queue. A subsequent call ! 594: // of flushInputQueue(), or inputPacket() with the queue argument set to ! 595: // false, will cause all queued packets (may be a single packet) to be ! 596: // delivered to the network layer, by making a single dlil_input() call. ! 597: // Additional methods that manipulate the input queue are flushInputQueue() ! 598: // and clearInputQueue(). This queue, which is nothing more than a chain of ! 599: // mbufs, is not protected by a lock since the controller is expected to ! 600: // manipulate the input queue from a single thread. If the input filter ! 601: // tap mode is set to kIOFilterTapModeInternal, then packets sent to ! 602: // this method are also fed to the input filter tap. ! 603: // ! 604: // m: The packet mbuf containing the received frame. ! 605: // ! 606: // length: If non zero, the mbuf will be truncated to the ! 607: // given length. If zero, then no truncation will take place. ! 608: // ! 609: // queue: If true, the only action performed is to queue the ! 610: // input packet. Otherwise, the dlil_input() function is ! 611: // called to handoff all queued packets (including the packet ! 612: // passed in). ! 613: // ! 614: // Returns the number of packets submitted to the network layer. ! 615: // Returns 0 if the packet was queued. ! 616: // ! 617: // FIXME - The current implementation does not use the new DLIL API's. ! 618: // Thus it will only work for Ethernet devices. ! 619: ! 620: #define IN_Q_RESET {inputQHead = 0;} ! 621: ! 622: #define IN_Q_ENQUEUE(m) \ ! 623: { \ ! 624: if (inputQHead == 0) \ ! 625: inputQHead = inputQTail = (m); \ ! 626: else { \ ! 627: inputQTail->m_nextpkt = (m); \ ! 628: inputQTail = (m); \ ! 629: } \ ! 630: } ! 631: ! 632: #define IN_Q_FLUSH(count) \ ! 633: { \ ! 634: struct mbuf * _m; \ ! 635: struct ether_header * _eh; \ ! 636: \ ! 637: count = 0; \ ! 638: \ ! 639: while ((_m = inputQHead)) { \ ! 640: inputQHead = inputQHead->m_nextpkt; \ ! 641: _m->m_nextpkt = 0; \ ! 642: _m->m_pkthdr.rcvif = _ifp; \ ! 643: \ ! 644: if (_inputFilterTapMode == kIOFilterTapModeInternal) \ ! 645: _feedFilterTap(_ifp, _m, _inputFilterFunc, BPF_TAP_INPUT); \ ! 646: \ ! 647: _eh = (struct ether_header *) _m->m_data; \ ! 648: _m->m_len -= sizeof(struct ether_header); \ ! 649: _m->m_data += sizeof(struct ether_header); \ ! 650: _m->m_pkthdr.len -= sizeof(struct ether_header); \ ! 651: \ ! 652: dlil_input(_ifp, _m, (char *) _eh); \ ! 653: count++; \ ! 654: } \ ! 655: } ! 656: ! 657: UInt32 IONetworkInterface::flushInputQueue() ! 658: { ! 659: UInt32 count; ! 660: ! 661: IN_Q_FLUSH(count); ! 662: // IN_Q_RESET; ! 663: return count; ! 664: } ! 665: ! 666: UInt32 IONetworkInterface::clearInputQueue() ! 667: { ! 668: UInt32 count = 0; ! 669: struct mbuf * m; ! 670: ! 671: while ((m = inputQHead)) ! 672: { ! 673: inputQHead = inputQHead->m_nextpkt; ! 674: m_freem(m); ! 675: count++; ! 676: } ! 677: // IN_Q_RESET; ! 678: return count; ! 679: } ! 680: ! 681: UInt32 IONetworkInterface::inputPacket(struct mbuf * m, ! 682: UInt32 length = 0, ! 683: bool queue = false) ! 684: { ! 685: assert(m); ! 686: ! 687: // Truncate the tail of the mbuf chain to the specified length. ! 688: // The mbuf chain passed in will usually have the length in ! 689: // each mbuf set to its capacity. ! 690: // ! 691: if (length) ! 692: { ! 693: struct mbuf * mb = m; ! 694: mb->m_pkthdr.len = length; // set total length ! 695: do { ! 696: if (length < (UInt) mb->m_len) ! 697: { ! 698: mb->m_len = length; // truncate mbuf to remaining length ! 699: } ! 700: length -= mb->m_len; // decrement remaining length ! 701: } while ((mb = mb->m_next)); ! 702: assert(length == 0); // why is capacity smaller than length? ! 703: } ! 704: ! 705: IN_Q_ENQUEUE(m); ! 706: ! 707: if (queue == false) ! 708: { ! 709: UInt32 count; ! 710: IN_Q_FLUSH(count); ! 711: // IN_Q_RESET; ! 712: return count; ! 713: } ! 714: else ! 715: return 0; ! 716: } ! 717: ! 718: //--------------------------------------------------------------------------- ! 719: // Called by the controller driver to send a network event to the network ! 720: // layer. Possible applications include: media changed events, ! 721: // power management events, controller state change events. ! 722: // ! 723: // eventType: The event type. ! 724: // arg: An argument associated with the event. ! 725: ! 726: void IONetworkInterface::inputEvent(UInt32 eventType, void * arg) ! 727: { ! 728: switch (eventType) ! 729: { ! 730: case kIONetworkEventMediumChange: ! 731: case kIONetworkEventLinkChange: ! 732: _handleMediumAndLinkChangeEvent(); ! 733: break; ! 734: ! 735: default: ! 736: IOLog("IONetworkInterface: event (%x, %x) not handled\n", ! 737: (UInt) eventType, (UInt) arg); ! 738: break; ! 739: } ! 740: } ! 741: ! 742: //--------------------------------------------------------------------------- ! 743: // Handles media and link change events. Deliver a notification to ! 744: // all IONetworkUserClients. ! 745: ! 746: void IONetworkInterface::_handleMediumAndLinkChangeEvent() ! 747: { ! 748: OSCollectionIterator * iter; ! 749: IONetworkUserClient * uc; ! 750: ! 751: lockForArbitration(); ! 752: iter = OSCollectionIterator::withCollection(_clientSet); ! 753: if (iter) { ! 754: while ((uc = (IONetworkUserClient *) iter->getNextObject())) { ! 755: if ((uc = OSDynamicCast(IONetworkUserClient, uc)) == 0) ! 756: continue; ! 757: uc->deliverNotification(kIONUCNotificationTypeLinkChange); ! 758: } ! 759: iter->release(); ! 760: } ! 761: unlockForArbitration(); ! 762: } ! 763: ! 764: //--------------------------------------------------------------------------- ! 765: // SIOCSIFMTU (set interface MTU) ioctl handler. ! 766: ! 767: SInt IONetworkInterface::syncSIOCSIFMTU(IONetworkController * ctlr, ! 768: struct ifreq * ifr) ! 769: { ! 770: SInt error; ! 771: UInt32 newMtu = ifr->ifr_mtu; ! 772: ! 773: // If change is not necessary, return success without getting the ! 774: // controller involved. ! 775: ! 776: if (getMaxTransferUnit() == newMtu) ! 777: return 0; ! 778: ! 779: // Request the controller to switch MTU size. ! 780: // ! 781: error = errnoFromReturn(ctlr->doSetMaxTransferUnit(this, newMtu)); ! 782: ! 783: if (error == 0) ! 784: { ! 785: // Controller reports success. Update the interface MTU size ! 786: // property. ! 787: // ! 788: setMaxTransferUnitInt(newMtu); ! 789: } ! 790: ! 791: return error; ! 792: } ! 793: ! 794: //--------------------------------------------------------------------------- ! 795: // SIOCSIFMEDIA (SET interface media) ioctl handler. ! 796: ! 797: SInt IONetworkInterface::syncSIOCSIFMEDIA(IONetworkController * ctlr, ! 798: struct ifreq * ifr) ! 799: { ! 800: OSDictionary * mediumDict; ! 801: IONetworkMedium * medium; ! 802: SInt error; ! 803: ! 804: mediumDict = ctlr->copyMediumDictionary(); // creates a copy ! 805: if (!mediumDict) ! 806: { ! 807: // unable to allocate memory, or no medium dictionary. ! 808: return EOPNOTSUPP; ! 809: } ! 810: ! 811: medium = IONetworkMedium::getMediumWithType(mediumDict, ifr->ifr_media); ! 812: if (!medium) ! 813: { ! 814: // Exact type was not found. Try a partial match. ! 815: // ifconfig program sets the media type and media ! 816: // options separately. The client should not send ! 817: // an incomplete type!!! ! 818: ! 819: medium = IONetworkMedium::getMediumWithType(mediumDict, ! 820: ifr->ifr_media, ! 821: ~kIOMediumTypeMask); ! 822: if (!medium) ! 823: { ! 824: mediumDict->release(); ! 825: return EINVAL; // requested medium not found. ! 826: } ! 827: } ! 828: ! 829: // It may be possible for the controller to update the medium ! 830: // dictionary and perhaps delete the medium entry that we have ! 831: // selected from our copy of the stale dictionary. This should be ! 832: // harmless since IONetworkController's doSelectMedium() should ! 833: // filter invalid selections before calling the driver. ! 834: ! 835: error = errnoFromReturn(ctlr->doSelectMedium(this, medium->getName())); ! 836: ! 837: if (error == 0) ! 838: { ! 839: // Remember the last media type sent by BSD which the driver ! 840: // accepted. Note that _bsdMediaType may not be equal to ! 841: // medium->getType() since we may have done a partial match. ! 842: // The only reason for this is to be able to return the ! 843: // _bsdMediaType as the current media type in SICGIFMEDIA. ! 844: ! 845: _bsdMediaType = ifr->ifr_media; ! 846: } ! 847: ! 848: mediumDict->release(); ! 849: ! 850: return error; ! 851: } ! 852: ! 853: //--------------------------------------------------------------------------- ! 854: // SIOCGIFMEDIA (GET interface media) ioctl handler. ! 855: ! 856: SInt IONetworkInterface::syncSIOCGIFMEDIA(IONetworkController * ctlr, ! 857: struct ifreq * ifr) ! 858: { ! 859: OSDictionary * mediumDict = 0; ! 860: UInt mediumCount = 0; ! 861: UInt maxCount; ! 862: OSCollectionIterator * iter = 0; ! 863: UInt32 * typeList; ! 864: UInt typeListSize; ! 865: OSSymbol * keyObject; ! 866: SInt error = 0; ! 867: struct ifmediareq * ifmr = (struct ifmediareq *) ifr; ! 868: ! 869: // Maximum number of medium types that the ioctl caller will accept. ! 870: // ! 871: maxCount = ifmr->ifm_count; ! 872: ! 873: do { ! 874: mediumDict = ctlr->copyMediumDictionary(); // creates a copy ! 875: if (!mediumDict) ! 876: { ! 877: error = EOPNOTSUPP; ! 878: break; // unable to allocate memory, or no medium dictionary. ! 879: } ! 880: ! 881: if ((mediumCount = mediumDict->getCount()) == 0) ! 882: break; // no medium in the medium dictionary ! 883: ! 884: if (maxCount == 0) ! 885: break; // caller is only probing for support and media count. ! 886: ! 887: if (maxCount < mediumCount) ! 888: { ! 889: // user buffer is too small to hold all medium entries. ! 890: error = E2BIG; ! 891: ! 892: // Proceed with partial copy on E2BIG. This follows the ! 893: // SIOCGIFMEDIA handling practice in bsd/net/if_media.c. ! 894: // ! 895: // break; ! 896: } ! 897: ! 898: // Create an iterator to loop through the medium entries in the ! 899: // dictionary. ! 900: // ! 901: iter = OSCollectionIterator::withCollection(mediumDict); ! 902: if (!iter) ! 903: { ! 904: error = ENOMEM; ! 905: break; ! 906: } ! 907: ! 908: // Allocate memory for the copyout buffer. ! 909: // ! 910: typeListSize = maxCount * sizeof(UInt32); ! 911: typeList = (UInt32 *) IOMalloc(typeListSize); ! 912: if (!typeList) ! 913: { ! 914: error = ENOMEM; ! 915: break; ! 916: } ! 917: bzero(typeList, typeListSize); ! 918: ! 919: // Iterate through the medium dictionary and copy the type of ! 920: // each medium entry to typeList[]. ! 921: // ! 922: mediumCount = 0; ! 923: while ( (keyObject = (OSSymbol *) iter->getNextObject()) && ! 924: (mediumCount < maxCount) ) ! 925: { ! 926: IONetworkMedium * medium = OSDynamicCast(IONetworkMedium, ! 927: mediumDict->getObject(keyObject)); ! 928: if (!medium) ! 929: continue; // should not happen! ! 930: ! 931: typeList[mediumCount++] = medium->getType(); ! 932: } ! 933: ! 934: if (mediumCount) ! 935: { ! 936: error = copyout((caddr_t) typeList, ! 937: (caddr_t) ifmr->ifm_ulist, ! 938: typeListSize); ! 939: } ! 940: ! 941: IOFree(typeList, typeListSize); ! 942: } ! 943: while (0); ! 944: ! 945: ifmr->ifm_active = ifmr->ifm_current = IFM_NONE; ! 946: ifmr->ifm_status = 0; ! 947: ifmr->ifm_count = mediumCount; ! 948: ! 949: // Get a copy of the controller's property table and read the ! 950: // link status, current, and active medium. ! 951: ! 952: OSDictionary * pTable = ctlr->dictionaryWithProperties(); ! 953: if (pTable) ! 954: { ! 955: OSNumber * linkStatus = OSDynamicCast(OSNumber, ! 956: pTable->getObject(kIOLinkStatus)); ! 957: if (linkStatus) ! 958: ifmr->ifm_status = linkStatus->unsigned32BitValue(); ! 959: ! 960: if (mediumDict) ! 961: { ! 962: IONetworkMedium * medium; ! 963: OSSymbol * mediumName; ! 964: ! 965: if ((mediumName = OSDynamicCast(OSSymbol, ! 966: pTable->getObject(kIOCurrentMedium))) && ! 967: (medium = OSDynamicCast(IONetworkMedium, ! 968: mediumDict->getObject(mediumName)))) ! 969: { ! 970: ifmr->ifm_current = medium->getType(); ! 971: if (IOMediumGetType(_bsdMediaType) == ! 972: IOMediumGetType((UInt32) ifmr->ifm_current)) ! 973: { ! 974: ifmr->ifm_current = _bsdMediaType; ! 975: } ! 976: } ! 977: ! 978: if ((mediumName = OSDynamicCast(OSSymbol, ! 979: pTable->getObject(kIOActiveMedium))) && ! 980: (medium = OSDynamicCast(IONetworkMedium, ! 981: mediumDict->getObject(mediumName)))) ! 982: { ! 983: ifmr->ifm_active = medium->getType(); ! 984: } ! 985: } ! 986: pTable->release(); ! 987: } ! 988: ! 989: if (iter) ! 990: iter->release(); ! 991: if (mediumDict) ! 992: mediumDict->release(); ! 993: ! 994: return error; ! 995: } ! 996: ! 997: //--------------------------------------------------------------------------- ! 998: // Handles generic socket ioctl commands sent to the interface. ! 999: // IONetworkInterface handles commands that are common to all network ! 1000: // families. A subclass of IONetworkInterface may override this method ! 1001: // in order to handle the same command that is handled here, but in a ! 1002: // different manner, or (the more like case) to augment the command ! 1003: // handling to include additional commands, and call super for any ! 1004: // commands not handled in the subclass. ! 1005: // ! 1006: // The commands handled by IONetworkInterface are: ! 1007: // SIOCGIFMTU - Get interface MTU size. ! 1008: // SIOCSIFMTU - Set interface MTU size. ! 1009: // SIOCSIFMEDIA - Set media. ! 1010: // SIOCGIFMEDIA - Get media and link status. ! 1011: // ! 1012: // Returns a BSD return code defined in bsd/sys/errno.h. ! 1013: ! 1014: SInt IONetworkInterface::performCommand(IONetworkController * ctlr, ! 1015: UInt32 cmd, ! 1016: void * arg0, ! 1017: void * arg1) ! 1018: { ! 1019: SInt ret = EBUSY; ! 1020: ! 1021: ctlr->syncRequest(this, /* sender */ ! 1022: this, /* target */ ! 1023: (IONetworkAction) &IONetworkInterface::syncPerformCommand, ! 1024: (UInt32 *) &ret, /* return */ ! 1025: (void *) ctlr, /* arg0 - arg3 */ ! 1026: (void *) cmd, ! 1027: (void *) arg0, ! 1028: (void *) arg1); ! 1029: ! 1030: return ret; ! 1031: } ! 1032: ! 1033: SInt IONetworkInterface::syncPerformCommand(IONetworkController * ctlr, ! 1034: UInt32 cmd, ! 1035: void * arg0, ! 1036: void * arg1) ! 1037: { ! 1038: struct ifreq * ifr = (struct ifreq *) arg1; ! 1039: SInt ret = EINVAL; ! 1040: ! 1041: if (ifr == 0) ! 1042: return EINVAL; ! 1043: ! 1044: switch (cmd) ! 1045: { ! 1046: // Get interface MTU. ! 1047: // ! 1048: case SIOCGIFMTU: ! 1049: ifr->ifr_mtu = getMaxTransferUnit(); ! 1050: ret = 0; // no error ! 1051: break; ! 1052: ! 1053: // Set interface MTU. ! 1054: // ! 1055: case SIOCSIFMTU: ! 1056: ret = syncSIOCSIFMTU(ctlr, ifr); ! 1057: break; ! 1058: ! 1059: // Set interface media type. ! 1060: // ! 1061: case SIOCSIFMEDIA: ! 1062: ret = syncSIOCSIFMEDIA(ctlr, ifr); ! 1063: break; ! 1064: ! 1065: // Get interface media type and status. ! 1066: // ! 1067: case SIOCGIFMEDIA: ! 1068: ret = syncSIOCGIFMEDIA(ctlr, ifr); ! 1069: break; ! 1070: ! 1071: default: ! 1072: // DLOG(%s: command not handled (%08lx), getName(), cmd); ! 1073: break; ! 1074: } ! 1075: ! 1076: return ret; ! 1077: } ! 1078: ! 1079: //--------------------------------------------------------------------------- ! 1080: // if_ioctl() handler - Calls performCommand() when we receive an ioctl ! 1081: // command from the network stack. ! 1082: ! 1083: int ! 1084: IONetworkInterface::ioctl_shim(struct ifnet * ifp, u_long cmd, caddr_t data) ! 1085: { ! 1086: assert(ifp && ifp->if_private); ! 1087: ! 1088: IONetworkInterface * self = (IONetworkInterface *) ifp->if_private; ! 1089: ! 1090: assert((ifp == self->_ifp) && self->_provider); ! 1091: ! 1092: return self->performCommand(self->_provider, ! 1093: cmd, ! 1094: (void *) ifp, ! 1095: (void *) data); ! 1096: } ! 1097: ! 1098: //--------------------------------------------------------------------------- ! 1099: // if_output() handler. ! 1100: // ! 1101: // Handle a call from the network stack to transmit all packets in ! 1102: // the ifnet's output queue. This queue is likely to be removed in ! 1103: // the future when DLIL gets rolled out. ! 1104: ! 1105: int IONetworkInterface::output_shim(struct ifnet * ifp, struct mbuf * m) ! 1106: { ! 1107: assert(ifp && ifp->if_private); ! 1108: ! 1109: IONetworkInterface * self = (IONetworkInterface *) ifp->if_private; ! 1110: ! 1111: assert(ifp == self->_ifp); ! 1112: ! 1113: if (m == 0) ! 1114: { ! 1115: DLOG("IONetworkInterface: NULL output mbuf\n"); ! 1116: return EINVAL; ! 1117: } ! 1118: ! 1119: if ((m->m_flags & M_PKTHDR) == 0) ! 1120: { ! 1121: DLOG("IONetworkInterface: M_PKTHDR bit not set\n"); ! 1122: m_freem(m); ! 1123: return EINVAL; ! 1124: } ! 1125: ! 1126: // Feed the output filter tap. ! 1127: // ! 1128: if (self->_outputFilterTapMode == kIOFilterTapModeInternal) ! 1129: _feedFilterTap(ifp, m, self->_outputFilterFunc, BPF_TAP_OUTPUT); ! 1130: ! 1131: // Forward the packet to the registered output packet handler. ! 1132: // ! 1133: return ((self->_target)->*(self->_outAction))(m); ! 1134: } ! 1135: ! 1136: //--------------------------------------------------------------------------- ! 1137: // if_set_bpf_tap() handler. Handles request from the DLIL to enable or ! 1138: // disable the input/output filter taps. ! 1139: // ! 1140: // FIXME - locking may be needed. ! 1141: ! 1142: int IONetworkInterface::set_bpf_tap_shim(struct ifnet * ifp, ! 1143: int mode, ! 1144: BPF_FUNC func) ! 1145: { ! 1146: assert(ifp && ifp->if_private); ! 1147: ! 1148: IONetworkInterface * self = (IONetworkInterface *) ifp->if_private; ! 1149: ! 1150: assert(ifp == self->_ifp); ! 1151: ! 1152: switch (mode) ! 1153: { ! 1154: case BPF_TAP_DISABLE: ! 1155: self->_inputFilterFunc = self->_outputFilterFunc = 0; ! 1156: break; ! 1157: ! 1158: case BPF_TAP_INPUT: ! 1159: assert(func); ! 1160: self->_inputFilterFunc = func; ! 1161: break; ! 1162: ! 1163: case BPF_TAP_OUTPUT: ! 1164: assert(func); ! 1165: self->_outputFilterFunc = func; ! 1166: break; ! 1167: ! 1168: case BPF_TAP_INPUT_OUTPUT: ! 1169: assert(func); ! 1170: self->_inputFilterFunc = self->_outputFilterFunc = func; ! 1171: break; ! 1172: ! 1173: default: ! 1174: DLOG("IONetworkInterface: Unknown BPF tap mode %d\n", mode); ! 1175: break; ! 1176: } ! 1177: ! 1178: return 0; ! 1179: } ! 1180: ! 1181: //--------------------------------------------------------------------------- ! 1182: // As the name implies, this function does nothing. This will get called ! 1183: // if the network stack tries to call the if_watchdog function pointer ! 1184: // in ifnet. This should not happen. IOKit does not use this watchdog ! 1185: // timer facility. ! 1186: ! 1187: void IONetworkInterface::null_shim(struct ifnet * /*ifp*/) ! 1188: { ! 1189: IOLog("IONetworkInterface::null_shim called!\n"); ! 1190: } ! 1191: ! 1192: //--------------------------------------------------------------------------- ! 1193: // ifnet field (and property table) getter/setter. ! 1194: // ! 1195: // For the setter, if restrict flag is set, that means that the property is ! 1196: // restricted from being modified once the interface's has been registered. ! 1197: ! 1198: bool IONetworkInterface::_setInterfaceProperty( ! 1199: UInt32 value, ! 1200: UInt32 mask, ! 1201: UInt32 bytes, ! 1202: void * addr, ! 1203: char * key, ! 1204: bool restrict) ! 1205: { ! 1206: bool updateOk = false; ! 1207: UInt32 newValue; ! 1208: ! 1209: lock(); ! 1210: ! 1211: if (restrict && (_registered == true)) ! 1212: goto abort; ! 1213: ! 1214: // Update the property in ifnet. ! 1215: // ! 1216: switch (bytes) ! 1217: { ! 1218: case 1: ! 1219: newValue = (*((UInt8 *) addr) & mask) | value; ! 1220: *((UInt8 *) addr) = (UInt8) newValue; ! 1221: break; ! 1222: case 2: ! 1223: newValue = (*((UInt16 *) addr) & mask) | value; ! 1224: *((UInt16 *) addr) = (UInt16) newValue; ! 1225: break; ! 1226: case 4: ! 1227: newValue = (*((UInt32 *) addr) & mask) | value; ! 1228: *((UInt32 *) addr) = (UInt32) newValue; ! 1229: break; ! 1230: default: ! 1231: goto abort; ! 1232: } ! 1233: ! 1234: // Update the OSNumber in the property table. ! 1235: // ! 1236: updateOk = key ? setProperty(key, newValue, bytes * 8) : true; ! 1237: ! 1238: abort: ! 1239: unlock(); ! 1240: return updateOk; ! 1241: } ! 1242: ! 1243: #define IO_IFNET_GET(func, type, field) \ ! 1244: type IONetworkInterface:: ## func() const \ ! 1245: { \ ! 1246: type ret; \ ! 1247: ((IONetworkInterface *) this)->lock(); \ ! 1248: ret = _ifp ? _ifp-> ## field : 0; \ ! 1249: ((IONetworkInterface *) this)->unlock(); \ ! 1250: return ret; \ ! 1251: } ! 1252: ! 1253: #define IO_IFNET_SET(func, type, field, propName) \ ! 1254: bool IONetworkInterface:: ## func ## Int(type value) \ ! 1255: { \ ! 1256: return _setInterfaceProperty( \ ! 1257: (UInt32) value, \ ! 1258: 0, \ ! 1259: sizeof(type), \ ! 1260: (void *) &_ifp-> ## field, \ ! 1261: propName, \ ! 1262: false); \ ! 1263: } \ ! 1264: \ ! 1265: bool IONetworkInterface:: ## func(type value) \ ! 1266: { \ ! 1267: return _setInterfaceProperty( \ ! 1268: (UInt32) value, \ ! 1269: 0, \ ! 1270: sizeof(type), \ ! 1271: (void *) &_ifp-> ## field, \ ! 1272: propName, \ ! 1273: true); \ ! 1274: } ! 1275: ! 1276: #define IO_IFNET_RMW(func, type, field, propName) \ ! 1277: bool IONetworkInterface:: ## func ## Int(type value, type clear = 0) \ ! 1278: { \ ! 1279: return _setInterfaceProperty( \ ! 1280: (UInt32) value, \ ! 1281: (UInt32) ~clear, \ ! 1282: sizeof(type), \ ! 1283: (void *) &_ifp-> ## field, \ ! 1284: propName, \ ! 1285: false); \ ! 1286: } \ ! 1287: \ ! 1288: bool IONetworkInterface:: ## func(type value, type clear = 0) \ ! 1289: { \ ! 1290: return _setInterfaceProperty( \ ! 1291: (UInt32) value, \ ! 1292: (UInt32) ~clear, \ ! 1293: sizeof(type), \ ! 1294: (void *) &_ifp-> ## field, \ ! 1295: propName, \ ! 1296: true); \ ! 1297: } ! 1298: ! 1299: //--------------------------------------------------------------------------- ! 1300: // Interface type accessors (ifp->if_type). The list of interface types is ! 1301: // defined in <bsd/net/if_types.h>. ! 1302: ! 1303: IO_IFNET_SET(setInterfaceType, UInt8, if_type, kIOInterfaceType) ! 1304: IO_IFNET_GET(getInterfaceType, UInt8, if_type) ! 1305: ! 1306: //--------------------------------------------------------------------------- ! 1307: // Mtu (MaxTransferUnit) accessors (ifp->if_mtu). ! 1308: ! 1309: IO_IFNET_SET(setMaxTransferUnit, UInt32, if_mtu, kIOMaxTransferUnit) ! 1310: IO_IFNET_GET(getMaxTransferUnit, UInt32, if_mtu) ! 1311: ! 1312: //--------------------------------------------------------------------------- ! 1313: // Flags accessors (ifp->if_flags). This is a read-modify-write operation. ! 1314: ! 1315: IO_IFNET_RMW(setFlags, UInt16, if_flags, kIOInterfaceFlags) ! 1316: IO_IFNET_GET(getFlags, UInt16, if_flags) ! 1317: ! 1318: //--------------------------------------------------------------------------- ! 1319: // EFlags accessors (ifp->if_eflags). This is a read-modify-write operation. ! 1320: ! 1321: IO_IFNET_RMW(setExtraFlags, UInt32, if_eflags, kIOInterfaceExtraFlags) ! 1322: IO_IFNET_GET(getExtraFlags, UInt32, if_eflags) ! 1323: ! 1324: //--------------------------------------------------------------------------- ! 1325: // MediaAddressLength accessors (ifp->if_addrlen) ! 1326: ! 1327: IO_IFNET_SET(setMediaAddressLength, UInt8, if_addrlen, kIOMediaAddressLength) ! 1328: IO_IFNET_GET(getMediaAddressLength, UInt8, if_addrlen) ! 1329: ! 1330: //--------------------------------------------------------------------------- ! 1331: // MediaHeaderLength accessors (ifp->if_hdrlen) ! 1332: ! 1333: IO_IFNET_SET(setMediaHeaderLength, UInt8, if_hdrlen, kIOMediaHeaderLength) ! 1334: IO_IFNET_GET(getMediaHeaderLength, UInt8, if_hdrlen) ! 1335: ! 1336: //--------------------------------------------------------------------------- ! 1337: // Interface unit number. The unit number for the interface is assigned ! 1338: // by our client. ! 1339: ! 1340: IO_IFNET_SET(setUnitNumber, UInt16, if_unit, 0) ! 1341: IO_IFNET_GET(getUnitNumber, UInt16, if_unit) ! 1342: ! 1343: //--------------------------------------------------------------------------- ! 1344: // Interface name. ! 1345: ! 1346: IO_IFNET_SET(setInterfaceName, const char *, if_name, 0) ! 1347: IO_IFNET_GET(getInterfaceName, const char *, if_name) ! 1348: ! 1349: //--------------------------------------------------------------------------- ! 1350: // Return true if the interface has been registered with the network layer, ! 1351: // false otherwise. ! 1352: ! 1353: bool IONetworkInterface::isRegistered() const ! 1354: { ! 1355: return _registered; ! 1356: } ! 1357: ! 1358: //--------------------------------------------------------------------------- ! 1359: // Perform a lookup of the dictionary kept by the interface, ! 1360: // and return an entry that matches the specified string key. ! 1361: // ! 1362: // key: Search for an IONetworkData entry with this key. ! 1363: // ! 1364: // Returns the matching entry, or 0 if no match was found. ! 1365: ! 1366: IONetworkData * IONetworkInterface::getNetworkData(const OSSymbol * key) const ! 1367: { ! 1368: return OSDynamicCast(IONetworkData, _dataDict->getObject(key)); ! 1369: } ! 1370: ! 1371: IONetworkData * IONetworkInterface::getNetworkData(const char * key) const ! 1372: { ! 1373: return OSDynamicCast(IONetworkData, _dataDict->getObject(key)); ! 1374: } ! 1375: ! 1376: //--------------------------------------------------------------------------- ! 1377: // A private function to copy the data dictionary to the property table. ! 1378: ! 1379: bool IONetworkInterface::_copyNetworkDataDictToPropertyTable() ! 1380: { ! 1381: OSDictionary * aCopy = OSDictionary::withDictionary(_dataDict); ! 1382: bool ret = false; ! 1383: ! 1384: if (aCopy) { ! 1385: ret = setProperty(kIONetworkData, _dataDict); ! 1386: aCopy->release(); ! 1387: } ! 1388: ! 1389: return ret; ! 1390: } ! 1391: ! 1392: //--------------------------------------------------------------------------- ! 1393: // Remove an entry from the dictionary of IONetworkData objects. ! 1394: // ! 1395: // aKey: A key for an IONetworkData entry in the dictionary. ! 1396: // ! 1397: // Returns true if completed without errors, ! 1398: // false if the operation was aborted. ! 1399: ! 1400: bool IONetworkInterface::removeNetworkData(const OSSymbol * aKey) ! 1401: { ! 1402: bool ret = false; ! 1403: ! 1404: lockForArbitration(); ! 1405: ! 1406: do { ! 1407: if (_clientSet->getCount()) ! 1408: break; ! 1409: ! 1410: _dataDict->removeObject(aKey); ! 1411: ret = _copyNetworkDataDictToPropertyTable(); ! 1412: } ! 1413: while (0); ! 1414: ! 1415: unlockForArbitration(); ! 1416: ! 1417: return ret; ! 1418: } ! 1419: ! 1420: bool IONetworkInterface::removeNetworkData(const char * aKey) ! 1421: { ! 1422: bool ret = false; ! 1423: ! 1424: lockForArbitration(); ! 1425: ! 1426: do { ! 1427: if (_clientSet->getCount()) ! 1428: break; ! 1429: ! 1430: _dataDict->removeObject(aKey); ! 1431: ret = _copyNetworkDataDictToPropertyTable(); ! 1432: } ! 1433: while (0); ! 1434: ! 1435: unlockForArbitration(); ! 1436: ! 1437: return ret; ! 1438: } ! 1439: ! 1440: //--------------------------------------------------------------------------- ! 1441: // Add an IONetworkData object to a dictionary kept by ! 1442: // the interface. ! 1443: // ! 1444: // aData: An IONetworkData object. ! 1445: // ! 1446: // Returns true if the data object was added successfully, false otherwise. ! 1447: ! 1448: bool IONetworkInterface::addNetworkData(IONetworkData * aData) ! 1449: { ! 1450: bool ret = false; ! 1451: ! 1452: if (OSDynamicCast(IONetworkData, aData) == 0) ! 1453: return false; ! 1454: ! 1455: lockForArbitration(); ! 1456: ! 1457: if (_clientSet->getCount() == 0) ! 1458: { ! 1459: if ((ret = _dataDict->setObject(aData->getKey(), aData))) ! 1460: ret = _copyNetworkDataDictToPropertyTable(); ! 1461: } ! 1462: ! 1463: unlockForArbitration(); ! 1464: ! 1465: return ret; ! 1466: } ! 1467: ! 1468: //--------------------------------------------------------------------------- ! 1469: // Create a new IOUserClient to handle client requests. The default ! 1470: // implementation will create an IONetworkUserClient instance if ! 1471: // the type is kIONUCType. ! 1472: ! 1473: IOReturn IONetworkInterface::newUserClient(task_t owningTask, ! 1474: void * /*security_id*/, ! 1475: UInt32 type, ! 1476: IOUserClient ** handler) ! 1477: { ! 1478: IOReturn err = kIOReturnSuccess; ! 1479: IONetworkUserClient * client; ! 1480: ! 1481: if (type != kIONUCType) ! 1482: return kIOReturnBadArgument; ! 1483: ! 1484: client = IONetworkUserClient::withTask(owningTask); ! 1485: ! 1486: if (!client || !client->attach(this) || !client->start(this)) ! 1487: { ! 1488: if (client) ! 1489: { ! 1490: client->detach(this); ! 1491: client->release(); ! 1492: client = 0; ! 1493: } ! 1494: err = kIOReturnNoMemory; ! 1495: } ! 1496: ! 1497: *handler = client; ! 1498: ! 1499: return err; ! 1500: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.