Annotation of XNU/iokit/Families/IONetworking/IOEthernetInterface.cpp, revision 1.1.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:  * IOEthernetInterface.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 <libkern/c++/OSData.h>
                     35: #include <IOKit/network/IOEthernetInterface.h>
                     36: #include <IOKit/network/IOEthernetController.h>
                     37: #include <IOKit/network/IONetworkUserClient.h>
                     38: 
                     39: extern "C" {
                     40: #include <sys/param.h>
                     41: #include <sys/errno.h>
                     42: #include <net/if_dl.h>
                     43: #include <net/if_types.h>
                     44: #include <sys/sockio.h>
                     45: #include <netinet/in_var.h>
                     46: #include <sys/malloc.h>
                     47: void arpwhohas(struct arpcom * ac, struct in_addr * addr);
                     48: }
                     49: 
                     50: //---------------------------------------------------------------------------
                     51: 
                     52: #define super IONetworkInterface
                     53: 
                     54: OSDefineMetaClassAndStructors( IOEthernetInterface, IONetworkInterface )
                     55: 
                     56: // The name prefix for all BSD Ethernet interfaces.
                     57: // 
                     58: #define kIOEthernetInterfaceNamePrefix      "en"
                     59: 
                     60: //---------------------------------------------------------------------------
                     61: // Macros
                     62: 
                     63: #define CTLR_SYNC_REQ(ctlr, action, ret, args...)   \
                     64:         ctlr->syncRequest(this, this, (IONetworkAction) action, \
                     65:                           (UInt32 *) ret, ## args)
                     66: 
                     67: #ifdef  DEBUG
                     68: #define DLOG(fmt, args...)  IOLog(fmt, ## args)
                     69: #else
                     70: #define DLOG
                     71: #endif
                     72: 
                     73: //---------------------------------------------------------------------------
                     74: // Initialize an IOEthernetInterface instance. Instance variables are
                     75: // initialized, and an arpcom structure is allocated.
                     76: 
                     77: bool IOEthernetInterface::init(OSDictionary * properties = 0)
                     78: {
                     79:     // Initialize instance variables.
                     80:     //
                     81:     _arpcom             = 0;     // arpcom structure.
                     82:     _mcAddrCount        = 0;     // number of multicast addresses.
                     83:     _features           = 0;     // controller's family specific features.
                     84:     _activeFilters      = 0;     // active packet filters.
                     85:     _availableFilters   = 0;     // available packet filters.
                     86:     _controllerEnabled  = false;
                     87: 
                     88:     // Allocate an arpcom structure, clear it, then call super::init().
                     89:     // We expect our superclass to call getIfnet() during its init()
                     90:     // method. So we have to create arpcom before calling super::init().
                     91: 
                     92:     if ((_arpcom = (struct arpcom *) IOMalloc(sizeof(*_arpcom))) == 0)
                     93:     {
                     94:         DLOG("IOEthernetInterface: arpcom allocation failed\n");
                     95:         return false;
                     96:     }
                     97: 
                     98:     bzero(_arpcom, sizeof(*_arpcom));
                     99: 
                    100:     // Pass the init() call to our superclass.
                    101:     //
                    102:     if (!super::init(properties))
                    103:         return false;
                    104: 
                    105:     // Add an IONetworkData with room to hold an IOEthernetStats structure.
                    106:     // This class does not reference the data object created, and no harm
                    107:     // is done if the data object is released.
                    108: 
                    109:     IONetworkData * data = IONetworkData::withName(kIOEthernetStatsKey,
                    110:                                                    sizeof(IOEthernetStats));
                    111:     if (data) {
                    112:         addNetworkData(data);
                    113:         data->release();
                    114:     }
                    115: 
                    116:     return true;
                    117: }
                    118: 
                    119: //---------------------------------------------------------------------------
                    120: // Initialize the ifnet structure. The argument specified is
                    121: // a pointer to an ifnet structure obtained through getIfnet().
                    122: // IOEthernetInterface will initialize this structure in a manner that
                    123: // is appropriate for Ethernet interfaces.
                    124: //
                    125: // ifp: Pointer to the ifnet structure to be initialized.
                    126: //
                    127: // Returns true if successful, false otherwise.
                    128: 
                    129: bool IOEthernetInterface::initIfnet(struct ifnet * ifp)
                    130: {
                    131:     struct arpcom * ac = (struct arpcom *) ifp;
                    132:     
                    133:     assert(ac);
                    134: 
                    135:     lock();    // lock interface state
                    136: 
                    137:     bzero(ac, sizeof(*ac));
                    138: 
                    139:     // Set defaults suitable for Ethernet interfaces.
                    140: 
                    141:     setInterfaceType(IFT_ETHER);
                    142:     setMaxTransferUnit(ETHERMTU);
                    143:     setMediaAddressLength(NUM_EN_ADDR_BYTES);
                    144:     setMediaHeaderLength(ETHERHDRSIZE);
                    145:     setFlags(IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS);
                    146: 
                    147:     unlock();  // unlock interface state
                    148: 
                    149:     return super::initIfnet(ifp);
                    150: }
                    151: 
                    152: //---------------------------------------------------------------------------
                    153: // Free the IOEthernetInterface instance. The memory allocated
                    154: // for the arpcom structure is released.
                    155: 
                    156: void IOEthernetInterface::free()
                    157: {
                    158:     if (_arpcom) IOFree(_arpcom, sizeof(*_arpcom));
                    159: 
                    160:     super::free();
                    161: }
                    162: 
                    163: //---------------------------------------------------------------------------
                    164: // This method returns a pointer to an ifnet structure
                    165: // maintained by the family specific interface. IOEthernetInterface
                    166: // allocates an arpcom structure during initialization, and returns
                    167: // a pointer to this structure when this method is called.
                    168: //
                    169: // Returns a pointer to an ifnet structure.
                    170: 
                    171: struct ifnet * IOEthernetInterface::getIfnet() const
                    172: {
                    173:     return (&(_arpcom->ac_if));
                    174: }
                    175: 
                    176: //---------------------------------------------------------------------------
                    177: // The name of the interface advertised to the network layer
                    178: // is generated by concatenating the string returned by this method,
                    179: // and an unit number.
                    180: //
                    181: // Returns a pointer to a constant string "en". Thus Ethernet interfaces
                    182: // will be registered as en0, en1, etc.
                    183: 
                    184: const char * IOEthernetInterface::getNamePrefix() const
                    185: {
                    186:     return kIOEthernetInterfaceNamePrefix;
                    187: }
                    188: 
                    189: //---------------------------------------------------------------------------
                    190: // Update the packet filter property. This property contains the set of
                    191: // packet filters needed by the interface. It may not represent the set
                    192: // of packet filters that are actually in use and enabled.
                    193: //
                    194: // Returns true if the newFilter provided is different from the previously 
                    195: // cached value.
                    196: 
                    197: bool IOEthernetInterface::_setActiveFilters(UInt32 newFilters)
                    198: {
                    199:     if (newFilters == _activeFilters)
                    200:         return false;
                    201: 
                    202:     _activeFilters = newFilters;
                    203:     setProperty(kIOPacketFilters, _activeFilters, 32);
                    204:     return true;
                    205: }
                    206: 
                    207: //---------------------------------------------------------------------------
                    208: // Prepare the controller after it has been opened.
                    209: // This method will be called by our superclass after a
                    210: // network controller has accepted an open from this interface.
                    211: // IOEthernetInterface uses this method to inspect the controller
                    212: // and to cache certain controller properties, such as its hardware
                    213: // address, and its set of supported packet filters.
                    214: //
                    215: // controller: The controller object that was opened.
                    216: //
                    217: // Returns true if the controller was accepted, false otherwise
                    218: // (which will cause the controller to be closed).
                    219: 
                    220: bool IOEthernetInterface::controllerDidOpen(IONetworkController * inController)
                    221: {
                    222:     bool ret = false;
                    223:     IOEthernetController * controller = OSDynamicCast(IOEthernetController, 
                    224:                                                       inController);
                    225: 
                    226:     do {
                    227:         IOReturn  r;
                    228: 
                    229:         if (!controller)
                    230:             break;
                    231: 
                    232:         // Call the superclass' controllerDidOpen().
                    233:         //
                    234:         if (!super::controllerDidOpen(controller))
                    235:             break;
                    236: 
                    237:         // Cache the controller's family feature set.
                    238:         //
                    239:         _features = controller->getFamilyFeatureSet();
                    240: 
                    241:         // Get the controller's (supported) packet filters.
                    242:         //
                    243:         r = controller->doGetPacketFilters(this, &_availableFilters);
                    244: 
                    245:         if (r != kIOReturnSuccess)
                    246:         {
                    247:             DLOG("%s: doGetPacketFilters error %x\n", getName(), r);
                    248:             break;
                    249:         }
                    250: 
                    251:         // Controller must support Unicast and Broadcast filtering.
                    252:         //
                    253:         if ((_availableFilters &
                    254:             (kIOPacketFilterUnicast | kIOPacketFilterBroadcast)) !=
                    255:             (kIOPacketFilterUnicast | kIOPacketFilterBroadcast))
                    256:         {
                    257:             DLOG("%s: No Unicast/Broadcast packet filters %lx\n",
                    258:                 getName(), _availableFilters);
                    259:             break;
                    260:         }
                    261: 
                    262:         // If controller reports multicast or multicast-all capability,
                    263:         // then update if_flags to include multicast support.
                    264:         //
                    265:         if (_availableFilters &
                    266:             (kIOPacketFilterMulticast | kIOPacketFilterMulticastAll))
                    267:         {
                    268:             setFlagsInt(IFF_MULTICAST);
                    269:         }
                    270: 
                    271:         // Even though the network stack will not explicitly request the
                    272:         // interface to enable Unicast and Broadcast filtering. It is
                    273:         // implicit. Therefore, we will always activate both of those
                    274:         // filter types.
                    275: 
                    276:         _setActiveFilters(kIOPacketFilterUnicast | kIOPacketFilterBroadcast);
                    277: 
                    278:         r = controller->doEnablePacketFilters(this, _activeFilters);
                    279: 
                    280:         if (r != kIOReturnSuccess)
                    281:         {
                    282:             DLOG("%s: Failed to enable Unicast/Broadcast filters %x\n",
                    283:                  getName(), r);
                    284:             break;
                    285:         }
                    286: 
                    287:         // Read and save the controller's MAC address.
                    288:         //
                    289:         r = ((IOEthernetController *) 
                    290:             controller)->doGetHardwareAddress(this, &_macAddr);
                    291:         if (r != kIOReturnSuccess)
                    292:         {
                    293:             DLOG("%s: kRequestGetHardwareAddress error %x\n", getName(), r);
                    294:             break;
                    295:         }
                    296: 
                    297: #if 1   // Print the MAC address
                    298:         IOLog("%s: Ethernet address %02x:%02x:%02x:%02x:%02x:%02x\n",
                    299:               getName(),
                    300:               _macAddr.ether_addr_octet[0],
                    301:               _macAddr.ether_addr_octet[1],
                    302:               _macAddr.ether_addr_octet[2],
                    303:               _macAddr.ether_addr_octet[3],
                    304:               _macAddr.ether_addr_octet[4],
                    305:               _macAddr.ether_addr_octet[5]);
                    306: #endif
                    307: 
                    308:         // Copy the hardware address we obtained from the controller
                    309:         // to the arpcom structure.
                    310:         //
                    311:         bcopy(&_macAddr, _arpcom->ac_enaddr, NUM_EN_ADDR_BYTES);
                    312: 
                    313:         // Store MAC address in interface's propertyTable.
                    314:         //
                    315:         setProperty(kIOMACAddress, (void *) &_macAddr, NUM_EN_ADDR_BYTES);
                    316: 
                    317:         ret = true;
                    318:     }
                    319:     while (0);
                    320: 
                    321:     return ret;
                    322: }
                    323: 
                    324: //---------------------------------------------------------------------------
                    325: // When the last close from our client is received, the
                    326: // interface object will close its controller. But before the controller
                    327: // is closed, this method will be called by our superclass to perform any 
                    328: // final cleanup. IOEthernetInterface will ensure that the controller
                    329: // is disabled before it is closed.
                    330: //
                    331: // controller: The currently opened controller object.
                    332: 
                    333: void IOEthernetInterface::controllerWillClose(IONetworkController * controller)
                    334: {
                    335:     if (_controllerEnabled)
                    336:     {
                    337:         // Make sure the controller is disabled when we have lost all
                    338:         // our clients, and is about to close the controller. It
                    339:         // should be safe to update the _controllerEnabled variable
                    340:         // shared with the ioctl handlers, which shouldn't run without
                    341:         // an open client.
                    342: 
                    343:         controller->doDisable(this);
                    344:         _controllerEnabled = false;
                    345:     }
                    346: 
                    347:     super::controllerWillClose(controller);
                    348: }
                    349: 
                    350: //---------------------------------------------------------------------------
                    351: // The handler for ioctl commands sent from the network layer.
                    352: // Commands not handled by this method are passed to our superclass.
                    353: //
                    354: // Argument convention is:
                    355: //
                    356: //    arg0 - (struct ifnet *)
                    357: //    arg1 - (void *)
                    358: //
                    359: // The commands handled by IOEthernetInterface are:
                    360: //
                    361: //    SIOCSIFADDR
                    362: //    SIOCSIFFLAGS
                    363: //    SIOCADDMULTI
                    364: //    SIOCDELMULTI
                    365: //
                    366: // Returns an error code defined in errno.h (BSD).
                    367: 
                    368: SInt IOEthernetInterface::performCommand(IONetworkController * inController,
                    369:                                          UInt32                cmd,
                    370:                                          void *                arg0,
                    371:                                          void *                arg1)
                    372: {
                    373:     struct arpcom *        ac  = (struct arpcom *) _arpcom;
                    374:     struct ifaddr *        ifa = (struct ifaddr *) arg1;
                    375:     SInt                   ret = EBUSY;
                    376:     IOEthernetController * controller = (IOEthernetController *) inController;
                    377: 
                    378:     assert(arg0 == _arpcom);
                    379: 
                    380:     if (!controller) return EINVAL;
                    381: 
                    382:     switch (cmd)
                    383:     {
                    384:         case SIOCSIFADDR:
                    385:             CTLR_SYNC_REQ(controller, &IOEthernetInterface::syncSIOCSIFADDR, 
                    386:                           &ret, controller);
                    387:             if (ret)
                    388:             {
                    389:                 IOLog("IOEthernetInterface: SIOCSIFADDR returned %d\n", ret);
                    390:                 break;
                    391:             }
                    392: 
                    393:             switch (ifa->ifa_addr->sa_family)
                    394:             {
                    395:                 case AF_INET:
                    396:                     //
                    397:                     // See if another station has *our* IP address.
                    398:                     // i.e.: There is an address conflict! If a
                    399:                     // conflict exists, a message is sent to the
                    400:                     // console.
                    401:                     //
                    402:                     if (IA_SIN(ifa)->sin_addr.s_addr != 0)
                    403:                     {
                    404:                         /* don't bother for 0.0.0.0 */
                    405:                         ac->ac_ipaddr = IA_SIN(ifa)->sin_addr;
                    406:                         arpwhohas(ac, &IA_SIN(ifa)->sin_addr);
                    407:                     }
                    408:                     break;
                    409: 
                    410:                 default:
                    411:                     break;
                    412:             }
                    413:             break;
                    414: 
                    415:         case SIOCSIFFLAGS:
                    416:             CTLR_SYNC_REQ(controller, &IOEthernetInterface::syncSIOCSIFFLAGS, 
                    417:                           &ret, controller);
                    418:             break;
                    419: 
                    420:         case SIOCADDMULTI:
                    421:             CTLR_SYNC_REQ(controller, &IOEthernetInterface::syncSIOCADDMULTI, 
                    422:                           &ret, controller);    
                    423:             break;
                    424: 
                    425:         case SIOCDELMULTI:
                    426:             CTLR_SYNC_REQ(controller, &IOEthernetInterface::syncSIOCDELMULTI, 
                    427:                           &ret, controller);
                    428:             break;  
                    429: 
                    430:         default:            
                    431:             // Don't know what to do with this ioctl command, forward it
                    432:             // to our superclass.
                    433:             //
                    434:             ret = super::performCommand(controller, cmd, arg0, arg1);
                    435:             break;
                    436:     }
                    437: 
                    438:     return ret;
                    439: }
                    440: 
                    441: //---------------------------------------------------------------------------
                    442: // _enableController() is reponsible for calling the controller's enable()
                    443: // method and restoring the state of the controller. We assume that
                    444: // controllers can completely reset its state upon receiving a disable()
                    445: // method call. And when it is brought back up, the interface should
                    446: // assist in restoring the previous state of the Ethernet controller.
                    447: 
                    448: IOReturn IOEthernetInterface::_enableController(IONetworkController * ctlr)
                    449: {
                    450:     IOReturn ret;
                    451: 
                    452:     assert(ctlr);
                    453: 
                    454:     // Send the controller an enable request.
                    455:     //
                    456:     ret = ctlr->doEnable(this);
                    457:     if (ret != kIOReturnSuccess)
                    458:         return ret;     // unable to bring up the controller.
                    459: 
                    460:     // Restore current filter settings.
                    461:     //
                    462:     ret = ctlr->doEnablePacketFilters(this, _activeFilters);
                    463:     if (ret != kIOReturnSuccess)
                    464:         goto error;
                    465: 
                    466:     // Update multicast address list.
                    467:     //
                    468:     if (_availableFilters & kIOPacketFilterMulticast)
                    469:     {
                    470:         ret = _loadMulticastList((IOEthernetController *) ctlr);
                    471:         if (ret != kIOReturnSuccess)
                    472:             goto error;
                    473:     }
                    474: 
                    475:     _controllerEnabled = true;
                    476: 
                    477:     return kIOReturnSuccess;
                    478: 
                    479: error:
                    480:     // If the controller was enabled, make sure we disable it if an
                    481:     // error occurred.
                    482:     //
                    483:     DLOG("%s: _enableController error %x\n", getName(), ret);
                    484: 
                    485:     ret = ctlr->doDisable(this);
                    486: 
                    487:     return ret;
                    488: }
                    489: 
                    490: //---------------------------------------------------------------------------
                    491: // Handles SIOCSIFFLAGS ioctl command for Ethernet interfaces. The network
                    492: // stack has changed the if_flags field in ifnet. Our job is to go
                    493: // through if_flags and see what has changed, and act accordingly.
                    494: //
                    495: // The fact that if_flags contains both generic and Ethernet specific bits
                    496: // means that we cannot move some of the default flag processing to the
                    497: // superclass. Sigh...
                    498: 
                    499: int IOEthernetInterface::syncSIOCSIFFLAGS(IOEthernetController * ctlr)
                    500: {
                    501:     SInt      r = 0;
                    502:     UInt16    flags = getFlags();
                    503:     IOReturn  ret;
                    504:     UInt32    newFilters = _activeFilters;
                    505: 
                    506:     if ( !(flags & IFF_UP) && (flags & IFF_RUNNING) )
                    507:     {
                    508:         // If interface is marked down and it is running,
                    509:         // then stop it.
                    510: 
                    511:         ctlr->doDisable(this);
                    512:         flags &= ~IFF_RUNNING;
                    513:         _controllerEnabled = false;
                    514:     }
                    515:     else if ( (flags & IFF_UP) && !(flags & IFF_RUNNING) )
                    516:     {
                    517:         // If interface is marked up and it is stopped, then
                    518:         // start it.
                    519: 
                    520:         if ((ret = _enableController(ctlr)) == kIOReturnSuccess)
                    521:             flags |= IFF_RUNNING;
                    522:         else
                    523:             r = errnoFromReturn(ret);
                    524:     }
                    525: 
                    526:     if (flags & IFF_RUNNING)
                    527:     {
                    528:         // Set/Clear promiscuous mode.
                    529:         //
                    530:         if (_availableFilters & kIOPacketFilterPromiscuous)
                    531:         {
                    532:             if (flags & IFF_PROMISC)
                    533:                 newFilters |= kIOPacketFilterPromiscuous;
                    534:             else
                    535:                 newFilters &= ~kIOPacketFilterPromiscuous;
                    536:         }
                    537: 
                    538:         // Set/Clear Multicast-All mode.
                    539:         //
                    540:         if (_availableFilters & kIOPacketFilterMulticastAll)
                    541:         {
                    542:             if (flags & IFF_ALLMULTI)
                    543:                 newFilters |= kIOPacketFilterMulticastAll;
                    544:             else
                    545:                 newFilters &= ~kIOPacketFilterMulticastAll;
                    546:         }
                    547:     }
                    548: 
                    549:     if (_setActiveFilters(newFilters))
                    550:     {
                    551:         ret = ctlr->doEnablePacketFilters(this, newFilters);    
                    552:         if (ret != kIOReturnSuccess)
                    553:             r = errnoFromReturn(ret);
                    554:     }
                    555: 
                    556:     // Update the flags field to pick up any modifications. Also update the
                    557:     // property table to reflect any flag changes.
                    558:     //
                    559:     setFlagsInt(flags, ~flags);
                    560: 
                    561:     return r;
                    562: }
                    563: 
                    564: //---------------------------------------------------------------------------
                    565: // Handles SIOCSIFADDR ioctl command for Ethernet interfaces.
                    566: 
                    567: SInt IOEthernetInterface::syncSIOCSIFADDR(IOEthernetController * ctlr)
                    568: {
                    569:     SInt    r = 0;
                    570:     UInt16  flags = getFlags();
                    571: 
                    572:     flags |= IFF_UP;
                    573:     
                    574:     if (!(flags & IFF_RUNNING))
                    575:     {
                    576:         r = errnoFromReturn(_enableController(ctlr));
                    577:         if (r == 0)
                    578:             flags |= IFF_RUNNING;
                    579:     }
                    580: 
                    581:     setFlagsInt(flags, ~flags);
                    582:     
                    583:     return r;
                    584: }
                    585: 
                    586: //---------------------------------------------------------------------------
                    587: // This method is called by syncSIOCADDMULTI() and syncSIOCDELMULTI() to
                    588: // reload the hardware's multicast filter whenever the multicast address
                    589: // list is changed. A OSData is published in the property table containing
                    590: // the multicast addresses.
                    591: 
                    592: IOReturn
                    593: IOEthernetInterface::_loadMulticastList(IOEthernetController * ctlr)
                    594: {
                    595:     enet_addr_t *        multiAddrs = 0;
                    596:     UInt                 mcount;
                    597:     OSData *             mcData = 0;
                    598:     struct ifnet *       ifp = (struct ifnet *) _arpcom;
                    599:     struct ifmultiaddr * ifma;
                    600:     IOReturn             ret;
                    601:     bool                 ok;
                    602: 
                    603:     assert(ifp);
                    604: 
                    605:     // Update the multicast addresses count ivar.
                    606:     //
                    607:     mcount = 0;
                    608:     for (ifma = ifp->if_multiaddrs.lh_first;
                    609:          ifma != NULL;
                    610:          ifma = ifma->ifma_link.le_next)
                    611:     {
                    612:         if ((ifma->ifma_addr->sa_family == AF_UNSPEC) ||
                    613:             (ifma->ifma_addr->sa_family == AF_LINK))
                    614:             mcount++;
                    615:     }
                    616:     _mcAddrCount = mcount;
                    617: 
                    618:     if (mcount)
                    619:     {
                    620:         char * addrp;
                    621:             
                    622:         mcData = OSData::withCapacity(mcount * NUM_EN_ADDR_BYTES);
                    623:         if (!mcData)
                    624:         {
                    625:             DLOG("%s: multicast memory allocation failed\n", getName());
                    626:             return kIOReturnNoMemory;
                    627:         }
                    628:         
                    629:         // Loop through the linked multicast structures and write the
                    630:         // address to the OSData.
                    631:         //
                    632:         for (ifma = ifp->if_multiaddrs.lh_first;
                    633:              ifma != NULL;
                    634:              ifma = ifma->ifma_link.le_next)
                    635:         {
                    636:             if (ifma->ifma_addr->sa_family == AF_UNSPEC) 
                    637:                 addrp = &ifma->ifma_addr->sa_data[0];
                    638:             else
                    639:                 if (ifma->ifma_addr->sa_family == AF_LINK)
                    640:                 addrp = LLADDR((struct sockaddr_dl *) ifma->ifma_addr);
                    641:                 else
                    642:                 continue;
                    643: 
                    644:             ok = mcData->appendBytes((const void *) addrp, NUM_EN_ADDR_BYTES);
                    645:             assert(ok);
                    646:         }
                    647: 
                    648:         multiAddrs = (enet_addr_t *) mcData->getBytesNoCopy();
                    649:         assert(multiAddrs);
                    650:     }
                    651: 
                    652:     // Call the controller's setMulticastList() method.
                    653:     //
                    654:     ret = ctlr->doSetMulticastList(this, multiAddrs, mcount);
                    655: 
                    656:     if (mcData)
                    657:     {
                    658:         if (ret == kIOReturnSuccess)
                    659:             setProperty(kIOMulticastAddresses, mcData);
                    660:         mcData->release();
                    661:     }
                    662:     else {
                    663:         removeProperty(kIOMulticastAddresses);
                    664:     }
                    665: 
                    666:     return ret;
                    667: }
                    668: 
                    669: //---------------------------------------------------------------------------
                    670: // Handles SIOCADDMULTI ioctl command.
                    671: 
                    672: SInt IOEthernetInterface::syncSIOCADDMULTI(IOEthernetController * ctlr)
                    673: {
                    674:     IOReturn  ret;
                    675:     UInt32    activatedFilters;
                    676:     SInt      r = 0;
                    677: 
                    678:     if (_availableFilters & kIOPacketFilterMulticast)
                    679:     {
                    680:         _setActiveFilters(_activeFilters | kIOPacketFilterMulticast);
                    681: 
                    682:         // Make sure the multicast filter is active.
                    683:         //
                    684:         ret = ctlr->doEnablePacketFilters(this, _activeFilters, 
                    685:                                           &activatedFilters);
                    686: 
                    687:         // If the controller did not activate the multicast filter,
                    688:         // report an error.
                    689:         //
                    690:         if ((activatedFilters & kIOPacketFilterMulticast) == 0)
                    691:         {
                    692:             assert(ret != kIOReturnSuccess);
                    693:             r = errnoFromReturn(ret);
                    694:         }
                    695: 
                    696:         // Do not load multicast list if the multicast filter
                    697:         // did not become active.
                    698:         //
                    699:         if (r == 0)
                    700:             r = errnoFromReturn(_loadMulticastList(ctlr));
                    701:     }
                    702:     else
                    703:         r = EOPNOTSUPP;   // no multicast support.
                    704: 
                    705:     return r;
                    706: }
                    707: 
                    708: //---------------------------------------------------------------------------
                    709: // Handles SIOCDELMULTI ioctl command.
                    710: 
                    711: SInt IOEthernetInterface::syncSIOCDELMULTI(IOEthernetController * ctlr)
                    712: {
                    713:     IOReturn  ret;
                    714:     UInt32    activatedFilters;
                    715:     SInt      r = 0;
                    716: 
                    717:     if (_availableFilters & kIOPacketFilterMulticast)
                    718:     {
                    719:         r = errnoFromReturn(_loadMulticastList(ctlr));
                    720: 
                    721:         if (r == 0)
                    722:         {
                    723:             // If the multicast list is now empty, instruct the controller
                    724:             // to turn off its multicast filter.
                    725: 
                    726:             if (_mcAddrCount == 0)
                    727:             {
                    728:                 _setActiveFilters(_activeFilters & ~kIOPacketFilterMulticast);
                    729: 
                    730:                 ret = ctlr->doEnablePacketFilters(this, _activeFilters,
                    731:                                                   &activatedFilters);
                    732: 
                    733:                 if (activatedFilters & kIOPacketFilterMulticast)
                    734:                 {
                    735:                     assert(ret != kIOReturnSuccess);
                    736:                     r = errnoFromReturn(ret);
                    737:                 }
                    738:             }
                    739:         }
                    740:     }
                    741:     else
                    742:         r = EOPNOTSUPP;   // no multicast support.
                    743: 
                    744:     return r;
                    745: }

unix.superglobalmegacorp.com

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