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