Annotation of XNU/iokit/Families/IONetworking/IONetworkInterface.cpp, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.