1/* 2 * Copyright (c) 1998-2008 Apple 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 * IOEthernetInterface.cpp 24 * 25 * HISTORY 26 * 8-Jan-1999 Joe Liu (jliu) created. 27 * 28 */ 29 30#include <IOKit/assert.h> 31#include <IOKit/IOLib.h> 32#include <libkern/c++/OSData.h> 33#include <IOEthernetInterface.h> 34#include <IOEthernetController.h> 35#include "IONetworkUserClient.h" 36#include "IONetworkDebug.h" 37#include "IONetworkControllerPrivate.h" 38 39#include <IOKit/pwr_mgt/RootDomain.h> // publishFeature() 40 41extern "C" { 42#include <sys/param.h> 43#include <sys/errno.h> 44#include <sys/socket.h> 45#include <sys/mbuf.h> 46#include <net/if.h> 47#include <net/ethernet.h> 48#include <net/if_ether.h> 49#include <net/if_arp.h> 50#include <net/if_dl.h> 51#include <net/if_types.h> 52#include <net/dlil.h> 53#include <net/bpf.h> 54#include <netinet/if_ether.h> 55#include <sys/sockio.h> 56#include <sys/malloc.h> 57} 58 59//--------------------------------------------------------------------------- 60 61#define super IONetworkInterface 62 63OSDefineMetaClassAndStructors( IOEthernetInterface, IONetworkInterface ) 64OSMetaClassDefineReservedUnused( IOEthernetInterface, 0); 65OSMetaClassDefineReservedUnused( IOEthernetInterface, 1); 66OSMetaClassDefineReservedUnused( IOEthernetInterface, 2); 67OSMetaClassDefineReservedUnused( IOEthernetInterface, 3); 68OSMetaClassDefineReservedUnused( IOEthernetInterface, 4); 69OSMetaClassDefineReservedUnused( IOEthernetInterface, 5); 70OSMetaClassDefineReservedUnused( IOEthernetInterface, 6); 71OSMetaClassDefineReservedUnused( IOEthernetInterface, 7); 72OSMetaClassDefineReservedUnused( IOEthernetInterface, 8); 73OSMetaClassDefineReservedUnused( IOEthernetInterface, 9); 74OSMetaClassDefineReservedUnused( IOEthernetInterface, 10); 75OSMetaClassDefineReservedUnused( IOEthernetInterface, 11); 76OSMetaClassDefineReservedUnused( IOEthernetInterface, 12); 77OSMetaClassDefineReservedUnused( IOEthernetInterface, 13); 78OSMetaClassDefineReservedUnused( IOEthernetInterface, 14); 79OSMetaClassDefineReservedUnused( IOEthernetInterface, 15); 80 81// The name prefix for all BSD Ethernet interfaces. 82// 83#define kIOEthernetInterfaceNamePrefix "en" 84 85// Options used for enableFilter(), disableFilter(). 86enum { 87 //kFilterOptionDeferIO = 0x0001, 88 //kFilterOptionNotInsideGate = 0x0002, 89 kFilterOptionNoStateChange = 0x0004, 90 //kFilterOptionDisableZeroBits = 0x0008, 91 kFilterOptionSyncPendingIO = 0x0010 92}; 93 94//--------------------------------------------------------------------------- 95// Macros 96 97#define _altMTU _reserved->altMTU 98#define _publishedFeatureID _reserved->publishedFeatureID 99#define _supportedWakeFilters _reserved->supportedWakeFilters 100#define _disabledWakeFilters _reserved->disabledWakeFilters 101#define _wompEnabledAssertionID _reserved->wompEnabledAssertionID 102 103#define kWOMPFeatureKey "WakeOnMagicPacket" 104 105UInt32 106IOEthernetInterface::getFilters( 107 const OSDictionary * dict, 108 const OSSymbol * group ) 109{ 110 OSNumber * num; 111 UInt32 filters = 0; 112 113 assert( dict && group ); 114 115 if (( num = (OSNumber *) dict->getObject(group) )) 116 { 117 filters = num->unsigned32BitValue(); 118 } 119 return filters; 120} 121 122bool 123IOEthernetInterface::setFilters( 124 OSDictionary * dict, 125 const OSSymbol * group, 126 UInt32 filters ) 127{ 128 OSNumber * num; 129 bool ret = false; 130 131 assert( dict && group ); 132 133 num = (OSNumber *) dict->getObject(group); 134 if ( num == 0 ) 135 { 136 if (( num = OSNumber::withNumber(filters, 32) )) 137 { 138 ret = dict->setObject(group, num); 139 num->release(); 140 } 141 } 142 else 143 { 144 num->setValue(filters); 145 ret = true; 146 } 147 return ret; 148} 149 150#define GET_REQUIRED_FILTERS(g) getFilters(_requiredFilters, (g)) 151#define GET_ACTIVE_FILTERS(g) getFilters(_activeFilters, (g)) 152#define GET_SUPPORTED_FILTERS(g) getFilters(_supportedFilters, (g)) 153 154#define SET_REQUIRED_FILTERS(g, v) setFilters(_requiredFilters, (g), (v)) 155#define SET_ACTIVE_FILTERS(g, v) setFilters(_activeFilters, (g), (v)) 156 157//--------------------------------------------------------------------------- 158// Initialize an IOEthernetInterface instance. Instance variables are 159// initialized 160 161bool IOEthernetInterface::init(IONetworkController * controller) 162{ 163 OSObject * obj; 164 165 _reserved = IONew( ExpansionData, 1 ); 166 if( _reserved == 0 ) 167 return false; 168 memset(_reserved, 0, sizeof(ExpansionData)); 169 170 if ( super::init(controller) == false ) 171 return false; 172 173 // initialize enet specific fields. 174 setInterfaceType(IFT_ETHER); 175 setMaxTransferUnit( ETHERMTU ); 176 setMediaAddressLength( ETHER_ADDR_LEN ); 177 setMediaHeaderLength( ETHER_HDR_LEN ); 178 setFlags( IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS, 179 IFF_RUNNING | IFF_MULTICAST ); 180 181 // Add an IONetworkData with room to hold an IOEthernetStats structure. 182 // This class does not reference the data object created, and no harm 183 // is done if the data object is released or replaced. 184 185 IONetworkData * data = IONetworkData::withInternalBuffer( 186 kIOEthernetStatsKey, 187 sizeof(IOEthernetStats)); 188 if (data) 189 { 190 addNetworkData(data); 191 data->release(); 192 } 193 194 _inputEventThreadCall = thread_call_allocate( 195 handleEthernetInputEvent, this ); 196 if (!_inputEventThreadCall) 197 return false; 198 199 // Create and initialize the filter dictionaries. 200 201 _requiredFilters = OSDictionary::withCapacity(2); 202 _activeFilters = OSDictionary::withCapacity(2); 203 204 if ( (_requiredFilters == 0) || (_activeFilters == 0) ) 205 return false; 206 207 obj = controller->copyProperty(kIOPacketFilters); 208 if (obj && ((_supportedFilters = OSDynamicCast(OSDictionary, obj)) == 0)) 209 obj->release(); 210 if (!_supportedFilters) 211 return false; 212 213 // Cache the bit mask of wake filters supported by the driver. 214 // This value will not change. 215 216 _supportedWakeFilters = GET_SUPPORTED_FILTERS( 217 gIOEthernetWakeOnLANFilterGroup ); 218 219 // Retain the Disabled WOL filters OSNumber. 220 // Its value will be updated live for link and WOL changed events. 221 222 obj = _supportedFilters->getObject( 223 gIOEthernetDisabledWakeOnLANFilterGroup ); 224 _disabledWakeFilters = OSDynamicCast(OSNumber, obj); 225 if (_disabledWakeFilters) 226 _disabledWakeFilters->retain(); 227 228 // Controller's Unicast (directed) and Broadcast filters should always 229 // be enabled. Those bits should never be cleared. 230 231 if ( !SET_REQUIRED_FILTERS( gIONetworkFilterGroup, 232 kIOPacketFilterUnicast | 233 kIOPacketFilterBroadcast ) 234 || !SET_REQUIRED_FILTERS( gIOEthernetWakeOnLANFilterGroup, 0 ) 235 || !SET_ACTIVE_FILTERS( gIONetworkFilterGroup, 0 ) 236 || !SET_ACTIVE_FILTERS( gIOEthernetWakeOnLANFilterGroup, 0 ) ) 237 { 238 return false; 239 } 240 241 _publishedFeatureID = 0; 242 243 // Publish filter dictionaries to property table. 244 245 setProperty( kIORequiredPacketFilters, _requiredFilters ); 246 setProperty( kIOActivePacketFilters, _activeFilters ); 247 248 return true; 249} 250 251static const u_char ether_broadcast_addr[ETHER_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 252 253bool IOEthernetInterface::initIfnetParams(struct ifnet_init_params *params) 254{ 255 OSData *uniqueID; 256 //get the default values 257 super::initIfnetParams( params ); 258 259 uniqueID = OSDynamicCast(OSData, getProvider()->getProperty(kIOMACAddress)); 260 if ( (uniqueID == 0) || (uniqueID->getLength() != ETHER_ADDR_LEN) ) 261 { 262 DLOG("%s: kIOMACAddress property access error (len %d)\n", 263 getName(), uniqueID ? uniqueID->getLength() : 0); 264 return false; 265 } 266 267 // fill in ethernet specific values 268 params->uniqueid = uniqueID->getBytesNoCopy(); 269 params->uniqueid_len = uniqueID->getLength(); 270 params->family = APPLE_IF_FAM_ETHERNET; 271 params->demux = ether_demux; 272 params->add_proto = ether_add_proto; 273 params->del_proto = ether_del_proto; 274 params->framer = ether_frameout; 275 params->check_multi = ether_check_multi; 276 params->broadcast_addr = ether_broadcast_addr; 277 params->broadcast_len = sizeof(ether_broadcast_addr); 278 return true; 279} 280 281//--------------------------------------------------------------------------- 282// Free the IOEthernetInterface instance. 283 284void IOEthernetInterface::free() 285{ 286 if ( _requiredFilters ) 287 { 288 _requiredFilters->release(); 289 _requiredFilters = 0; 290 } 291 292 if ( _activeFilters ) 293 { 294 _activeFilters->release(); 295 _activeFilters = 0; 296 } 297 298 if ( _supportedFilters ) 299 { 300 _supportedFilters->release(); 301 _supportedFilters = 0; 302 } 303 304 if ( _inputEventThreadCall ) 305 { 306 thread_call_free( _inputEventThreadCall ); 307 _inputEventThreadCall = 0; 308 } 309 310 if ( _reserved ) 311 { 312 if (kIOPMUndefinedDriverAssertionID != _wompEnabledAssertionID) 313 { 314 getPMRootDomain()->releasePMAssertion(_wompEnabledAssertionID); 315 _wompEnabledAssertionID = kIOPMUndefinedDriverAssertionID; 316 } 317 318 if (_disabledWakeFilters) 319 { 320 _disabledWakeFilters->release(); 321 _disabledWakeFilters = 0; 322 } 323 IODelete( _reserved, ExpansionData, 1 ); 324 _reserved = 0; 325 } 326 327 super::free(); 328} 329 330//--------------------------------------------------------------------------- 331// The name of the interface advertised to the network layer 332// is generated by concatenating the string returned by this method, 333// and an unit number. 334// 335// Returns a pointer to a constant string "en". Thus Ethernet interfaces 336// will be registered as en0, en1, etc. 337 338const char * IOEthernetInterface::getNamePrefix() const 339{ 340 return kIOEthernetInterfaceNamePrefix; 341} 342 343//--------------------------------------------------------------------------- 344// Prepare the 'Ethernet' controller after it has been opened. This is called 345// by IONetworkInterface after a controller has accepted an open from this 346// interface. IOEthernetInterface uses this method to inspect the controller, 347// and to cache certain controller properties, such as its hardware address. 348// This method is called with the arbitration lock held. 349// 350// controller: The controller object that was opened. 351// 352// Returns true on success, false otherwise 353// (which will cause the controller to be closed). 354 355bool IOEthernetInterface::controllerDidOpen(IONetworkController * ctr) 356{ 357 bool ret = false; 358 OSData * addrData; 359 IOEthernetAddress * addr; 360 361 do { 362 // Call the controllerDidOpen() in superclass first. 363 364 if ( (ctr == 0) || (super::controllerDidOpen(ctr) == false) ) 365 break; 366 367 // If the controller supports some form of multicast filtering, 368 // then set the ifnet IFF_MULTICAST flag. 369 370 if ( GET_SUPPORTED_FILTERS(gIONetworkFilterGroup) & 371 (kIOPacketFilterMulticast | kIOPacketFilterMulticastAll) ) 372 { 373 setFlags(IFF_MULTICAST); 374 } 375 376 // Advertise Wake on Magic Packet feature if supported. 377 378 if ( _supportedWakeFilters & kIOEthernetWakeOnMagicPacket ) 379 { 380 IOPMrootDomain * root = getPMRootDomain(); 381 if ( root ) root->publishFeature( kWOMPFeatureKey, 382 kIOPMSupportedOnAC | kIOPMSupportedOnUPS, 383 (uint32_t *)&_publishedFeatureID); 384 } 385 386 // Get the controller's MAC/Ethernet address. 387 388 addrData = OSDynamicCast(OSData, ctr->getProperty(kIOMACAddress)); 389 if ( (addrData == 0) || (addrData->getLength() != ETHER_ADDR_LEN) ) 390 { 391 DLOG("%s: kIOMACAddress property access error (len %d)\n", 392 getName(), addrData ? addrData->getLength() : 0); 393 break; 394 } 395 396 addr = (IOEthernetAddress *) addrData->getBytesNoCopy(); 397 398 DLOG("%s: Ethernet address %02x:%02x:%02x:%02x:%02x:%02x\n", 399 ctr->getName(), 400 addr->bytes[0], 401 addr->bytes[1], 402 addr->bytes[2], 403 addr->bytes[3], 404 addr->bytes[4], 405 addr->bytes[5]); 406 407 ret = true; 408 } 409 while (0); 410 411 return ret; 412} 413 414//--------------------------------------------------------------------------- 415// When a close from our last client is received, the interface will 416// close the controller. But before the controller is closed, this method 417// will be called by our superclass to perform any final cleanup. This 418// method is called with the arbitration lock held. 419// 420// IOEthernetInterface will ensure that the controller is disabled. 421// 422// controller: The currently opened controller object. 423 424void IOEthernetInterface::controllerWillClose(IONetworkController * ctr) 425{ 426 if ( _supportedWakeFilters & kIOEthernetWakeOnMagicPacket ) 427 { 428 IOPMrootDomain * root = getPMRootDomain(); 429 if ( root ) root->removePublishedFeature( _publishedFeatureID ); 430 _publishedFeatureID = 0; 431 } 432 433 super::controllerWillClose(ctr); 434} 435 436//--------------------------------------------------------------------------- 437// Handle ioctl commands originated from the network layer. 438// Commands not handled by this method are passed to our superclass. 439// 440// Argument convention is: 441// 442// arg0 - (struct ifnet *) 443// arg1 - (void *) 444// 445// The commands handled by IOEthernetInterface are: 446// 447// SIOCSIFADDR 448// SIOCSIFFLAGS 449// SIOCADDMULTI 450// SIOCDELMULTI 451// 452// Returns an error code defined in errno.h (BSD). 453 454SInt32 IOEthernetInterface::performCommand( IONetworkController * ctr, 455 unsigned long cmd, 456 void * arg0, 457 void * arg1 ) 458{ 459 SInt32 ret; 460 461 if ( ctr == 0 ) return EINVAL; 462 463 switch ( cmd ) 464 { 465 case SIOCSIFFLAGS: 466 case SIOCADDMULTI: 467 case SIOCDELMULTI: 468 case SIOCSIFADDR: 469 case SIOCSIFMTU: 470 case SIOCSIFDEVMTU: 471 case SIOCGIFDEVMTU: 472 case SIOCSIFLLADDR: 473 ret = (int) ctr->executeCommand( 474 this, /* client */ 475 (IONetworkController::Action) 476 &IOEthernetInterface::performGatedCommand, 477 this, /* target */ 478 ctr, /* param0 */ 479 (void *) cmd, /* param1 */ 480 arg0, /* param2 */ 481 arg1 ); /* param3 */ 482 break; 483 484 default: 485 // Unknown command, let our superclass deal with it. 486 ret = super::performCommand(ctr, cmd, arg0, arg1); 487 break; 488 } 489 490 return ret; 491} 492 493//--------------------------------------------------------------------------- 494// Handle an ioctl command on the controller's workloop context. 495 496int IOEthernetInterface::performGatedCommand(void * target, 497 void * arg1_ctr, 498 void * arg2_cmd, 499 void * arg3_0, 500 void * arg4_1) 501{ 502 IOEthernetInterface * self = (IOEthernetInterface *) target; 503 IONetworkController * ctr = (IONetworkController *) arg1_ctr; 504 struct ifreq * ifr = (struct ifreq *) arg4_1; 505 SInt ret = EOPNOTSUPP; 506 507 // Refuse to perform controller I/O if the controller is in a 508 // low-power state that makes it "unusable". 509 510 if ( self->_controllerLostPower || 511 ( self->getInterfaceState() & kIONetworkInterfaceDisabledState ) ) 512 return EPWROFF; 513 514 switch ( (uintptr_t) arg2_cmd ) 515 { 516 case SIOCSIFADDR: 517 ret = self->syncSIOCSIFADDR(ctr); 518 break; 519 520 case SIOCSIFFLAGS: 521 ret = self->syncSIOCSIFFLAGS(ctr); 522 break; 523 524 case SIOCADDMULTI: 525 ret = self->syncSIOCADDMULTI(ctr); 526 break; 527 528 case SIOCDELMULTI: 529 ret = self->syncSIOCDELMULTI(ctr); 530 break; 531 532 case SIOCSIFMTU: 533 ret = self->syncSIOCSIFMTU( ctr, ifr, 0 ); 534 break; 535 536 case SIOCSIFDEVMTU: 537 ret = self->syncSIOCSIFMTU(ctr, ifr, 1); 538 break; 539 540 case SIOCGIFDEVMTU: 541 ret = self->syncSIOCGIFDEVMTU(ctr, ifr); 542 break; 543 544 case SIOCSIFLLADDR: 545 ret = self->syncSIOCSIFLLADDR( ctr, ifr->ifr_addr.sa_data, 546 ifr->ifr_addr.sa_len ); 547 break; 548 } 549 550 return ret; 551} 552 553//--------------------------------------------------------------------------- 554// enableController() is reponsible for calling the controller's enable() 555// method and restoring the state of the controller. We assume that 556// controllers can completely reset its state upon receiving a disable() 557// method call. And when it is brought back up, the interface should 558// assist in restoring the previous state of the Ethernet controller. 559 560IOReturn IOEthernetInterface::enableController(IONetworkController * ctr) 561{ 562 IOReturn ret = kIOReturnSuccess; 563 bool enabled = false; 564 565 assert(ctr); 566 567 do { 568 // Is controller already enabled? If so, exit and return success. 569 570 if ( _ctrEnabled ) 571 break; 572 573 // Send the controller an enable command. 574 575 if ( (ret = ctr->doEnable(this)) != kIOReturnSuccess ) 576 break; // unable to enable the controller. 577 578 enabled = true; 579 580 // Disable all Wake-On-LAN filters. 581 582 disableFilter(ctr, gIOEthernetWakeOnLANFilterGroup, ~0, 583 kFilterOptionNoStateChange); 584 585 // Restore current filter selection. 586 587 SET_ACTIVE_FILTERS(gIONetworkFilterGroup, 0); 588 ret = enableFilter(ctr, gIONetworkFilterGroup, 0, 589 kFilterOptionSyncPendingIO); 590 if ( ret != kIOReturnSuccess ) break; 591 592 // Restore multicast filter settings. 593 594 syncSIOCADDMULTI(ctr); 595 596 // Re-apply the user supplied link-level address. 597 598 OSData * lladdr = OSDynamicCast(OSData, getProperty(kIOMACAddress)); 599 if ( lladdr && lladdr->getLength() == ETHER_ADDR_LEN ) 600 { 601 ctr->setHardwareAddress( lladdr->getBytesNoCopy(), 602 lladdr->getLength() ); 603 } 604 605 _ctrEnabled = true; 606 607 // Publish WOL support flags after interface is marked enabled. 608 609 reportInterfaceWakeFlags(ctr); 610 611 } while (false); 612 613 // Disable the controller if a serious error has occurred after the 614 // controller has been enabled. 615 616 if ( enabled && (ret != kIOReturnSuccess) ) 617 { 618 ctr->doDisable(this); 619 } 620 621 return ret; 622} 623 624//--------------------------------------------------------------------------- 625// Handles SIOCSIFFLAGS ioctl command for Ethernet interfaces. The network 626// stack has changed the if_flags field in ifnet. Our job is to go 627// through if_flags and see what has changed, and act accordingly. 628// 629// The fact that if_flags contains both generic and Ethernet specific bits 630// means that we cannot move some of the default flag processing to the 631// superclass. 632 633int IOEthernetInterface::syncSIOCSIFFLAGS(IONetworkController * ctr) 634{ 635 UInt16 flags = getFlags(); 636 IOReturn ret = kIOReturnSuccess; 637 638 if ( ( ((flags & IFF_UP) == 0) || _controllerLostPower ) && 639 ( flags & IFF_RUNNING ) ) 640 { 641 // If interface is marked down and it is currently running, 642 // then stop it. 643 644 ctr->doDisable(this); 645 flags &= ~IFF_RUNNING; 646 _ctrEnabled = false; 647 } 648 else if ( ( flags & IFF_UP ) && 649 ( _controllerLostPower == false ) && 650 ((flags & IFF_RUNNING) == 0) ) 651 { 652 // If interface is marked up and it is currently stopped, 653 // then start it. 654 655 if ( (ret = enableController(ctr)) == kIOReturnSuccess ) 656 flags |= IFF_RUNNING; 657 } 658 659 if ( flags & IFF_RUNNING ) 660 { 661 IOReturn rc; 662 663 // We don't expect multiple flags to be changed for a given 664 // SIOCSIFFLAGS call. 665 666 // Promiscuous mode 667 668 rc = (flags & IFF_PROMISC) ? 669 enableFilter(ctr, gIONetworkFilterGroup, 670 kIOPacketFilterPromiscuous) : 671 disableFilter(ctr, gIONetworkFilterGroup, 672 kIOPacketFilterPromiscuous); 673 674 if (ret == kIOReturnSuccess) ret = rc; 675 676 // Multicast-All mode 677 678 rc = (flags & IFF_ALLMULTI) ? 679 enableFilter(ctr, gIONetworkFilterGroup, 680 kIOPacketFilterMulticastAll) : 681 disableFilter(ctr, gIONetworkFilterGroup, 682 kIOPacketFilterMulticastAll); 683 684 if (ret == kIOReturnSuccess) ret = rc; 685 } 686 687 // Update the flags field to pick up any modifications. Also update the 688 // property table to reflect any flag changes. 689 690 setFlags(flags, ~flags); 691 692 return errnoFromReturn(ret); 693} 694 695//--------------------------------------------------------------------------- 696// Handles SIOCSIFADDR ioctl. 697 698SInt IOEthernetInterface::syncSIOCSIFADDR(IONetworkController * ctr) 699{ 700 IOReturn ret = kIOReturnSuccess; 701 702 // Interface is implicitly brought up by an SIOCSIFADDR ioctl. 703 704 setFlags(IFF_UP); 705 706 if ( (getFlags() & IFF_RUNNING) == 0 ) 707 { 708 if ( (ret = enableController(ctr)) == kIOReturnSuccess ) 709 setFlags(IFF_RUNNING); 710 } 711 712 return errnoFromReturn(ret); 713} 714 715//--------------------------------------------------------------------------- 716// Handle SIOCADDMULTI ioctl command. 717 718SInt IOEthernetInterface::syncSIOCADDMULTI(IONetworkController * ctr) 719{ 720 IOReturn ret; 721 722 // Make sure multicast filter is active. 723 724 ret = enableFilter(ctr, gIONetworkFilterGroup, kIOPacketFilterMulticast); 725 726 if ( ret == kIOReturnSuccess ) 727 { 728 // Load multicast addresses only if the filter was activated. 729 730 ret = setupMulticastFilter(ctr); 731 732 // If the list is now empty, then deactivate the multicast filter. 733 734 if ( _mcAddrCount == 0 ) 735 { 736 IOReturn dret = disableFilter(ctr, gIONetworkFilterGroup, 737 kIOPacketFilterMulticast); 738 739 if (ret == kIOReturnSuccess) ret = dret; 740 } 741 } 742 743 return errnoFromReturn(ret); 744} 745 746//--------------------------------------------------------------------------- 747// Handle SIOCDELMULTI ioctl command. 748 749SInt IOEthernetInterface::syncSIOCDELMULTI(IONetworkController * ctr) 750{ 751 return syncSIOCADDMULTI(ctr); 752} 753 754#define MTU_TO_FRAMESIZE(x) \ 755((x) + kIOEthernetCRCSize + sizeof(struct ether_header)) 756 757#define FRAMESIZE_TO_MTU(x) \ 758((x) - kIOEthernetCRCSize - sizeof(struct ether_header)) 759 760int IOEthernetInterface::syncSIOCGIFDEVMTU( IONetworkController * ctr, 761 struct ifreq * ifr ) 762{ 763 IOReturn ret; 764 UInt32 size; 765 766 ifr->ifr_devmtu.ifdm_current = max(_altMTU, getMaxTransferUnit()); 767 768 ret = ctr->getMaxPacketSize( &size ); 769 if(ret == kIOReturnSuccess ) 770 { 771 ifr->ifr_devmtu.ifdm_max = FRAMESIZE_TO_MTU(size); 772 ret = ctr->getMinPacketSize( &size ); 773 if(ret == kIOReturnSuccess) 774 ifr->ifr_devmtu.ifdm_min = FRAMESIZE_TO_MTU( size ); 775 } 776 return errnoFromReturn( ret ); 777} 778 779//--------------------------------------------------------------------------- 780// Handle SIOCSIFMTU ioctl. 781 782int IOEthernetInterface::syncSIOCSIFMTU( IONetworkController * ctr, 783 struct ifreq * ifr, 784 bool setAltMTU) 785{ 786 787 IOReturn ret = kIOReturnSuccess; 788 UInt32 newControllerMTU, oldControllerMTU; 789 UInt32 softMTU = getMaxTransferUnit(); 790 UInt32 requestedMTU = ifr->ifr_mtu; 791 792 UInt32 maxFrameSize = kIOEthernetMaxPacketSize; // 1518 793 UInt32 minFrameSize = kIOEthernetMinPacketSize; 794 UInt32 tempSize; 795 796 // Determine controller's max allowable mtu... 797 if ( ctr->getMaxPacketSize( &tempSize ) == kIOReturnSuccess ) 798 maxFrameSize = max( tempSize, kIOEthernetMaxPacketSize ); 799 800 // ...and reject requests that are too big. 801 if ( MTU_TO_FRAMESIZE( requestedMTU ) > maxFrameSize ) 802 return EINVAL; // MTU is too large for the controller. 803 804 // Determine controller's min allowable mtu... 805 ctr->getMinPacketSize( &minFrameSize ); 806 807 // ...and reject requests that are too small. 808 if ( MTU_TO_FRAMESIZE( requestedMTU ) < minFrameSize && !(setAltMTU && requestedMTU==0)) //allow setting dev MTU to 0 to turn it off 809 return EINVAL; // MTU is too small for the controller. 810 811 //the controller gets the max of the mtu we're changing and the one we're not. 812 newControllerMTU = max(requestedMTU, setAltMTU ? softMTU : _altMTU); 813 814 // determine what's currently set on the controller (the max of current soft and alt settings) 815 oldControllerMTU = max(softMTU, _altMTU); 816 817 // we only have to change the controller if the new value is different from the old, 818 // and either the new value is bigger than the standard max ethernet or the old value was. 819 if(newControllerMTU != oldControllerMTU && 820 ( (MTU_TO_FRAMESIZE(newControllerMTU) > kIOEthernetMaxPacketSize) || 821 (MTU_TO_FRAMESIZE(oldControllerMTU) > kIOEthernetMaxPacketSize) ) 822 ) 823 { 824 ret = ctr->setMaxPacketSize( max(MTU_TO_FRAMESIZE(newControllerMTU), kIOEthernetMaxPacketSize)); //don't set smaller than standard max ethernet 825 } 826 if(ret == kIOReturnSuccess) //if we successfully set value in controller (or didn't need to) then store the new value 827 { 828 829 if(setAltMTU) 830 _altMTU = requestedMTU; 831 else 832 setMaxTransferUnit( requestedMTU ); 833 } 834 return errnoFromReturn( ret ); 835} 836 837//--------------------------------------------------------------------------- 838 839int IOEthernetInterface::syncSIOCSIFLLADDR( IONetworkController * ctr, 840 const char * lladdr, int len ) 841{ 842 unsigned char tempaddr[kIOEthernetAddressSize]; 843 OSData *hardAddr; 844 845 if(len != kIOEthernetAddressSize) 846 return EINVAL; 847 848 if (_ctrEnabled != true) /* reject if interface is down */ 849 return (ENETDOWN); 850 // keep a backup in case stack refuses our change 851 hardAddr = OSDynamicCast(OSData, getProperty(kIOMACAddress)); 852 if(hardAddr && hardAddr->getLength() == kIOEthernetAddressSize) 853 bcopy(hardAddr->getBytesNoCopy(), tempaddr, kIOEthernetAddressSize); 854 855 // change the hardware- we do it before the stack, in case the stack 856 // needs to generate traffic as a result. 857 858 if ( ctr->setHardwareAddress( lladdr, len ) == kIOReturnSuccess ) 859 { 860 if( ifnet_set_lladdr(getIfnet(), lladdr, len) ) //uh-oh, stack didn't like this 861 { 862 // restore previous address 863 if(hardAddr) 864 ctr->setHardwareAddress(tempaddr, sizeof(tempaddr)); 865 return EINVAL; 866 } 867 868 setProperty(kIOMACAddress, (void *)lladdr, len); 869 870 DLOG("%s: SIOCSIFLLADDR %02x:%02x:%02x:%02x:%02x:%02x\n", 871 ctr->getName(), 872 lladdr[0], lladdr[1], lladdr[2], 873 lladdr[3], lladdr[4], lladdr[5]); 874 } 875 876 return 0; 877} 878 879//--------------------------------------------------------------------------- 880// Enable a packet filter. 881 882#define getOneFilter(x) ((x) & (~((x) - 1))) 883 884// this stub's sole purpose is to eliminate warning generated by gcc in enableFilter 885// when we try to cast a ptr to member function to a ptr to a 'C' function. 886 887IOReturn 888IOEthernetInterface::enableFilter_Wrapper( 889 IOEthernetInterface * self, 890 IONetworkController * ctr, 891 const OSSymbol * group, 892 UInt32 filters, 893 IOOptionBits options) 894{ 895 return self->enableFilter(ctr, group, filters, options); 896} 897 898IOReturn 899IOEthernetInterface::enableFilter(IONetworkController * ctr, 900 const OSSymbol * group, 901 UInt32 filters, 902 IOOptionBits options) 903{ 904 IOReturn ret = kIOReturnSuccess; 905 906 // If the controller does not support the packet filter, 907 // there's no need to proceed. 908 909 if (( GET_SUPPORTED_FILTERS(group) & filters ) != filters) 910 return kIOReturnUnsupported; 911 912 do { 913 // Add new filter to the set of required filters. 914 915 UInt32 reqFilters = GET_REQUIRED_FILTERS(group) | filters; 916 UInt32 actFilters = GET_ACTIVE_FILTERS(group); 917 UInt32 resFilters = ( actFilters ^ reqFilters ); 918 919 if ( (options & kFilterOptionSyncPendingIO) == 0 ) 920 { 921 // Restrict filter update by using 'filters' as a mask. 922 resFilters &= filters; 923 } 924 925 while ( resFilters ) 926 { 927 UInt32 oneFilter = getOneFilter(resFilters); 928 929 // Send a command to the controller driver. 930 931 ret = ctr->enablePacketFilter(group, oneFilter, 932 actFilters, options); 933 if ( ret != kIOReturnSuccess ) break; 934 935 resFilters &= ~oneFilter; 936 actFilters |= oneFilter; 937 } 938 939 if ( (options & kFilterOptionNoStateChange) == 0 ) 940 SET_REQUIRED_FILTERS(group, reqFilters); 941 SET_ACTIVE_FILTERS(group, actFilters); 942 } 943 while (false); 944 945 return ret; 946} 947 948//--------------------------------------------------------------------------- 949// Disable a packet filter. 950 951IOReturn 952IOEthernetInterface::disableFilter(IONetworkController * ctr, 953 const OSSymbol * group, 954 UInt32 filters, 955 IOOptionBits options) 956{ 957 IOReturn ret = kIOReturnSuccess; 958 959 do { 960 // Remove specified filter from the set of required filters. 961 962 UInt32 reqFilters = GET_REQUIRED_FILTERS(group) & ~filters; 963 UInt32 actFilters = GET_ACTIVE_FILTERS(group); 964 UInt32 resFilters = ( actFilters ^ reqFilters ) & filters; 965 966 while ( resFilters ) 967 { 968 UInt32 oneFilter = getOneFilter(resFilters); 969 970 // Send a command to the controller driver. 971 972 ret = ctr->disablePacketFilter(group, oneFilter, 973 actFilters, options); 974 if ( ret != kIOReturnSuccess ) break; 975 976 resFilters &= ~oneFilter; 977 actFilters &= ~oneFilter; 978 } 979 980 if ( (options & kFilterOptionNoStateChange) == 0 ) 981 SET_REQUIRED_FILTERS(group, reqFilters); 982 SET_ACTIVE_FILTERS(group, actFilters); 983 } 984 while (false); 985 986 return ret; 987} 988 989//--------------------------------------------------------------------------- 990// Cache the list of multicast addresses and send a command to the 991// controller to update the multicast list. 992 993IOReturn 994IOEthernetInterface::setupMulticastFilter(IONetworkController * ctr) 995{ 996 void * multiAddrs = 0; 997 UInt mcount; 998 OSData * mcData = 0; 999 ifnet_t interface; 1000 struct sockaddr dlAddress; 1001 IOReturn ret = kIOReturnSuccess; 1002 bool ok; 1003 ifmultiaddr_t *addressList; 1004 1005 interface = getIfnet(); 1006 1007 assert(interface); 1008 1009 // get the list and count how many mcast link addresses there are 1010 if(ifnet_get_multicast_list(interface, &addressList)) 1011 return kIOReturnNoMemory; 1012 mcount = 0; 1013 for(int i=0; addressList[i]; i++) 1014 { 1015 ifmaddr_address(addressList[i], &dlAddress, sizeof(dlAddress)); 1016 1017 if (dlAddress.sa_family == AF_UNSPEC || dlAddress.sa_family == AF_LINK) 1018 mcount++; 1019 } 1020 1021 _mcAddrCount = mcount; 1022 1023 // now rewalk the list and copy the addresses to a format suitable to give to the controller 1024 if ( mcount ) 1025 { 1026 char * addrp; 1027 1028 mcData = OSData::withCapacity(mcount * ETHER_ADDR_LEN); 1029 if (!mcData) 1030 { 1031 DLOG("%s: no memory for multicast address list\n", getName()); 1032 ifnet_free_multicast_list(addressList); 1033 return kIOReturnNoMemory; 1034 } 1035 1036 // Loop through the list and copy the link multicast 1037 // address to the OSData. 1038 for(int i = 0; addressList[i]; i++) 1039 { 1040 //retrieve the datalink mcast address 1041 ifmaddr_address(addressList[i], &dlAddress, sizeof(dlAddress)); 1042 1043 if (dlAddress.sa_family == AF_UNSPEC) 1044 addrp = &dlAddress.sa_data[0]; 1045 else if (dlAddress.sa_family == AF_LINK) 1046 addrp = LLADDR((struct sockaddr_dl *)&dlAddress); 1047 else 1048 continue; 1049 1050 ok = mcData->appendBytes((const void *) addrp, ETHER_ADDR_LEN); 1051 assert(ok); 1052 } 1053 1054 multiAddrs = (void *) mcData->getBytesNoCopy(); 1055 assert(multiAddrs); 1056 } 1057 1058 // Issue a controller command to setup the multicast filter. 1059 1060 ret = ((IOEthernetController *)ctr)->setMulticastList( 1061 (IOEthernetAddress *) multiAddrs, 1062 mcount); 1063 if (mcData) 1064 { 1065 if (ret == kIOReturnSuccess) 1066 setProperty(kIOMulticastAddressList, mcData); 1067 1068 mcData->release(); 1069 } 1070 else { 1071 removeProperty(kIOMulticastAddressList); 1072 } 1073 ifnet_free_multicast_list(addressList); 1074 return ret; 1075} 1076 1077//--------------------------------------------------------------------------- 1078// Power management support. 1079// 1080// Handlers called, with the controller's gate closed, in response to a 1081// controller power state change. 1082 1083IOReturn 1084IOEthernetInterface::controllerWillChangePowerState( 1085 IONetworkController * ctr, 1086 IOPMPowerFlags flags, 1087 UInt32 stateNumber, 1088 IOService * policyMaker ) 1089{ 1090 if ( ( (flags & IOPMDeviceUsable ) == 0) && 1091 ( _controllerLostPower == false ) ) 1092 { 1093 _controllerLostPower = true; 1094 1095 if (_ctrEnabled && !ctr->isInactive()) 1096 { 1097 if (policyMaker) 1098 { 1099 unsigned long filters; 1100 1101 // Called from PM instead of shutdown/restart context. 1102 // Get the "aggressiveness" factor from the policy maker. 1103 1104 ctr->getAggressiveness( kPMEthernetWakeOnLANSettings, &filters ); 1105 1106 filters &= _supportedWakeFilters; 1107 1108 // Is the link up? If it is, leave the WOL filters intact, 1109 // otherwise mask out the WOL filters that would not function 1110 // without a proper link. This will reduce power consumption 1111 // for cases when a machine is put to sleep and there is no 1112 // network connection. 1113 1114 OSNumber * linkStatusNumber = (OSNumber *) 1115 ctr->getProperty( kIOLinkStatus ); 1116 1117 if ( ( linkStatusNumber == 0 ) || 1118 ( ( linkStatusNumber->unsigned32BitValue() & 1119 (kIONetworkLinkValid | kIONetworkLinkActive) ) == 1120 kIONetworkLinkValid ) ) 1121 { 1122 filters &= ~( kIOEthernetWakeOnMagicPacket | 1123 kIOEthernetWakeOnPacketAddressMatch ); 1124 } 1125 1126 // Before controller is disabled, program its wake up filters. 1127 // The WOL setting is formed by a bitwise OR between the WOL filter 1128 // settings, and the aggresiveness factor from the policy maker. 1129 1130 enableFilter( ctr, 1131 gIOEthernetWakeOnLANFilterGroup, 1132 filters, 1133 kFilterOptionNoStateChange | 1134 kFilterOptionSyncPendingIO ); 1135 } 1136 1137 // Call SIOCSIFFLAGS handler to disable the controller, 1138 // and mark the interface as Not Running. 1139 1140 syncSIOCSIFFLAGS(ctr); 1141 } 1142 } 1143 1144 return super::controllerWillChangePowerState( ctr, flags, 1145 stateNumber, 1146 policyMaker ); 1147} 1148 1149IOReturn 1150IOEthernetInterface::controllerDidChangePowerState( 1151 IONetworkController * ctr, 1152 IOPMPowerFlags flags, 1153 UInt32 stateNumber, 1154 IOService * policyMaker ) 1155{ 1156 IOReturn ret = super::controllerDidChangePowerState( ctr, flags, 1157 stateNumber, 1158 policyMaker ); 1159 1160 if ( ( flags & IOPMDeviceUsable ) && ( _controllerLostPower == true ) ) 1161 { 1162 _controllerLostPower = false; 1163 1164 // Clear _controllerLostPower, then call the SIOCSIFFLAGS handler to 1165 // perhaps enable the controller, restore all Ethernet controller 1166 // state, then mark the interface as Running. 1167 1168 if (!ctr->isInactive()) 1169 syncSIOCSIFFLAGS(ctr); 1170 } 1171 1172 return ret; 1173} 1174 1175//--------------------------------------------------------------------------- 1176// willTerminate 1177 1178bool IOEthernetInterface::willTerminate( IOService * provider, 1179 IOOptionBits options ) 1180{ 1181 bool ret = super::willTerminate( provider, options ); 1182 1183 // willTerminate() is always called from the provider's work loop context. 1184 // But might be a different work loop than provider->getWorkLoop() 1185 1186 if (_ctrEnabled && (getController() == provider)) 1187 { 1188 DLOG("IOEthernetInterface::willTerminate disabling controller\n"); 1189 getController()->doDisable( this ); 1190 _ctrEnabled = false; 1191 } 1192 1193 return ret; 1194} 1195 1196//--------------------------------------------------------------------------- 1197 1198IOReturn IOEthernetInterface::attachToDataLinkLayer( IOOptionBits options, 1199 void * parameter ) 1200{ 1201 IOReturn ret = super::attachToDataLinkLayer( options, parameter ); 1202 if ( ret == kIOReturnSuccess ) 1203 { 1204 // on success, the interface is backed by an actual BSD ifnet_t. 1205 // now we can set a few important ethernet specific values on it. 1206 // Set defaults suitable for Ethernet interfaces. 1207 ifnet_set_baudrate(getIfnet(), 0); 1208 bpfattach( getIfnet(), DLT_EN10MB, sizeof(struct ether_header) ); 1209 } 1210 return ret; 1211} 1212 1213#define VLAN_HEADER_LEN 4 1214// Temporarily stuff a vlan tag back into a packet so that tag shows up to bpf. 1215// We do it by creating a temp header mbuf with the enet/vlan header in it and 1216// then point its next field to the proper place (after the dest+src addresses) in the original 1217// mbuf. 1218void IOEthernetInterface::_fixupVlanPacket(mbuf_t mt, u_int16_t vlan_tag, int inputPacket) 1219{ 1220 mbuf_t newmb; 1221 mbuf_t chain; 1222 size_t remainingBytes; 1223 size_t copyBytes = 0; //initialize to prevent annoying, incorrect warning that it's used uninitialized 1224 char * destptr; 1225 1226 if( mbuf_gethdr(MBUF_DONTWAIT, MT_DATA, &newmb) ) 1227 return; 1228 1229 //init enough of the mbuf to keep bpf happy 1230 mbuf_setlen(newmb, ETHER_ADDR_LEN*2 + VLAN_HEADER_LEN); 1231 mbuf_pkthdr_setlen(newmb, mbuf_pkthdr_len( mt ) + VLAN_HEADER_LEN); 1232 mbuf_pkthdr_setrcvif(newmb, mbuf_pkthdr_rcvif( mt ) ); 1233 1234 //now walk the incoming mbuf to copy out its dst & src address and 1235 //locate the type/len field in the packet. 1236 chain = mt; 1237 remainingBytes = ETHER_ADDR_LEN*2; 1238 destptr = (char *)mbuf_data( newmb ); 1239 1240 while(chain && remainingBytes) 1241 { 1242 copyBytes = remainingBytes > mbuf_len( chain ) ? mbuf_len( chain ): remainingBytes; 1243 1244 remainingBytes -= copyBytes; 1245 bcopy( mbuf_data( chain ), destptr, copyBytes); 1246 destptr += copyBytes; 1247 if (mbuf_len( chain ) == copyBytes) //we've completely drained this mbuf 1248 { 1249 chain = mbuf_next( chain ); //advance to next 1250 copyBytes = 0; //if we break out of loop now, make sure the offset is correct 1251 } 1252 } 1253 1254 // chain points to the mbuf that contains the packet data with type/len field 1255 // and copyBytes indicates the offset it's at. 1256 if(chain==0 || remainingBytes) 1257 { 1258 mbuf_freem( newmb ); 1259 return; //if we can't munge the packet, just return 1260 } 1261 1262 //patch mbuf so its data points after the dst+src address 1263 mbuf_setdata(chain, (char *)mbuf_data( chain ) + copyBytes, mbuf_len( chain ) - copyBytes ); 1264 1265 //finish setting up our head mbuf 1266 *(short *)(destptr) = htons(ETHERTYPE_VLAN); //vlan magic number 1267 *(short *)(destptr + 2) = htons( vlan_tag ); // and the tag's value 1268 mbuf_setnext( newmb, chain ); //stick it infront of the rest of the packet 1269 1270 // feed the tap 1271 if(inputPacket) 1272 super::feedPacketInputTap( newmb ); 1273 else 1274 super::feedPacketOutputTap( newmb ); 1275 1276 //release the fake header 1277 mbuf_setnext( newmb, NULL ); 1278 mbuf_freem( newmb ); 1279 1280 //and repair our old mbuf 1281 mbuf_setdata( chain, (char *)mbuf_data( chain ) - copyBytes, mbuf_len( chain ) + copyBytes ); 1282} 1283 1284//we need to feed the taps the packets as they appear 1285//on the wire...but devices with hardware vlan stuffing/stripping 1286//put that info oob. so we must munge the packet with the 1287//vlan, feed the tap, then unmunge it. 1288 1289void IOEthernetInterface::feedPacketInputTap(mbuf_t mt) 1290{ 1291 u_int16_t vlan; 1292 1293 if( mbuf_get_vlan_tag(mt, &vlan) == 0) //does this packet have oob vlan tag? 1294 _fixupVlanPacket(mt, vlan, 1); 1295 else 1296 super::feedPacketInputTap(mt); 1297} 1298 1299void IOEthernetInterface::feedPacketOutputTap(mbuf_t mt) 1300{ 1301 u_int16_t vlan; 1302 if( mbuf_get_vlan_tag(mt, &vlan) == 0) //does this packet have oob vlan tag? 1303 _fixupVlanPacket(mt, vlan, 0); 1304 else 1305 super::feedPacketOutputTap(mt); 1306} 1307 1308//--------------------------------------------------------------------------- 1309 1310bool IOEthernetInterface::inputEvent( UInt32 type, void * data ) 1311{ 1312 if ((type == kIONetworkEventTypeLinkUp) || 1313 (type == kIONetworkEventTypeLinkDown) || 1314 (type == kIONetworkEventWakeOnLANSupportChanged)) 1315 { 1316 IONetworkController * ctr = getController(); 1317 1318 if (ctr && !ctr->isInactive()) 1319 { 1320 // reportInterfaceWakeFlags() callout 1321 retain(); 1322 ctr->retain(); 1323 if (thread_call_enter( _inputEventThreadCall ) == TRUE) 1324 { 1325 release(); 1326 ctr->release(); 1327 } 1328 } 1329 } 1330 1331 if ((type == kIONetworkEventTypeLinkUp) || 1332 (type == kIONetworkEventTypeLinkDown)) 1333 { 1334 ifnet_t ifp = getIfnet(); 1335 const IONetworkLinkEventData * linkData = 1336 (const IONetworkLinkEventData *) data; 1337 1338 if (ifp && linkData) 1339 { 1340 if ((IOMediumGetNetworkType(linkData->linkType) == kIOMediumEthernet)) 1341 { 1342 // Ethernet drivers typically don't report link quality, 1343 // do it for them based on link status. 1344 if (type == kIONetworkEventTypeLinkUp) 1345 { 1346 ifnet_set_link_quality(ifp, IFNET_LQM_THRESH_GOOD); 1347 } 1348 else 1349 { 1350 ifnet_set_link_quality(ifp, IFNET_LQM_THRESH_OFF); 1351 } 1352 } 1353 } 1354 } 1355 1356 return super::inputEvent(type, data); 1357} 1358 1359void IOEthernetInterface::handleEthernetInputEvent( 1360 thread_call_param_t param0, 1361 thread_call_param_t /*param1 not used*/ ) 1362{ 1363 IOEthernetInterface * me = (IOEthernetInterface *) param0; 1364 IONetworkController * ctr; 1365 1366 if (me) 1367 { 1368 ctr = me->getController(); 1369 if (ctr) 1370 { 1371 ctr->executeCommand( 1372 me, /* client */ 1373 /* action */ 1374 OSMemberFunctionCast( 1375 IONetworkController::Action, me, 1376 &IOEthernetInterface::reportInterfaceWakeFlags), 1377 me, /* target */ 1378 ctr ); /* param0 */ 1379 1380 ctr->release(); 1381 } 1382 me->release(); 1383 } 1384} 1385 1386//--------------------------------------------------------------------------- 1387 1388void IOEthernetInterface::reportInterfaceWakeFlags( IONetworkController * ctr ) 1389{ 1390 ifnet_t ifnet; 1391 OSNumber * number; 1392 unsigned long wakeSetting = 0; 1393 uint32_t disabled = 0; 1394 uint32_t filters = 0; 1395 uint32_t linkStatus = 0; 1396 1397 ifnet = getIfnet(); 1398 1399 if (!ifnet || !ctr) 1400 return; 1401 1402 // Across system sleep/wake, link down is expected, this should 1403 // not trigger a wake flags changed. 1404 1405 if (_controllerLostPower) 1406 { 1407 DLOG("en%u: controllerLostPower\n", getUnitNumber()); 1408 return; 1409 } 1410 1411 do { 1412 // Report negative if controller is disabled or does not support WOL. 1413 1414 if (!_ctrEnabled || 1415 ((_supportedWakeFilters & kIOEthernetWakeOnMagicPacket) == 0)) 1416 { 1417 DLOG("en%u: ctrEnabled = %x, WakeFilters = %x\n", 1418 getUnitNumber(), _ctrEnabled, _supportedWakeFilters); 1419 break; 1420 } 1421 1422 // Poll for disabled WOL filters, which is allowed to change 1423 // after every link and WOL changed event. 1424 1425 if (_disabledWakeFilters) 1426 { 1427 if ( ctr->getPacketFilters( 1428 gIOEthernetDisabledWakeOnLANFilterGroup, 1429 (UInt32 *) &disabled ) != kIOReturnSuccess ) 1430 { 1431 disabled = 0; 1432 } 1433 _disabledWakeFilters->setValue( disabled ); 1434 } 1435 1436 // Check if network wake option is enabled, 1437 // that also implies system is on AC power. 1438 1439 getAggressiveness(kPMEthernetWakeOnLANSettings, &wakeSetting); 1440 filters = wakeSetting & _supportedWakeFilters & ~disabled; 1441 DLOG("en%u: WakeSetting = %lx, WakeFilters = %x, disabled = %x\n", 1442 getUnitNumber(), wakeSetting, _supportedWakeFilters, disabled); 1443 1444 if ((kIOEthernetWakeOnMagicPacket & filters) == 0) 1445 break; 1446 1447 // Check driver is reporting valid link. 1448 1449 number = OSDynamicCast(OSNumber, ctr->getProperty(kIOLinkStatus)); 1450 if (!number) 1451 { 1452 filters = 0; 1453 break; 1454 } 1455 1456 linkStatus = number->unsigned32BitValue(); 1457 if ((linkStatus & (kIONetworkLinkValid | kIONetworkLinkActive)) == 1458 kIONetworkLinkValid) 1459 { 1460 filters = 0; 1461 } 1462 } 1463 while (false); 1464 1465 filters &= IFNET_WAKE_ON_MAGIC_PACKET; 1466 if (filters != (ifnet_get_wake_flags(ifnet) & IFNET_WAKE_ON_MAGIC_PACKET)) 1467 { 1468 ifnet_set_wake_flags(ifnet, filters, IFNET_WAKE_ON_MAGIC_PACKET); 1469 DLOG("en%u: ifnet_set_wake_flags = %x\n", getUnitNumber(), filters); 1470 1471 // Lazy create of kernel assertion 1472 if (kIOPMUndefinedDriverAssertionID == _wompEnabledAssertionID) 1473 { 1474 _wompEnabledAssertionID = getPMRootDomain()->createPMAssertion( 1475 kIOPMDriverAssertionMagicPacketWakeEnabledBit, 1476 (filters & IFNET_WAKE_ON_MAGIC_PACKET) ? 1477 kIOPMDriverAssertionLevelOn : kIOPMDriverAssertionLevelOff, 1478 this, getName()); 1479 } 1480 else 1481 { 1482 getPMRootDomain()->setPMAssertionLevel(_wompEnabledAssertionID, 1483 (filters & IFNET_WAKE_ON_MAGIC_PACKET) ? 1484 kIOPMDriverAssertionLevelOn : kIOPMDriverAssertionLevelOff); 1485 } 1486 } 1487} 1488