|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.