2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
25 * IONetworkInterface.cpp
28 * 8-Jan-1999 Joe Liu (jliu) created.
32 #include <IOKit/assert.h>
33 #include <IOKit/IOLib.h>
34 #include <IOKit/IOBSD.h>
35 #include <IOKit/network/IONetworkInterface.h>
36 #include <IOKit/network/IONetworkController.h>
37 #include <IOKit/network/IONetworkUserClient.h>
38 #include <IOKit/network/IONetworkStack.h>
41 #include <sys/param.h>
43 #include <sys/socket.h>
44 #include <sys/sockio.h>
47 #include <netinet/if_ether.h>
48 #include <net/if_media.h>
50 int copyout(void *kaddr
, void *udaddr
, size_t len
);
53 #include <sys/kern_event.h>
54 int dlil_event(struct ifnet
*ifp
, struct kern_event_msg
*event
);
58 //---------------------------------------------------------------------------
60 #define super IOService
62 OSDefineMetaClassAndAbstractStructors( IONetworkInterface
, IOService
)
63 OSMetaClassDefineReservedUnused( IONetworkInterface
, 0);
64 OSMetaClassDefineReservedUnused( IONetworkInterface
, 1);
65 OSMetaClassDefineReservedUnused( IONetworkInterface
, 2);
66 OSMetaClassDefineReservedUnused( IONetworkInterface
, 3);
67 OSMetaClassDefineReservedUnused( IONetworkInterface
, 4);
68 OSMetaClassDefineReservedUnused( IONetworkInterface
, 5);
69 OSMetaClassDefineReservedUnused( IONetworkInterface
, 6);
70 OSMetaClassDefineReservedUnused( IONetworkInterface
, 7);
71 OSMetaClassDefineReservedUnused( IONetworkInterface
, 8);
72 OSMetaClassDefineReservedUnused( IONetworkInterface
, 9);
73 OSMetaClassDefineReservedUnused( IONetworkInterface
, 10);
74 OSMetaClassDefineReservedUnused( IONetworkInterface
, 11);
75 OSMetaClassDefineReservedUnused( IONetworkInterface
, 12);
76 OSMetaClassDefineReservedUnused( IONetworkInterface
, 13);
77 OSMetaClassDefineReservedUnused( IONetworkInterface
, 14);
78 OSMetaClassDefineReservedUnused( IONetworkInterface
, 15);
80 //---------------------------------------------------------------------------
84 #define DLOG(fmt, args...) IOLog(fmt, ## args)
86 #define DLOG(fmt, args...)
89 //---------------------------------------------------------------------------
90 // Initialize an IONetworkInterface instance.
92 // Returns true if initialized successfully, false otherwise.
94 bool IONetworkInterface::init(IONetworkController
* controller
)
96 // Propagate the init() call to our superclass.
98 if ( super::init() == false )
101 // The controller object provided must be valid.
103 if ( OSDynamicCast(IONetworkController
, controller
) == 0 )
106 _controller
= controller
;
108 // Create interface lock to serialize ifnet updates.
110 _ifLock
= IORecursiveLockAlloc();
114 // Create an OSNumber to store interface state bits.
116 _stateBits
= OSNumber::withNumber((UInt64
) 0, 32);
117 if ( _stateBits
== 0 )
119 setProperty( kIOInterfaceState
, _stateBits
);
121 // Create an OSSet to store client objects. Initial capacity
122 // (which can grow) is set at 2 clients.
124 _clientSet
= OSSet::withCapacity(2);
125 if ( _clientSet
== 0 )
128 // Get the ifnet structure of the network interface. Subclasses must
129 // implement getIfnet() and expect this function to be called when
130 // they call IONetworkInterface::init().
135 DLOG("%s: getIfnet() returned NULL\n", getName());
139 // Intialize the ifnet structure.
141 if ( initIfnet(_ifp
) == false )
144 // Create a data dictionary.
146 if ( (_dataDict
= OSDictionary::withCapacity(5)) == 0 )
149 IONetworkData
* data
= IONetworkData::withExternalBuffer(
151 sizeof(IONetworkStats
),
152 (UInt8
*) &(_ifp
->if_data
.ifi_ipackets
));
155 addNetworkData(data
);
159 // Register default output handler.
161 if ( registerOutputHandler( controller
,
162 controller
->getOutputHandler() ) == false )
167 // Set the kIOInterfaceNamePrefix and kIOPrimaryInterface properties.
168 // These may be used by an user space agent as hints when assigning a
169 // BSD name for the interface.
171 setProperty( kIOInterfaceNamePrefix
, getNamePrefix() );
172 setProperty( kIOPrimaryInterface
, isPrimaryInterface() );
177 //---------------------------------------------------------------------------
178 // Destroy the interface. Release all allocated resources.
180 void IONetworkInterface::free()
182 DLOG("IONetworkInterface::free()\n");
186 // Should not have any clients.
187 assert(_clientSet
->getCount() == 0);
188 _clientSet
->release();
192 if ( _dataDict
) { _dataDict
->release(); _dataDict
= 0; }
193 if ( _stateBits
) { _stateBits
->release(); _stateBits
= 0; }
197 IORecursiveLockFree(_ifLock
);
206 //---------------------------------------------------------------------------
207 // Returns true if the receiver of this method is the system's primary
208 // network interface.
210 bool IONetworkInterface::isPrimaryInterface() const
212 IOService
* provider
= getController();
213 bool isPrimary
= false;
215 if ( provider
) provider
= provider
->getProvider();
217 // FIXME: Should rely on a single property, and the platform
218 // expert should patch the device tree if necessary to make
222 ( provider
->getProperty( "AAPL,slot-name" ) == 0 ) &&
223 ( provider
->getProperty( "built-in" ) ||
224 provider
->getProperty( "AAPL,connector" ) ||
225 ( strcmp( provider
->getName(), "ethernet" ) == 0 ) ) )
233 //---------------------------------------------------------------------------
234 // Get the IONetworkCotroller object that is servicing this interface.
236 IONetworkController
* IONetworkInterface::getController() const
241 #ifdef HW_CSUM_SUPPORT
242 //---------------------------------------------------------------------------
243 // Get the value that should be set in the hwassist field in the ifnet
244 // structure. Currently, this field is solely used for advertising the
245 // hardware checksumming support.
247 static UInt32
getIfnetHardwareAssistValue( IONetworkController
* ctr
)
254 if ( ctr
->getChecksumSupport(
256 IONetworkController::kChecksumFamilyTCPIP
,
257 false ) != kIOReturnSuccess
) break;
259 if ( ctr
->getChecksumSupport(
261 IONetworkController::kChecksumFamilyTCPIP
,
262 true ) != kIOReturnSuccess
) break;
264 if ( input
& output
& IONetworkController::kChecksumIP
)
269 if ( ( input
& ( IONetworkController::kChecksumTCP
|
270 IONetworkController::kChecksumTCPNoPseudoHeader
) )
271 && ( output
& ( IONetworkController::kChecksumTCP
|
272 IONetworkController::kChecksumTCPSum16
) ) )
274 hwassist
|= CSUM_TCP
;
277 if ( ( input
& ( IONetworkController::kChecksumUDP
|
278 IONetworkController::kChecksumUDPNoPseudoHeader
) )
279 && ( output
& ( IONetworkController::kChecksumUDP
|
280 IONetworkController::kChecksumTCPSum16
) ) )
282 hwassist
|= CSUM_UDP
;
289 #endif HW_CSUM_SUPPORT
291 //---------------------------------------------------------------------------
292 // Initialize the ifnet structure.
294 bool IONetworkInterface::initIfnet(struct ifnet
* ifp
)
298 // Register our 'shim' functions. These function pointers
299 // points to static member functions inside this class.
301 ifp
->if_output
= output_shim
;
302 ifp
->if_ioctl
= ioctl_shim
;
303 ifp
->if_set_bpf_tap
= set_bpf_tap_shim
;
304 ifp
->if_private
= this;
305 ifp
->if_free
= &IONetworkStack::bsdInterfaceWasUnregistered
;
306 ifp
->if_name
= (char *) getNamePrefix();
313 //---------------------------------------------------------------------------
314 // Implement family specific matching.
316 bool IONetworkInterface::matchPropertyTable(OSDictionary
* table
,
319 return super::matchPropertyTable(table
, score
);
322 //---------------------------------------------------------------------------
323 // Take the interface lock.
325 void IONetworkInterface::lock()
327 IORecursiveLockLock(_ifLock
);
330 //---------------------------------------------------------------------------
331 // Release the interface lock.
333 void IONetworkInterface::unlock()
335 IORecursiveLockUnlock(_ifLock
);
338 //---------------------------------------------------------------------------
339 // Inspect the controller after it has been opened.
341 bool IONetworkInterface::controllerDidOpen(IONetworkController
* controller
)
343 return true; // by default, always accept the controller open.
346 //---------------------------------------------------------------------------
347 // Perform cleanup before the controller is closed.
349 void IONetworkInterface::controllerWillClose(IONetworkController
* controller
)
353 //---------------------------------------------------------------------------
354 // Handle a client open on the interface.
356 bool IONetworkInterface::handleOpen(IOService
* client
,
357 IOOptionBits options
,
361 bool controllerOpen
= false;
364 // Was this object already registered as our client?
366 if ( _clientSet
->containsObject(client
) )
368 DLOG("%s: multiple opens from client %lx\n",
369 getName(), (UInt32
) client
);
374 // If the interface has not received a client open, which also
375 // implies that the interface has not yet opened the controller,
376 // then open the controller upon receiving the first open from
377 // a client. If the controller open fails, the client open will
380 if ( ( getInterfaceState() & kIONetworkInterfaceOpenedState
) == 0 )
382 if ( ( (controllerOpen
= _controller
->open(this)) == false ) ||
383 ( controllerDidOpen(_controller
) == false ) )
387 // Qualify the client.
389 if ( handleClientOpen(client
, options
, argument
) == false )
392 // Add the new client object to our client set.
394 if ( _clientSet
->setObject(client
) == false )
396 handleClientClose(client
, 0);
404 // If provider was opened above, but an error has caused us to refuse
405 // the client open, then close our provider.
407 if ( controllerOpen
)
411 setInterfaceState( kIONetworkInterfaceOpenedState
);
412 _controller
->registerInterestedDriver( this );
415 controllerWillClose(_controller
);
416 _controller
->close(this);
423 //---------------------------------------------------------------------------
424 // Handle a client close on the interface.
426 void IONetworkInterface::handleClose(IOService
* client
, IOOptionBits options
)
428 // Remove the object from the client OSSet.
430 if ( _clientSet
->containsObject(client
) )
432 // Call handleClientClose() to handle the client close.
434 handleClientClose( client
, options
);
436 // If this is the last client, then close our provider.
438 if ( _clientSet
->getCount() == 1 )
440 _controller
->deRegisterInterestedDriver( this );
441 controllerWillClose( _controller
);
442 _controller
->close( this );
443 setInterfaceState( 0, kIONetworkInterfaceOpenedState
);
446 // Remove the client from our OSSet.
448 _clientSet
->removeObject(client
);
452 //---------------------------------------------------------------------------
453 // Query whether a client has an open on the interface.
455 bool IONetworkInterface::handleIsOpen(const IOService
* client
) const
458 return _clientSet
->containsObject(client
);
460 return (_clientSet
->getCount() > 0);
463 //---------------------------------------------------------------------------
464 // Handle a client open on the interface.
466 bool IONetworkInterface::handleClientOpen(IOService
* client
,
467 IOOptionBits options
,
470 if ( OSDynamicCast(IONetworkStack
, client
) )
472 // Transition state to registered interface.
474 setInterfaceState( kIONetworkInterfaceRegisteredState
);
479 //---------------------------------------------------------------------------
480 // Handle a client close on the interface.
482 void IONetworkInterface::handleClientClose(IOService
* client
,
483 IOOptionBits options
)
485 if ( OSDynamicCast(IONetworkStack
, client
) )
487 // Transition state to unregistered interface.
489 setInterfaceState( 0, kIONetworkInterfaceRegisteredState
);
493 //---------------------------------------------------------------------------
494 // Register the output packet handler.
496 bool IONetworkInterface::registerOutputHandler(OSObject
* target
,
497 IOOutputAction action
)
501 // Sanity check on the arguments.
503 if ( (getInterfaceState() & kIONetworkInterfaceRegisteredState
) ||
518 //---------------------------------------------------------------------------
519 // Feed packets to the input/output BPF packet filter taps.
521 static inline void _feedPacketTap(struct ifnet
* ifp
,
526 if (func
) func(ifp
, m
);
529 //---------------------------------------------------------------------------
530 // Called by a network controller to submit a single packet received from
531 // the network to the data link layer.
533 #define IN_Q_ENQUEUE(m) \
535 if (_inputQHead == 0) { \
536 _inputQHead = _inputQTail = (m); \
539 _inputQTail->m_nextpkt = (m) ; \
545 #define DLIL_INPUT(m_head, m_tail) \
548 dlil_input(_ifp, (m_head), (m_tail)); \
552 UInt32
IONetworkInterface::flushInputQueue()
554 UInt32 count
= _inputQCount
;
556 DLIL_INPUT(_inputQHead
, _inputQTail
);
557 _inputQHead
= _inputQTail
= 0;
563 UInt32
IONetworkInterface::clearInputQueue()
565 UInt32 count
= _inputQCount
;
567 m_freem_list( _inputQHead
);
569 _inputQHead
= _inputQTail
= 0;
575 UInt32
IONetworkInterface::inputPacket(struct mbuf
* pkt
,
577 IOOptionBits options
= 0,
584 // Set the source interface and length of the received frame.
588 if ( pkt
->m_next
== 0 )
590 pkt
->m_pkthdr
.len
= pkt
->m_len
= length
;
594 struct mbuf
* m
= pkt
;
595 pkt
->m_pkthdr
.len
= length
;
597 if (length
< (UInt32
) m
->m_len
)
600 } while (( m
= m
->m_next
));
605 pkt
->m_pkthdr
.rcvif
= _ifp
;
607 // Increment input byte count.
609 _ifp
->if_ibytes
+= pkt
->m_pkthdr
.len
;
613 _feedPacketTap(_ifp
, pkt
, _inputFilterFunc
, BPF_TAP_INPUT
);
615 pkt
->m_pkthdr
.header
= pkt
->m_data
;
616 pkt
->m_pkthdr
.len
-= sizeof(struct ether_header
);
617 pkt
->m_len
-= sizeof(struct ether_header
);
618 pkt
->m_data
+= sizeof(struct ether_header
);
620 if ( options
& kInputOptionQueuePacket
)
627 if ( _inputQHead
) // queue is not empty
631 count
= _inputQCount
;
633 DLIL_INPUT(_inputQHead
, _inputQTail
);
635 _inputQHead
= _inputQTail
= 0;
640 DLIL_INPUT(pkt
, pkt
);
647 //---------------------------------------------------------------------------
648 // Deliver an event to the network layer.
650 bool IONetworkInterface::inputEvent(UInt32 type
, void * data
)
654 #ifdef KEV_DL_LINK_ON
656 kern_event_msg header
;
658 char if_name
[IFNAMSIZ
];
663 // Deliver an IOKit defined event.
665 case kIONetworkEventTypeLinkUp
:
666 case kIONetworkEventTypeLinkDown
:
668 if ( ( _ifp
->if_flags
& IFF_UP
) == 0 )
673 bzero((void *) &event
, sizeof(event
));
675 event
.header
.total_size
= sizeof(event
);
676 event
.header
.vendor_code
= KEV_VENDOR_APPLE
;
677 event
.header
.kev_class
= KEV_NETWORK_CLASS
;
678 event
.header
.kev_subclass
= KEV_DL_SUBCLASS
;
679 event
.header
.event_code
= (type
== kIONetworkEventTypeLinkUp
) ?
680 KEV_DL_LINK_ON
: KEV_DL_LINK_OFF
;
681 event
.header
.event_data
[0] = _ifp
->if_family
;
682 event
.unit
= (u_long
) _ifp
->if_unit
;
683 strncpy(&event
.if_name
[0], _ifp
->if_name
, IFNAMSIZ
);
685 dlil_event(_ifp
, &event
.header
);
688 // Deliver a raw kernel event to DLIL.
689 // The data argument must point to a kern_event_msg structure.
691 case kIONetworkEventTypeDLIL
:
692 dlil_event(_ifp
, (struct kern_event_msg
*) data
);
696 IOLog("IONetworkInterface: unknown event type %lx\n", type
);
705 //---------------------------------------------------------------------------
706 // SIOCSIFMTU (set interface MTU) ioctl handler.
708 SInt32
IONetworkInterface::syncSIOCSIFMTU(IONetworkController
* ctr
,
712 UInt32 newMTU
= ifr
->ifr_mtu
;
714 // If change is not necessary, return success without getting the
715 // controller involved.
717 if ( getMaxTransferUnit() == newMTU
)
720 // Request the controller to switch MTU size.
722 error
= errnoFromReturn( ctr
->setMaxPacketSize(newMTU
) );
726 // Controller reports success. Update the interface MTU size
729 setMaxTransferUnit(newMTU
);
735 //---------------------------------------------------------------------------
736 // SIOCSIFMEDIA (SET interface media) ioctl handler.
738 SInt32
IONetworkInterface::syncSIOCSIFMEDIA(IONetworkController
* ctr
,
741 OSDictionary
* mediumDict
;
742 IONetworkMedium
* medium
;
745 mediumDict
= ctr
->copyMediumDictionary(); // creates a copy
746 if ( mediumDict
== 0 )
748 // unable to allocate memory, or no medium dictionary.
752 medium
= IONetworkMedium::getMediumWithType(mediumDict
, ifr
->ifr_media
);
755 // Exact type was not found. Try a partial match.
756 // ifconfig program sets the media type and media
757 // options separately. This should not be allowed!
759 medium
= IONetworkMedium::getMediumWithType(mediumDict
,
761 ~(IFM_TMASK
| IFM_NMASK
));
764 mediumDict
->release();
765 return EINVAL
; // requested medium not found.
769 // It may be possible for the controller to update the medium
770 // dictionary and perhaps delete the medium entry that we have
771 // selected from our copy of the stale dictionary. This is
772 // harmless since IONetworkController will filter out invalid
773 // selections before calling the driver.
775 error
= errnoFromReturn( ctr
->selectMediumWithName(medium
->getName()) );
777 mediumDict
->release();
782 //---------------------------------------------------------------------------
783 // SIOCGIFMEDIA (GET interface media) ioctl handler.
785 SInt32
IONetworkInterface::syncSIOCGIFMEDIA(IONetworkController
* ctr
,
788 OSDictionary
* mediumDict
= 0;
789 UInt mediumCount
= 0;
791 OSCollectionIterator
* iter
= 0;
794 OSSymbol
* keyObject
;
796 struct ifmediareq
* ifmr
= (struct ifmediareq
*) ifr
;
798 // Maximum number of medium types that the caller will accept.
800 maxCount
= ifmr
->ifm_count
;
803 mediumDict
= ctr
->copyMediumDictionary(); // creates a copy
806 break; // unable to allocate memory, or no medium dictionary.
809 if ((mediumCount
= mediumDict
->getCount()) == 0)
810 break; // no medium in the medium dictionary
813 break; // caller is only probing for support and media count.
815 if (maxCount
< mediumCount
)
817 // user buffer is too small to hold all medium entries.
820 // Proceed with partial copy on E2BIG. This follows the
821 // SIOCGIFMEDIA handling practice in bsd/net/if_media.c.
826 // Create an iterator to loop through the medium entries in the
829 iter
= OSCollectionIterator::withCollection(mediumDict
);
836 // Allocate memory for the copyout buffer.
838 typeListSize
= maxCount
* sizeof(UInt32
);
839 typeList
= (UInt32
*) IOMalloc(typeListSize
);
845 bzero(typeList
, typeListSize
);
847 // Iterate through the medium dictionary and copy the type of
848 // each medium entry to typeList[].
851 while ( (keyObject
= (OSSymbol
*) iter
->getNextObject()) &&
852 (mediumCount
< maxCount
) )
854 IONetworkMedium
* medium
= (IONetworkMedium
*)
855 mediumDict
->getObject(keyObject
);
857 continue; // should not happen!
859 typeList
[mediumCount
++] = medium
->getType();
864 error
= copyout((caddr_t
) typeList
,
865 (caddr_t
) ifmr
->ifm_ulist
,
869 IOFree(typeList
, typeListSize
);
873 ifmr
->ifm_active
= ifmr
->ifm_current
= IFM_NONE
;
874 ifmr
->ifm_status
= 0;
875 ifmr
->ifm_count
= mediumCount
;
877 // Get a copy of the controller's property table and read the
878 // link status, current, and active medium.
880 OSDictionary
* pTable
= ctr
->dictionaryWithProperties();
883 OSNumber
* linkStatus
= (OSNumber
*)
884 pTable
->getObject(kIOLinkStatus
);
886 ifmr
->ifm_status
= linkStatus
->unsigned32BitValue();
890 IONetworkMedium
* medium
;
891 OSSymbol
* mediumName
;
893 if ((mediumName
= (OSSymbol
*) pTable
->getObject(kIOSelectedMedium
))
894 && (medium
= (IONetworkMedium
*)
895 mediumDict
->getObject(mediumName
)))
897 ifmr
->ifm_current
= medium
->getType();
900 if ((mediumName
= (OSSymbol
*) pTable
->getObject(kIOActiveMedium
))
901 && (medium
= (IONetworkMedium
*)
902 mediumDict
->getObject(mediumName
)))
904 ifmr
->ifm_active
= medium
->getType();
914 mediumDict
->release();
919 //---------------------------------------------------------------------------
920 // Handle ioctl commands sent to the network interface.
922 SInt32
IONetworkInterface::performCommand(IONetworkController
* ctr
,
927 struct ifreq
* ifr
= (struct ifreq
*) arg1
;
928 SInt32 ret
= EOPNOTSUPP
;
930 if ( (ifr
== 0) || (ctr
== 0) )
935 // Get interface MTU.
938 ifr
->ifr_mtu
= getMaxTransferUnit();
942 // Get interface media type and status.
945 ret
= syncSIOCGIFMEDIA(ctr
, ifr
);
950 ret
= (int) ctr
->executeCommand(
952 (IONetworkController::Action
)
953 &IONetworkInterface::performGatedCommand
,
956 (void *) cmd
, /* param1 */
962 // DLOG(%s: command not handled (%08lx), getName(), cmd);
969 //---------------------------------------------------------------------------
970 // Perform an ioctl command on the controller's workloop context.
972 int IONetworkInterface::performGatedCommand(void * target
,
978 IONetworkInterface
* self
= (IONetworkInterface
*) target
;
979 IONetworkController
* ctr
= (IONetworkController
*) arg1_ctr
;
980 struct ifreq
* ifr
= (struct ifreq
*) arg4_1
;
981 SInt32 ret
= EOPNOTSUPP
;
983 // Refuse to issue I/O to the controller if it is in a power state
984 // that renders it "unusable".
986 if ( self
->getInterfaceState() & kIONetworkInterfaceDisabledState
)
989 switch ( (UInt32
) arg2_cmd
)
991 // Set interface MTU.
994 ret
= self
->syncSIOCSIFMTU(ctr
, ifr
);
997 // Set interface (controller) media type.
1000 ret
= self
->syncSIOCSIFMEDIA(ctr
, ifr
);
1007 //---------------------------------------------------------------------------
1008 // if_ioctl() handler - Calls performCommand() when we receive an ioctl
1012 IONetworkInterface::ioctl_shim(struct ifnet
* ifp
, u_long cmd
, caddr_t data
)
1014 assert(ifp
&& ifp
->if_private
);
1016 IONetworkInterface
* self
= (IONetworkInterface
*) ifp
->if_private
;
1018 assert(ifp
== self
->_ifp
);
1020 return self
->performCommand( self
->_controller
,
1026 //---------------------------------------------------------------------------
1027 // if_output() handler.
1029 // Handle a call from the network stack to transmit the given mbuf.
1030 // For now, we can assume that the mbuf is singular, and never chained.
1032 int IONetworkInterface::output_shim(struct ifnet
* ifp
, struct mbuf
* m
)
1034 assert(ifp
&& ifp
->if_private
);
1036 IONetworkInterface
* self
= (IONetworkInterface
*) ifp
->if_private
;
1038 assert(ifp
== self
->_ifp
);
1042 DLOG("IONetworkInterface: NULL output mbuf\n");
1046 if ( (m
->m_flags
& M_PKTHDR
) == 0 )
1048 DLOG("IONetworkInterface: M_PKTHDR bit not set\n");
1053 // Increment output byte counter.
1055 ifp
->if_obytes
+= m
->m_pkthdr
.len
;
1057 // Feed the output filter tap.
1059 _feedPacketTap(ifp
, m
, self
->_outputFilterFunc
, BPF_TAP_OUTPUT
);
1061 // Forward the packet to the registered output packet handler.
1063 return ((self
->_outTarget
)->*(self
->_outAction
))(m
, 0);
1066 //---------------------------------------------------------------------------
1067 // if_set_bpf_tap() handler. Handles request from the DLIL to enable or
1068 // disable the input/output filter taps.
1070 // FIXME - locking may be needed.
1072 int IONetworkInterface::set_bpf_tap_shim(struct ifnet
* ifp
,
1076 assert(ifp
&& ifp
->if_private
);
1078 IONetworkInterface
* self
= (IONetworkInterface
*) ifp
->if_private
;
1080 assert(ifp
== self
->_ifp
);
1086 case BPF_TAP_DISABLE
:
1087 self
->_inputFilterFunc
= self
->_outputFilterFunc
= 0;
1092 self
->_inputFilterFunc
= func
;
1095 case BPF_TAP_OUTPUT
:
1097 self
->_outputFilterFunc
= func
;
1100 case BPF_TAP_INPUT_OUTPUT
:
1102 self
->_inputFilterFunc
= self
->_outputFilterFunc
= func
;
1106 DLOG("IONetworkInterface: Unknown BPF tap mode %d\n", mode
);
1115 //---------------------------------------------------------------------------
1116 // As the name implies, this function does nothing. This will get called
1117 // if the network layer tries to call the if_watchdog function pointer
1118 // in ifnet. This should not happen. IOKit does not use this watchdog
1121 void IONetworkInterface::null_shim(struct ifnet
* /*ifp*/)
1123 IOLog("IONetworkInterface::null_shim called!\n");
1126 //---------------------------------------------------------------------------
1127 // ifnet field (and property table) getter/setter.
1129 bool IONetworkInterface::_setInterfaceProperty(UInt32 value
,
1135 bool updateOk
= false;
1141 // Update the property in ifnet.
1146 newValue
= (*((UInt8
*) addr
) & mask
) | value
;
1147 *((UInt8
*) addr
) = (UInt8
) newValue
;
1150 newValue
= (*((UInt16
*) addr
) & mask
) | value
;
1151 *((UInt16
*) addr
) = (UInt16
) newValue
;
1154 newValue
= (*((UInt32
*) addr
) & mask
) | value
;
1155 *((UInt32
*) addr
) = (UInt32
) newValue
;
1161 // Update the OSNumber in the property table.
1165 if ( (number
= (OSNumber
*) getProperty(key
)) )
1167 number
->setValue(newValue
);
1172 updateOk
= setProperty(key
, newValue
, bytes
* 8);
1180 #define IO_IFNET_GET(func, type, field) \
1181 type IONetworkInterface:: ## func() const \
1184 ((IONetworkInterface *) this)->lock(); \
1185 ret = _ifp ? _ifp-> ## field : 0; \
1186 ((IONetworkInterface *) this)->unlock(); \
1190 #define IO_IFNET_SET(func, type, field, propName) \
1191 bool IONetworkInterface:: ## func(type value) \
1193 return _setInterfaceProperty( \
1197 (void *) &_ifp-> ## field, \
1201 #define IO_IFNET_RMW(func, type, field, propName) \
1202 bool IONetworkInterface:: ## func(type value, type clear = 0) \
1204 return _setInterfaceProperty( \
1208 (void *) &_ifp-> ## field, \
1212 //---------------------------------------------------------------------------
1213 // Interface type accessors (ifp->if_type). The list of interface types is
1214 // defined in <bsd/net/if_types.h>.
1216 IO_IFNET_SET(setInterfaceType
, UInt8
, if_type
, kIOInterfaceType
)
1217 IO_IFNET_GET(getInterfaceType
, UInt8
, if_type
)
1219 //---------------------------------------------------------------------------
1220 // Mtu (MaxTransferUnit) accessors (ifp->if_mtu).
1222 IO_IFNET_SET(setMaxTransferUnit
, UInt32
, if_mtu
, kIOMaxTransferUnit
)
1223 IO_IFNET_GET(getMaxTransferUnit
, UInt32
, if_mtu
)
1225 //---------------------------------------------------------------------------
1226 // Flags accessors (ifp->if_flags). This is a read-modify-write operation.
1228 IO_IFNET_RMW(setFlags
, UInt16
, if_flags
, kIOInterfaceFlags
)
1229 IO_IFNET_GET(getFlags
, UInt16
, if_flags
)
1231 //---------------------------------------------------------------------------
1232 // EFlags accessors (ifp->if_eflags). This is a read-modify-write operation.
1234 IO_IFNET_RMW(setExtraFlags
, UInt32
, if_eflags
, kIOInterfaceExtraFlags
)
1235 IO_IFNET_GET(getExtraFlags
, UInt32
, if_eflags
)
1237 //---------------------------------------------------------------------------
1238 // MediaAddressLength accessors (ifp->if_addrlen)
1240 IO_IFNET_SET(setMediaAddressLength
, UInt8
, if_addrlen
, kIOMediaAddressLength
)
1241 IO_IFNET_GET(getMediaAddressLength
, UInt8
, if_addrlen
)
1243 //---------------------------------------------------------------------------
1244 // MediaHeaderLength accessors (ifp->if_hdrlen)
1246 IO_IFNET_SET(setMediaHeaderLength
, UInt8
, if_hdrlen
, kIOMediaHeaderLength
)
1247 IO_IFNET_GET(getMediaHeaderLength
, UInt8
, if_hdrlen
)
1249 //---------------------------------------------------------------------------
1250 // Interface unit number. The unit number for the interface is assigned
1253 IO_IFNET_SET(setUnitNumber
, UInt16
, if_unit
, kIOInterfaceUnit
)
1254 IO_IFNET_GET(getUnitNumber
, UInt16
, if_unit
)
1256 //---------------------------------------------------------------------------
1257 // Return true if the interface has been registered with the network layer,
1260 bool IONetworkInterface::isRegistered() const
1262 return (bool)(getInterfaceState() & kIONetworkInterfaceRegisteredState
);
1265 //---------------------------------------------------------------------------
1266 // Return the interface state flags.
1268 UInt32
IONetworkInterface::getInterfaceState() const
1270 return _stateBits
->unsigned32BitValue();
1273 //---------------------------------------------------------------------------
1274 // Set (or clear) the interface state flags.
1276 UInt32
IONetworkInterface::setInterfaceState( UInt32 set
,
1281 assert( _stateBits
);
1285 val
= ( _stateBits
->unsigned32BitValue() | set
) & ~clear
;
1286 _stateBits
->setValue( val
);
1293 //---------------------------------------------------------------------------
1294 // Perform a lookup of the dictionary kept by the interface,
1295 // and return an entry that matches the specified string key.
1297 // key: Search for an IONetworkData entry with this key.
1299 // Returns the matching entry, or 0 if no match was found.
1301 IONetworkData
* IONetworkInterface::getNetworkData(const OSSymbol
* key
) const
1303 return OSDynamicCast(IONetworkData
, _dataDict
->getObject(key
));
1306 IONetworkData
* IONetworkInterface::getNetworkData(const char * key
) const
1308 return OSDynamicCast(IONetworkData
, _dataDict
->getObject(key
));
1311 //---------------------------------------------------------------------------
1312 // A private function to copy the data dictionary to the property table.
1314 bool IONetworkInterface::_syncNetworkDataDict()
1316 OSDictionary
* aCopy
= OSDictionary::withDictionary(_dataDict
);
1320 ret
= setProperty(kIONetworkData
, aCopy
);
1327 //---------------------------------------------------------------------------
1328 // Remove an entry from the IONetworkData dictionary managed by the interface.
1329 // The removed object is released.
1331 bool IONetworkInterface::removeNetworkData(const OSSymbol
* aKey
)
1338 if ( getInterfaceState() & kIONetworkInterfaceOpenedState
)
1341 _dataDict
->removeObject(aKey
);
1342 ret
= _syncNetworkDataDict();
1351 bool IONetworkInterface::removeNetworkData(const char * aKey
)
1358 if ( getInterfaceState() & kIONetworkInterfaceOpenedState
)
1361 _dataDict
->removeObject(aKey
);
1362 ret
= _syncNetworkDataDict();
1371 //---------------------------------------------------------------------------
1372 // Add an IONetworkData object to a dictionary managed by the interface.
1374 bool IONetworkInterface::addNetworkData(IONetworkData
* aData
)
1378 if (OSDynamicCast(IONetworkData
, aData
) == 0)
1383 if (( getInterfaceState() & kIONetworkInterfaceOpenedState
) == 0)
1385 if ((ret
= _dataDict
->setObject(aData
->getKey(), aData
)))
1386 ret
= _syncNetworkDataDict();
1394 //---------------------------------------------------------------------------
1395 // Create a new IOUserClient to handle client requests. The default
1396 // implementation will create an IONetworkUserClient instance if
1397 // the type given is kIONUCType.
1399 IOReturn
IONetworkInterface::newUserClient(task_t owningTask
,
1400 void * /*security_id*/,
1402 IOUserClient
** handler
)
1404 IOReturn err
= kIOReturnSuccess
;
1405 IONetworkUserClient
* client
;
1407 if (type
!= kIONUCType
)
1408 return kIOReturnBadArgument
;
1410 client
= IONetworkUserClient::withTask(owningTask
);
1412 if (!client
|| !client
->attach(this) || !client
->start(this))
1416 client
->detach(this);
1420 err
= kIOReturnNoMemory
;
1428 //---------------------------------------------------------------------------
1429 // Handle controller's power state transitions.
1432 IONetworkInterface::controllerWillChangePowerState(
1433 IONetworkController
* controller
,
1434 IOPMPowerFlags flags
,
1436 IOService
* policyMaker
)
1438 if ( ( flags
& IOPMDeviceUsable
) == 0 )
1440 setInterfaceState( kIONetworkInterfaceDisabledState
);
1442 return kIOReturnSuccess
;
1446 IONetworkInterface::controllerDidChangePowerState(
1447 IONetworkController
* controller
,
1448 IOPMPowerFlags flags
,
1450 IOService
* policyMaker
)
1452 if ( flags
& IOPMDeviceUsable
)
1454 setInterfaceState( 0, kIONetworkInterfaceDisabledState
);
1456 return kIOReturnSuccess
;
1459 //---------------------------------------------------------------------------
1460 // Static member functions called by power-management notification handlers.
1461 // Act as stub functions that will simply forward the call to virtual member
1465 IONetworkInterface::sControllerWillChangePowerState(
1466 IONetworkInterface
* netif
,
1472 return netif
->controllerWillChangePowerState(
1473 (IONetworkController
*) param0
,
1474 (IOPMPowerFlags
) param1
,
1476 (IOService
*) param3
);
1480 IONetworkInterface::sControllerDidChangePowerState(
1481 IONetworkInterface
* netif
,
1487 return netif
->controllerDidChangePowerState(
1488 (IONetworkController
*) param0
,
1489 (IOPMPowerFlags
) param1
,
1491 (IOService
*) param3
);
1494 //---------------------------------------------------------------------------
1495 // Handle notitifications triggered by controller's power state change.
1498 IONetworkInterface::powerStateWillChangeTo( IOPMPowerFlags flags
,
1500 IOService
* policyMaker
)
1502 _controller
->executeCommand(
1504 (IONetworkController::Action
)
1505 &IONetworkInterface::sControllerWillChangePowerState
,
1507 (void *) _controller
, /* param0 */
1508 (void *) flags
, /* param1 */
1509 (void *) stateNumber
, /* param2 */
1510 (void *) policyMaker
); /* param3 */
1512 return IOPMAckImplied
;
1516 IONetworkInterface::powerStateDidChangeTo( IOPMPowerFlags flags
,
1518 IOService
* policyMaker
)
1520 _controller
->executeCommand(
1522 (IONetworkController::Action
)
1523 &IONetworkInterface::sControllerDidChangePowerState
,
1525 (void *) _controller
, /* param0 */
1526 (void *) flags
, /* param1 */
1527 (void *) stateNumber
, /* param2 */
1528 (void *) policyMaker
); /* param3 */
1530 return IOPMAckImplied
;