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 * IOFWInterface.cpp 26 * 27 */ 28 29#include <IOKit/assert.h> 30#include <IOKit/IOLib.h> 31#include <libkern/c++/OSData.h> 32#include "IOFWInterface.h" 33#include "IOFWController.h" 34//#include <IOKit/network/IONetworkUserClient.h> 35#include <IOKit/pwr_mgt/RootDomain.h> // publishFeature() 36 37extern "C" { 38#include <sys/param.h> 39#include <sys/errno.h> 40#include <sys/socket.h> 41#include <net/if.h> 42#include <firewire.h> 43#include <net/if_arp.h> 44#include <net/if_dl.h> 45#include <net/if_types.h> 46#include <net/dlil.h> 47#include <net/bpf.h> 48#include <net/kpi_protocol.h> 49 50#include <netinet/in.h> 51#include <netinet/in_var.h> 52#include <netinet/in_arp.h> 53#include <netinet/if_ether.h> 54 55#include <sys/sockio.h> 56#include <sys/malloc.h> 57} 58#include "if_firewire.h" 59 60#ifndef DLT_APPLE_IP_OVER_IEEE1394 61#define DLT_APPLE_IP_OVER_IEEE1394 138 62#endif 63 64//--------------------------------------------------------------------------- 65 66#define super IONetworkInterface 67 68OSDefineMetaClassAndStructors( IOFWInterface, IONetworkInterface ) 69OSMetaClassDefineReservedUnused( IOFWInterface, 0); 70OSMetaClassDefineReservedUnused( IOFWInterface, 1); 71OSMetaClassDefineReservedUnused( IOFWInterface, 2); 72OSMetaClassDefineReservedUnused( IOFWInterface, 3); 73OSMetaClassDefineReservedUnused( IOFWInterface, 4); 74OSMetaClassDefineReservedUnused( IOFWInterface, 5); 75OSMetaClassDefineReservedUnused( IOFWInterface, 6); 76OSMetaClassDefineReservedUnused( IOFWInterface, 7); 77OSMetaClassDefineReservedUnused( IOFWInterface, 8); 78OSMetaClassDefineReservedUnused( IOFWInterface, 9); 79OSMetaClassDefineReservedUnused( IOFWInterface, 10); 80OSMetaClassDefineReservedUnused( IOFWInterface, 11); 81OSMetaClassDefineReservedUnused( IOFWInterface, 12); 82OSMetaClassDefineReservedUnused( IOFWInterface, 13); 83OSMetaClassDefineReservedUnused( IOFWInterface, 14); 84OSMetaClassDefineReservedUnused( IOFWInterface, 15); 85 86// The name prefix for all BSD FireWire interfaces. 87// 88#define kIOFWInterfaceNamePrefix "fw" 89 90// Options used for enableFilter(), disableFilter(). 91enum { 92 kFilterOptionDeferIO = 0x0001, 93 kFilterOptionNotInsideGate = 0x0002, 94 kFilterOptionNoStateChange = 0x0004, 95 kFilterOptionDisableZeroBits = 0x0008, 96 kFilterOptionSyncPendingIO = 0x0010 97}; 98static u_long ivedonethis = 0; 99 100//--------------------------------------------------------------------------- 101// Macros 102 103#ifdef DEBUG 104#define DLOG(fmt, args...) IOLog(fmt, ## args) 105#else 106#define DLOG(fmt, args...) 107#endif 108 109UInt32 IOFWInterface::getFilters(const OSDictionary *dict, 110 const OSSymbol *group) 111{ 112 OSNumber * num; 113 UInt32 filters = 0; 114 115 assert( dict && group ); 116 117 if (( num = (OSNumber *) dict->getObject(group) )) 118 { 119 filters = num->unsigned32BitValue(); 120 } 121 return filters; 122} 123 124bool IOFWInterface::setFilters(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 IOFWInterface instance. Instance variables are 159// initialized 160bool IOFWInterface::init(IONetworkController *controller) 161{ 162 // Pass the init() call to our superclass. 163 if ( super::init(controller) == false ) 164 return false; 165 166 167 // initialize firewire specific fields. 168 setInterfaceType( IFT_IEEE1394 ); 169 setMaxTransferUnit( FIREWIREMTU ); 170 setMediaAddressLength( kIOFWAddressSize ); 171 setMediaHeaderLength( FIREWIRE_HDR_LEN ); 172 setFlags( IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS, 173 IFF_RUNNING | IFF_MULTICAST ); 174 175 176 // Add an IONetworkData with room to hold an IOFWStats structure. 177 // This class does not reference the data object created, and no harm 178 // is done if the data object is released or replaced. 179 180 IONetworkData * data = IONetworkData::withInternalBuffer( 181 kIOFWStatsKey, 182 sizeof(IOFWStats)); 183 if (data) 184 { 185 addNetworkData(data); 186 data->release(); 187 } 188 189 // Create and initialize the filter dictionaries. 190 191 _requiredFilters = OSDictionary::withCapacity(4); 192 _activeFilters = OSDictionary::withCapacity(4); 193 194 if ( (_requiredFilters == 0) || (_activeFilters == 0) ) 195 return false; 196 197 _supportedFilters = OSDynamicCast(OSDictionary, 198 controller->getProperty(kIOPacketFilters)); 199 if ( _supportedFilters == 0 ) return false; 200 _supportedFilters->retain(); 201 202 // Controller's Unicast (directed) and Broadcast filters should always 203 // be enabled. Those bits should never be cleared. 204 205 if ( !SET_REQUIRED_FILTERS( gIONetworkFilterGroup, 206 kIOPacketFilterUnicast | 207 kIOPacketFilterBroadcast ) 208 || !SET_REQUIRED_FILTERS( gIOEthernetWakeOnLANFilterGroup, 0 ) 209 || !SET_ACTIVE_FILTERS( gIONetworkFilterGroup, 0 ) 210 || !SET_ACTIVE_FILTERS( gIOEthernetWakeOnLANFilterGroup, 0 ) ) 211 { 212 return false; 213 } 214 215 // Publish filter dictionaries to property table. 216 217 setProperty( kIORequiredPacketFilters, _requiredFilters ); 218 setProperty( kIOActivePacketFilters, _activeFilters ); 219 220 _controller = controller; 221 222 return true; 223} 224 225//--------------------------------------------------------------------------- 226// Initialize the given ifnet structure. The argument specified is a pointer 227// to an ifnet structure obtained through getIfnet(). IOFWInterface 228// will initialize this structure in a manner that is appropriate for most 229// FireWire interfaces, then call super::initIfnet() to allow the superclass 230// to perform generic interface initialization. 231// 232// ifp: Pointer to the ifnet structure to be initialized. 233// 234// Returns true on success, false otherwise. 235int firewire_frameout(ifnet_t ifp, mbuf_t *m, 236 const struct sockaddr *ndest, const char *edst, const char *fw_type); 237int firewire_demux(ifnet_t ifp, mbuf_t m,char *frame_header,protocol_family_t *protocol_family); 238int firewire_add_proto(ifnet_t ifp, protocol_family_t protocol, const struct ifnet_demux_desc *demux_list, u_int32_t demux_count); 239int firewire_del_proto(ifnet_t ifp, protocol_family_t protocol_family); 240int firewire_add_if(ifnet_t ifp); 241 242bool IOFWInterface::initIfnetParams(struct ifnet_init_params *params) 243{ 244 //get the default values 245 super::initIfnetParams( params ); 246 247 _uniqueID = OSDynamicCast(OSData, getProvider()->getProperty(kIOMACAddress)); 248 if ( (_uniqueID == 0) || (_uniqueID->getLength() != kIOFWAddressSize) ) 249 { 250 DLOG("%s: kIOMACAddress property access error (len %d)\n", 251 getName(), _uniqueID ? _uniqueID->getLength() : 0); 252 return false; 253 } 254 255 // fill in firewire specific values 256 params->uniqueid = _uniqueID->getBytesNoCopy(); 257 params->uniqueid_len = _uniqueID->getLength(); 258 params->family = APPLE_IF_FAM_FIREWIRE; 259 params->demux = firewire_demux; 260 params->add_proto = firewire_add_proto; 261 params->del_proto = firewire_del_proto; 262 params->framer = firewire_frameout; 263 params->broadcast_addr = fwbroadcastaddr; 264 params->broadcast_len = sizeof(fwbroadcastaddr); 265 266 return true; 267} 268 269//--------------------------------------------------------------------------- 270// Free the IOFWInterface instance. 271int firewire_del_if(IOFWInterface *fwIf); 272 273void IOFWInterface::free() 274{ 275 struct ifnet *interface = (struct ifnet*)getIfnet(); 276 if ( interface ) 277 { 278 DLOG("%s%d: release ifnet %p\n", getNamePrefix(), getUnitNumber(), interface); 279 firewire_del_if( this ); 280 } 281 282 if ( _requiredFilters ) 283 { 284 _requiredFilters->release(); 285 _requiredFilters = 0; 286 } 287 288 if ( _activeFilters ) 289 { 290 _activeFilters->release(); 291 _activeFilters = 0; 292 } 293 294 if ( _supportedFilters ) 295 { 296 _supportedFilters->release(); 297 _supportedFilters = 0; 298 } 299 300 super::free(); 301} 302 303//--------------------------------------------------------------------------- 304// The name of the interface advertised to the network layer 305// is generated by concatenating the string returned by this method, 306// and an unit number. 307// 308// Returns a pointer to a constant string "fw". Thus FireWire interfaces 309// will be registered as fw0, fw1, etc. 310 311const char * IOFWInterface::getNamePrefix() const 312{ 313 return kIOFWInterfaceNamePrefix; 314} 315 316//--------------------------------------------------------------------------- 317// Prepare the 'FireWire' controller after it has been opened. This is called 318// by IONetworkInterface after a controller has accepted an open from this 319// interface. IOFWInterface uses this method to inspect the controller, 320// and to cache certain controller properties, such as its hardware address. 321// This method is called with the arbitration lock held. 322// 323// controller: The controller object that was opened. 324// 325// Returns true on success, false otherwise 326// (which will cause the controller to be closed). 327 328bool IOFWInterface::controllerDidOpen(IONetworkController * ctr) 329{ 330 bool ret = false; 331 OSData * addrData; 332 333 do { 334 // Call the controllerDidOpen() in superclass first. 335 336 if ( (ctr == 0) || (super::controllerDidOpen(ctr) == false) ) 337 break; 338 339 // If the controller supports some form of multicast filtering, 340 // then set the ifnet IFF_MULTICAST flag. 341 342 if ( GET_SUPPORTED_FILTERS(gIONetworkFilterGroup) & 343 (kIOPacketFilterMulticast | kIOPacketFilterMulticastAll) ) 344 { 345 setFlags(IFF_MULTICAST); 346 } 347 348 // Advertise Wake on Magic Packet feature if supported. 349 350 if ( GET_SUPPORTED_FILTERS( gIOEthernetWakeOnLANFilterGroup ) & 351 kIOFWWakeOnMagicPacket ) 352 { 353 IOPMrootDomain * root = getPMRootDomain(); 354 if ( root ) root->publishFeature( "WakeOnMagicPacket" ); 355 } 356 357 // Get the controller's MAC/FireWire address. 358 359 addrData = OSDynamicCast(OSData, ctr->getProperty(kIOMACAddress)); 360 if ((addrData == 0) || (addrData->getLength() != kIOFWAddressSize)) 361 { 362 DLOG("%s: kIOMACAddress property access error (len %d)\n", 363 getName(), addrData ? addrData->getLength() : 0); 364 break; 365 } 366 367 ret = true; 368 } 369 while (0); 370 371 return ret; 372} 373 374//--------------------------------------------------------------------------- 375// When a close from our last client is received, the interface will 376// close the controller. But before the controller is closed, this method 377// will be called by our superclass to perform any final cleanup. This 378// method is called with the arbitration lock held. 379// 380// IOFWInterface will ensure that the controller is disabled. 381// 382// controller: The currently opened controller object. 383 384void IOFWInterface::controllerWillClose(IONetworkController * ctr) 385{ 386 super::controllerWillClose(ctr); 387} 388 389//--------------------------------------------------------------------------- 390// Handle ioctl commands originated from the network layer. 391// Commands not handled by this method are passed to our superclass. 392// 393// Argument convention is: 394// 395// arg0 - (ifnet_t ) 396// arg1 - (void *) 397// 398// The commands handled by IOFWInterface are: 399// 400// SIOCSIFADDR 401// SIOCSIFFLAGS 402// SIOCADDMULTI 403// SIOCDELMULTI 404// 405// Returns an error code defined in errno.h (BSD). 406SInt32 IOFWInterface::performCommand( IONetworkController * ctr, 407 unsigned long cmd, 408 void * arg0, 409 void * arg1 ) 410{ 411 SInt32 ret; 412 413 if ( ctr == 0 ) return EINVAL; 414 415 switch ( cmd ) 416 { 417 case SIOCSIFFLAGS: 418 case SIOCADDMULTI: 419 case SIOCDELMULTI: 420 case SIOCSIFADDR: 421 case SIOCSIFMTU: 422 case SIOCSIFLLADDR: 423 ret = (int) ctr->executeCommand( 424 this, /* client */ 425 (IONetworkController::Action) 426 &IOFWInterface::performGatedCommand, 427 this, /* target */ 428 ctr, /* param0 */ 429 (void *) cmd, /* param1 */ 430 arg0, /* param2 */ 431 arg1 ); /* param3 */ 432 break; 433 434 default: 435 // Unknown command, let our superclass deal with it. 436 ret = super::performCommand(ctr, cmd, arg0, arg1); 437 break; 438 } 439 440 return ret; 441} 442 443//--------------------------------------------------------------------------- 444// Handle an ioctl command on the controller's workloop context. 445 446int IOFWInterface::performGatedCommand(void * target, 447 void * arg1_ctr, 448 void * arg2_cmd, 449 void * arg3_0, 450 void * arg4_1) 451{ 452 IOFWInterface *self = (IOFWInterface *) target; 453 IONetworkController *ctr = (IONetworkController *) arg1_ctr; 454 struct ifreq *ifr = (struct ifreq*) arg4_1; 455 SInt ret = EOPNOTSUPP; 456 457 // Refuse to perform controller I/O if the controller is in a 458 // low-power state that makes it "unusable". 459 460 if ( self->_controllerLostPower || 461 ( self->getInterfaceState() & kIONetworkInterfaceDisabledState ) ) 462 return EPWROFF; 463 464 switch ( (UInt64) arg2_cmd ) 465 { 466 case SIOCSIFADDR: 467 ret = self->syncSIOCSIFADDR(ctr); 468 break; 469 470 case SIOCSIFFLAGS: 471 ret = self->syncSIOCSIFFLAGS(ctr); 472 break; 473 474 case SIOCADDMULTI: 475 ret = self->syncSIOCADDMULTI(ctr); 476 break; 477 478 case SIOCDELMULTI: 479 ret = self->syncSIOCDELMULTI(ctr); 480 break; 481 482 case SIOCSIFMTU: 483 ret = self->syncSIOCSIFMTU( ctr, ifr ); 484 break; 485 486 case SIOCSIFLLADDR: 487 ret = self->syncSIOCSIFLLADDR( ctr, ifr->ifr_addr.sa_data, 488 ifr->ifr_addr.sa_len ); 489 break; 490 491 case SIOCGIFADDR: /* get ifnet address */ 492 struct sockaddr *sa = (struct sockaddr *) & ifr->ifr_data; 493 ret = self->syncSIOCGIFADDR( ctr, sa->sa_data, FIREWIRE_ADDR_LEN ); 494 break; 495 } 496 497 return ret; 498} 499 500//--------------------------------------------------------------------------- 501// enableController() is reponsible for calling the controller's enable() 502// method and restoring the state of the controller. We assume that 503// controllers can completely reset its state upon receiving a disable() 504// method call. And when it is brought back up, the interface should 505// assist in restoring the previous state of the FireWire controller. 506 507IOReturn IOFWInterface::enableController(IONetworkController * ctr) 508{ 509 IOReturn ret = kIOReturnSuccess; 510 bool enabled = false; 511 512 assert(ctr); 513 514 do { 515 // Is controller already enabled? If so, exit and return success. 516 517 if ( _ctrEnabled ) 518 break; 519 520 // Send the controller an enable command. 521 522 if ( (ret = ctr->doEnable(this)) != kIOReturnSuccess ) 523 break; // unable to enable the controller. 524 525 enabled = true; 526 527 // Disable all Wake-On-LAN filters. 528 529 disableFilter(ctr, gIOEthernetWakeOnLANFilterGroup, (UInt32)~0, kFilterOptionNoStateChange); 530 531 // Restore current filter selection. 532 533 SET_ACTIVE_FILTERS(gIONetworkFilterGroup, 0); 534 ret = enableFilter(ctr, gIONetworkFilterGroup, 0, 535 kFilterOptionSyncPendingIO); 536 if ( ret != kIOReturnSuccess ) break; 537 538 // Restore multicast filter settings. 539 540 syncSIOCADDMULTI(ctr); 541 542 // Re-apply the user supplied link-level address. 543 544 OSData * lladdr = OSDynamicCast(OSData, getProperty(kIOMACAddress)); 545 if ( lladdr && lladdr->getLength() == kIOFWAddressSize ) 546 { 547 ctr->setHardwareAddress( lladdr->getBytesNoCopy(), 548 lladdr->getLength() ); 549 } 550 551 _ctrEnabled = true; 552 553 } while (false); 554 555 // Disable the controller if a serious error has occurred after the 556 // controller has been enabled. 557 558 if ( enabled && (ret != kIOReturnSuccess) ) 559 { 560 ctr->doDisable(this); 561 } 562 563 return ret; 564} 565 566//--------------------------------------------------------------------------- 567// Handles SIOCSIFFLAGS ioctl command for FireWire interfaces. The network 568// stack has changed the if_flags field in ifnet. Our job is to go 569// through if_flags and see what has changed, and act accordingly. 570// 571// The fact that if_flags contains both generic and FireWire specific bits 572// means that we cannot move some of the default flag processing to the 573// superclass. 574 575int IOFWInterface::syncSIOCSIFFLAGS(IONetworkController * ctr) 576{ 577 UInt16 flags = getFlags(); 578 IOReturn ret = kIOReturnSuccess; 579 580 if ( ( ((flags & IFF_UP) == 0) || _controllerLostPower ) && 581 ( flags & IFF_RUNNING ) ) 582 { 583 // If interface is marked down and it is currently running, 584 // then stop it. 585 586 ctr->doDisable(this); 587 flags &= ~IFF_RUNNING; 588 _ctrEnabled = false; 589 } 590 else if ( ( flags & IFF_UP ) && 591 ( _controllerLostPower == false ) && 592 ((flags & IFF_RUNNING) == 0) ) 593 { 594 // If interface is marked up and it is currently stopped, 595 // then start it. 596 597 if ( (ret = enableController(ctr)) == kIOReturnSuccess ) 598 flags |= IFF_RUNNING; 599 } 600 601 if ( flags & IFF_RUNNING ) 602 { 603 IOReturn rc; 604 605 // We don't expect multiple flags to be changed for a given 606 // SIOCSIFFLAGS call. 607 608 // Promiscuous mode 609 610 rc = (flags & IFF_PROMISC) ? 611 enableFilter(ctr, gIONetworkFilterGroup, 612 kIOPacketFilterPromiscuous) : 613 disableFilter(ctr, gIONetworkFilterGroup, 614 kIOPacketFilterPromiscuous); 615 616 if (ret == kIOReturnSuccess) ret = rc; 617 618 // Multicast-All mode 619 620 rc = (flags & IFF_ALLMULTI) ? 621 enableFilter(ctr, gIONetworkFilterGroup, 622 kIOPacketFilterMulticastAll) : 623 disableFilter(ctr, gIONetworkFilterGroup, 624 kIOPacketFilterMulticastAll); 625 626 if (ret == kIOReturnSuccess) ret = rc; 627 } 628 629 // Update the flags field to pick up any modifications. Also update the 630 // property table to reflect any flag changes. 631 632 setFlags(flags, ~flags); 633 634 return errnoFromReturn(ret); 635} 636 637//--------------------------------------------------------------------------- 638// Handles SIOCSIFADDR ioctl. 639 640SInt IOFWInterface::syncSIOCSIFADDR(IONetworkController * ctr) 641{ 642 ifnet_t ifp = getIfnet(); 643 IOReturn ret = kIOReturnSuccess; 644 char lladdr[kIOFWAddressSize]; 645 646 if(ifp == NULL) 647 return (EINVAL); 648 649 IOFWAddress *addr = (IOFWAddress *) _uniqueID->getBytesNoCopy(); 650 651 bcopy(addr->bytes, lladdr, kIOFWAddressSize); 652 653 if(ifnet_set_lladdr(ifp, lladdr, kIOFWAddressSize) != 0) 654 DLOG("ifnet_set_lladdr failure in %s:%d", __FILE__, __LINE__); 655 656 // Interface is implicitly brought up by an SIOCSIFADDR ioctl. 657 setFlags(IFF_UP); 658 659 if ( (getFlags() & IFF_RUNNING) == 0 ) 660 { 661 if ( (ret = enableController(ctr)) == kIOReturnSuccess ) 662 { 663 setFlags(IFF_RUNNING); 664 665 ifaddr_t *addresses; 666 667 /* 668 * Also send gratuitous ARPs to notify other nodes about 669 * the address change. 670 */ 671 if (ifnet_get_address_list_family(ifp, &addresses, AF_INET) == 0) 672 { 673 int i; 674 675 for (i = 0; addresses[i] != NULL; i++) 676 inet_arp_init_ifaddr(ifp, addresses[i]); 677 678 ifnet_free_address_list(addresses); 679 } 680 } 681 } 682 683 return errnoFromReturn(ret); 684} 685 686//--------------------------------------------------------------------------- 687// Handle SIOCADDMULTI ioctl command. 688 689SInt IOFWInterface::syncSIOCADDMULTI(IONetworkController * ctr) 690{ 691 IOReturn ret; 692 693 // Make sure multicast filter is active. 694 695 ret = enableFilter(ctr, gIONetworkFilterGroup, kIOPacketFilterMulticast); 696 697 if ( ret == kIOReturnSuccess ) 698 { 699 // Load multicast addresses only if the filter was activated. 700 701 ret = setupMulticastFilter(ctr); 702 703 // If the list is now empty, then deactivate the multicast filter. 704 705 if ( _mcAddrCount == 0 ) 706 { 707 IOReturn dret = disableFilter(ctr, gIONetworkFilterGroup, 708 kIOPacketFilterMulticast); 709 710 if (ret == kIOReturnSuccess) ret = dret; 711 } 712 } 713 714 return errnoFromReturn(ret); 715} 716 717//--------------------------------------------------------------------------- 718// Handle SIOCDELMULTI ioctl command. 719 720SInt IOFWInterface::syncSIOCDELMULTI(IONetworkController * ctr) 721{ 722 return syncSIOCADDMULTI(ctr); 723} 724 725//--------------------------------------------------------------------------- 726// Handle SIOCSIFMTU ioctl. 727 728int IOFWInterface::syncSIOCSIFMTU( IONetworkController * ctr, 729 struct ifreq * ifr ) 730{ 731#define MTU_TO_FRAMESIZE(x) \ 732 ((x) + kIOFWCRCSize + sizeof(struct firewire_header)) 733 734 SInt32 error = 0; 735 UInt32 size; 736 UInt32 maxSize = kIOFWMaxPacketSize; // 1518 737 UInt32 ifrSize = MTU_TO_FRAMESIZE( ifr->ifr_mtu ); 738 UInt32 ctrSize = MTU_TO_FRAMESIZE( getMaxTransferUnit() ); 739 740 // If change is not necessary, return success without getting the 741 // controller involved. 742 743 if ( ctrSize == ifrSize ) 744 return 0; // no change required 745 746 if ( ctr->getMaxPacketSize( &size ) == kIOReturnSuccess ) 747 maxSize = max( size, kIOFWMaxPacketSize ); 748 749 if ( ifrSize > maxSize ) 750 return EINVAL; // MTU is too large for the controller. 751 752 // Message the controller if the new MTU requires a non standard 753 // frame size, or if the controller is currently programmed to 754 // support an extended frame size which is no longer required. 755 756 if ( max( ifrSize, ctrSize ) > kIOFWMaxPacketSize ) 757 { 758 IOReturn ret; 759 ret = ctr->setMaxPacketSize( max(ifrSize, kIOFWMaxPacketSize) ); 760 error = errnoFromReturn( ret ); 761 } 762 763 if ( error == 0 ) 764 { 765 // Success, update the MTU in ifnet. 766 setMaxTransferUnit( ifr->ifr_mtu ); 767 } 768 769 return error; 770} 771 772//--------------------------------------------------------------------------- 773 774int IOFWInterface::syncSIOCGIFADDR( IONetworkController * ctr, char * lladdr, int len ) 775{ 776 if( len != kIOFWAddressSize || lladdr == NULL ) 777 return EINVAL; 778 779 if ( _ctrEnabled != true ) /* reject if interface is down */ 780 return (ENETDOWN); 781 782 ifnet_lladdr_copy_bytes(getIfnet(), lladdr, len); 783 784 return 0; 785} 786 787int IOFWInterface::syncSIOCSIFLLADDR( IONetworkController * ctr, 788 const char * lladdr, int len ) 789{ 790 unsigned char tempaddr[kIOFWAddressSize]; 791 OSData *hardAddr; 792 793 if(len != kIOFWAddressSize) 794 return EINVAL; 795 796 if (_ctrEnabled != true) /* reject if interface is down */ 797 return (ENETDOWN); 798 799 // keep a backup in case stack refuses our change 800 hardAddr = OSDynamicCast(OSData, getProperty(kIOMACAddress)); 801 if(hardAddr && hardAddr->getLength() == kIOFWAddressSize) 802 bcopy(hardAddr->getBytesNoCopy(), tempaddr, kIOFWAddressSize); 803 804 // change the hardware- we do it before the stack, in case the stack 805 // needs to generate traffic as a result. 806 807 if ( ctr->setHardwareAddress( lladdr, len ) == kIOReturnSuccess ) 808 { 809 if( ifnet_set_lladdr(getIfnet(), lladdr, len) ) //uh-oh, stack didn't like this 810 { 811 // restore previous address 812 if(hardAddr) 813 ctr->setHardwareAddress(tempaddr, sizeof(tempaddr)); 814 return EINVAL; 815 } 816 817 setProperty(kIOMACAddress, (void *)lladdr, len); 818 819 DLOG("%s: SIOCSIFLLADDR %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", 820 ctr->getName(), 821 lladdr[0], lladdr[1], lladdr[2], lladdr[3], 822 lladdr[4], lladdr[5], lladdr[6], lladdr[7]); 823 } 824 825 return 0; 826} 827 828//--------------------------------------------------------------------------- 829// Enable a packet filter. 830 831#define getOneFilter(x) ((x) & (~((x) - 1))) 832 833IOReturn 834IOFWInterface::enableFilter(IONetworkController * ctr, 835 const OSSymbol * group, 836 UInt32 filters, 837 IOOptionBits options) 838{ 839 IOReturn ret = kIOReturnSuccess; 840 841 if ( options & kFilterOptionNotInsideGate ) 842 { 843 options &= ~kFilterOptionNotInsideGate; 844 845 return ctr->executeCommand( 846 this, /* client */ 847 OSMemberFunctionCast(IONetworkController::Action, this, &IOFWInterface::enableFilter), 848 this, /* target */ 849 (void *) ctr, /* param0 */ 850 (void *) group, /* param1 */ 851 (void *) filters, /* param2 */ 852 (void *) options ); /* param3 */ 853 } 854 855 if ( options & kFilterOptionDisableZeroBits ) 856 { 857 ret = disableFilter(ctr, group, ~filters, options); 858 if ( ret != kIOReturnSuccess) return ret; 859 } 860 861 // If the controller does not support the packet filter, 862 // there's no need to proceed. 863 864 if (( GET_SUPPORTED_FILTERS(group) & filters ) != filters) 865 return kIOReturnUnsupported; 866 867 do { 868 // Add new filter to the set of required filters. 869 870 UInt32 reqFilters = GET_REQUIRED_FILTERS(group) | filters; 871 UInt32 actFilters = GET_ACTIVE_FILTERS(group); 872 UInt32 resFilters = ( actFilters ^ reqFilters ); 873 874 if ( (options & kFilterOptionSyncPendingIO) == 0 ) 875 { 876 // Restrict filter update by using 'filters' as a mask. 877 resFilters &= filters; 878 } 879 880 while ( resFilters && ((options & kFilterOptionDeferIO) == 0) ) 881 { 882 UInt32 oneFilter = getOneFilter(resFilters); 883 884 // Send a command to the controller driver. 885 886 ret = ctr->enablePacketFilter(group, oneFilter, 887 actFilters, options); 888 if ( ret != kIOReturnSuccess ) break; 889 890 resFilters &= ~oneFilter; 891 actFilters |= oneFilter; 892 } 893 894 if ( (options & kFilterOptionNoStateChange) == 0 ) 895 SET_REQUIRED_FILTERS(group, reqFilters); 896 SET_ACTIVE_FILTERS(group, actFilters); 897 } 898 while (false); 899 900 return ret; 901} 902 903//--------------------------------------------------------------------------- 904// Disable a packet filter. 905 906IOReturn 907IOFWInterface::disableFilter(IONetworkController * ctr, 908 const OSSymbol * group, 909 UInt32 filters, 910 IOOptionBits options) 911{ 912 IOReturn ret = kIOReturnSuccess; 913 914 do { 915 // Remove specified filter from the set of required filters. 916 917 UInt32 reqFilters = GET_REQUIRED_FILTERS(group) & ~filters; 918 UInt32 actFilters = GET_ACTIVE_FILTERS(group); 919 UInt32 resFilters = ( actFilters ^ reqFilters ) & filters; 920 921 while ( resFilters && ((options & kFilterOptionDeferIO) == 0) ) 922 { 923 UInt32 oneFilter = getOneFilter(resFilters); 924 925 // Send a command to the controller driver. 926 927 ret = ctr->disablePacketFilter(group, oneFilter, 928 actFilters, options); 929 if ( ret != kIOReturnSuccess ) break; 930 931 resFilters &= ~oneFilter; 932 actFilters &= ~oneFilter; 933 } 934 935 if ( (options & kFilterOptionNoStateChange) == 0 ) 936 SET_REQUIRED_FILTERS(group, reqFilters); 937 SET_ACTIVE_FILTERS(group, actFilters); 938 } 939 while (false); 940 941 return ret; 942} 943 944//--------------------------------------------------------------------------- 945// Cache the list of multicast addresses and send a command to the 946// controller to update the multicast list. 947 948IOReturn 949IOFWInterface::setupMulticastFilter(IONetworkController * ctr) 950{ 951 void * multiAddrs = 0; 952 UInt mcount; 953 OSData * mcData = 0; 954 ifnet_t interface; 955 struct sockaddr dlAddress; 956 IOReturn ret = kIOReturnSuccess; 957 bool ok; 958 959 ifmultiaddr_t *addressList; 960 961 interface = getIfnet(); 962 963 assert(interface); 964 965 // get the list and count how many mcast link addresses there are 966 if(ifnet_get_multicast_list(interface, &addressList)) 967 return kIOReturnNoMemory; 968 969 mcount = 0; 970 for(int i=0; addressList[i]; i++) 971 { 972 ifmaddr_address(addressList[i], &dlAddress, sizeof(dlAddress)); 973 974 if (dlAddress.sa_family == AF_UNSPEC || dlAddress.sa_family == AF_LINK) 975 mcount++; 976 } 977 978 _mcAddrCount = mcount; 979 980 // now rewalk the list and copy the addresses to a format suitable to give to the controller 981 if ( mcount ) 982 { 983 char * addrp; 984 985 mcData = OSData::withCapacity(mcount * kIOFWAddressSize); 986 if (!mcData) 987 { 988 DLOG("%s: no memory for multicast address list\n", getName()); 989 return kIOReturnNoMemory; 990 } 991 992 // Loop through the list and copy the link multicast 993 // address to the OSData. 994 995 for(int i = 0; addressList[i]; i++) 996 { 997 //retrieve the datalink mcast address 998 ifmaddr_address(addressList[i], &dlAddress, sizeof(dlAddress)); 999 1000 if (dlAddress.sa_family == AF_UNSPEC) 1001 addrp = &dlAddress.sa_data[0]; 1002 else if (dlAddress.sa_family == AF_LINK) 1003 addrp = LLADDR((struct sockaddr_dl *)&dlAddress); 1004 else 1005 continue; 1006 1007 ok = mcData->appendBytes((const void *) addrp, kIOFWAddressSize); 1008 assert(ok); 1009 } 1010 1011 multiAddrs = (void *) mcData->getBytesNoCopy(); 1012 assert(multiAddrs); 1013 } 1014 1015 // Issue a controller command to setup the multicast filter. 1016 ret = ((IOFWController *)ctr)->setMulticastList((IOFWAddress *) multiAddrs, 1017 mcount); 1018 if (mcData) 1019 { 1020 if (ret == kIOReturnSuccess) 1021 setProperty(kIOMulticastAddressList, mcData); 1022 1023 mcData->release(); 1024 } 1025 else 1026 { 1027 removeProperty(kIOMulticastAddressList); 1028 } 1029 1030 ifnet_free_multicast_list(addressList); 1031 1032 return ret; 1033} 1034 1035//--------------------------------------------------------------------------- 1036// Power management support. 1037// 1038// Handlers called, with the controller's gate closed, in response to a 1039// controller power state change. 1040 1041IOReturn 1042IOFWInterface::controllerWillChangePowerState( 1043 IONetworkController * ctr, 1044 IOPMPowerFlags flags, 1045 UInt32 stateNumber, 1046 IOService * policyMaker ) 1047{ 1048 if ( ( (flags & IOPMDeviceUsable ) == 0) && 1049 ( _controllerLostPower == false ) && 1050 _ctrEnabled ) 1051 { 1052 unsigned long filters; 1053 1054 _controllerLostPower = true; 1055 1056 // Get the "aggressiveness" factor from the policy maker. 1057 1058 ctr->getAggressiveness( kPMEthernetWakeOnLANSettings, &filters ); 1059 1060 filters &= GET_SUPPORTED_FILTERS( gIOEthernetWakeOnLANFilterGroup ); 1061 1062 // Is the link up? If it is, leave the WOL filters intact, 1063 // otherwise mask out the WOL filters that would not function 1064 // without a proper link. This will reduce power consumption 1065 // for cases when a machine is put to sleep and there is no 1066 // network connection. 1067 1068 OSNumber * linkStatusNumber = (OSNumber *) 1069 ctr->getProperty( kIOLinkStatus ); 1070 1071 if ( ( linkStatusNumber == 0 ) || 1072 ( ( linkStatusNumber->unsigned32BitValue() & 1073 (kIONetworkLinkValid | kIONetworkLinkActive) ) == 1074 kIONetworkLinkValid ) ) 1075 { 1076 filters &= ~( kIOFWWakeOnMagicPacket | 1077 kIOFWWakeOnPacketAddressMatch ); 1078 } 1079 1080 // Before controller is disabled, program its wake up filters. 1081 // The WOL setting is formed by a bitwise OR between the WOL filter 1082 // settings, and the aggresiveness factor from the policy maker. 1083 1084 enableFilter( ctr, 1085 gIOEthernetWakeOnLANFilterGroup, 1086 filters, 1087 kFilterOptionNoStateChange | 1088 kFilterOptionSyncPendingIO ); 1089 1090 // Call SIOCSIFFLAGS handler to disable the controller, 1091 // and mark the interface as Not Running. 1092 1093 syncSIOCSIFFLAGS(ctr); 1094 } 1095 1096 return super::controllerWillChangePowerState( ctr, flags, 1097 stateNumber, 1098 policyMaker ); 1099} 1100 1101IOReturn 1102IOFWInterface::controllerDidChangePowerState( 1103 IONetworkController * ctr, 1104 IOPMPowerFlags flags, 1105 UInt32 stateNumber, 1106 IOService * policyMaker ) 1107{ 1108 IOReturn ret = super::controllerDidChangePowerState( ctr, flags, 1109 stateNumber, 1110 policyMaker ); 1111 1112 if ( ( flags & IOPMDeviceUsable ) && ( _controllerLostPower == true ) ) 1113 { 1114 _controllerLostPower = false; 1115 1116 // Clear _controllerLostPower, then call the SIOCSIFFLAGS handler to 1117 // perhaps enable the controller, restore all FireWire controller 1118 // state, then mark the interface as Running. 1119 1120 syncSIOCSIFFLAGS(ctr); 1121 } 1122 1123 return ret; 1124} 1125 1126#define kIONetworkInterfaceProperties "IONetworkInterfaceProperties" 1127 1128//--------------------------------------------------------------------------- 1129// Handle a request to set properties from kernel or non-kernel clients. 1130// For non-kernel clients, the preferred mechanism is through an user 1131// client. 1132 1133IOReturn IOFWInterface::setProperties( OSObject * properties ) 1134{ 1135 IOReturn ret; 1136 OSDictionary * dict = (OSDictionary *) properties; 1137 OSNumber * num; 1138 1139 // Call IONetworkInterface::setProperties() first. 1140 1141 ret = super::setProperties(properties); 1142 1143 if ( (ret == kIOReturnSuccess) || (ret == kIOReturnUnsupported) ) 1144 { 1145 dict = OSDynamicCast( OSDictionary, 1146 dict->getObject(kIONetworkInterfaceProperties) ); 1147 if ( dict ) 1148 { 1149 dict = OSDynamicCast( OSDictionary, 1150 dict->getObject(kIORequiredPacketFilters) ); 1151 if ( dict ) 1152 { 1153 num = OSDynamicCast( OSNumber, 1154 dict->getObject(kIOFWWakeOnLANFilterGroup) ); 1155 1156 if ( num ) 1157 { 1158 ret = enableFilter( getController(), 1159 gIOEthernetWakeOnLANFilterGroup, 1160 num->unsigned32BitValue(), 1161 kFilterOptionDeferIO | 1162 kFilterOptionNotInsideGate | 1163 kFilterOptionDisableZeroBits ); 1164 } 1165 } 1166 } 1167 } 1168 1169 return ret; 1170} 1171 1172//--------------------------------------------------------------------------- 1173// willTerminate 1174 1175bool IOFWInterface::willTerminate( IOService * provider, 1176 IOOptionBits options ) 1177{ 1178 bool ret = super::willTerminate( provider, options ); 1179 1180 // We assume that willTerminate() is always called from the 1181 // provider's work loop context. 1182 1183 // Once the gated ioctl path has been blocked, disable the controller. 1184 // The hardware may have already been removed from the system. 1185 1186 if ( _ctrEnabled && getController() ) 1187 { 1188 DLOG("IOFWInterface::willTerminate disabling controller\n"); 1189 getController()->doDisable( this ); 1190 _ctrEnabled = false; 1191 } 1192 1193 return ret; 1194} 1195 1196//--------------------------------------------------------------------------- 1197int firewire_init_if(ifnet_t ifp); 1198 1199IOReturn IOFWInterface::attachToDataLinkLayer( IOOptionBits options, 1200 void * parameter ) 1201{ 1202 IOReturn ret = 0; 1203 unsigned char lladdr[kIOFWAddressSize]; 1204 1205 ret = super::attachToDataLinkLayer( options, parameter ); 1206 if (ret == kIOReturnSuccess) 1207 { 1208 ifnet_set_baudrate(getIfnet(), 10000000); 1209 1210 bpfattach(getIfnet(), DLT_APPLE_IP_OVER_IEEE1394, sizeof(struct firewire_header) ); 1211 1212 IOFWAddress *addr = (IOFWAddress *) _uniqueID->getBytesNoCopy(); 1213 bcopy(addr->bytes, lladdr, kIOFWAddressSize); 1214 1215 if(ifnet_set_lladdr(getIfnet(), lladdr, kIOFWAddressSize) != 0) 1216 DLOG("ifnet_set_lladdr failure in %s:%d", __FILE__, __LINE__); 1217 1218 if (ivedonethis) 1219 { 1220 ivedonethis++; 1221 return kIOReturnSuccess; 1222 } 1223 1224 ivedonethis++; 1225 1226 // IPv4 proto register 1227 ret = proto_register_plumber(PF_INET, APPLE_IF_FAM_FIREWIRE, 1228 firewire_attach_inet, NULL); 1229 if(ret == EEXIST || ret == 0) 1230 ret = kIOReturnSuccess; 1231 else 1232 DLOG("ERROR: dlil_reg_proto_module for IPv4 over FIREWIRE %x", ret); 1233 1234 // IPv6 proto register 1235 ret = proto_register_plumber(PF_INET6, APPLE_IF_FAM_FIREWIRE, 1236 firewire_attach_inet6, NULL); 1237 if(ret == EEXIST || ret == 0) 1238 ret = kIOReturnSuccess; 1239 else 1240 DLOG("ERROR: dlil_reg_proto_module for IPv6 over FIREWIRE %x", ret); 1241 } 1242 1243 return ret; 1244} 1245 1246void IOFWInterface::detachFromDataLinkLayer( IOOptionBits options, 1247 void * parameter ) 1248{ 1249 if (ivedonethis == 1) 1250 { 1251 proto_unregister_plumber(PF_INET, APPLE_IF_FAM_FIREWIRE); 1252 proto_unregister_plumber(PF_INET6, APPLE_IF_FAM_FIREWIRE); 1253 } 1254 1255 ivedonethis--; 1256 1257 super::detachFromDataLinkLayer(options, parameter); 1258} 1259 1260void IOFWInterface::setIfnetMTU(UInt32 mtu) 1261{ 1262 setMaxTransferUnit(mtu-FIREWIRE_HDR_LEN); 1263} 1264 1265void IOFWInterface::setFamilyCookie(void *data) 1266{ 1267 _familyCookie = data; 1268} 1269