]> git.saurik.com Git - apple/xnu.git/blob - iokit/Families/IONetworking/IONetworkInterface.cpp
xnu-123.5.tar.gz
[apple/xnu.git] / iokit / Families / IONetworking / IONetworkInterface.cpp
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 * IONetworkInterface.cpp
26 *
27 * HISTORY
28 * 8-Jan-1999 Joe Liu (jliu) created.
29 *
30 */
31
32 #include <IOKit/assert.h>
33 #include <IOKit/IOLib.h>
34 #include <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>
39
40 extern "C" {
41 #include <sys/param.h>
42 #include <sys/mbuf.h>
43 #include <sys/socket.h>
44 #include <sys/sockio.h>
45 #include <net/bpf.h>
46 #include <net/if.h>
47 #include <netinet/if_ether.h>
48 #include <net/if_media.h>
49 #include <net/dlil.h>
50 int copyout(void *kaddr, void *udaddr, size_t len);
51
52 #ifdef KEV_DL_LINK_ON
53 #include <sys/kern_event.h>
54 int dlil_event(struct ifnet *ifp, struct kern_event_msg *event);
55 #endif
56 }
57
58 //---------------------------------------------------------------------------
59
60 #define super IOService
61
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);
79
80 //---------------------------------------------------------------------------
81 // Macros
82
83 #ifdef DEBUG
84 #define DLOG(fmt, args...) IOLog(fmt, ## args)
85 #else
86 #define DLOG(fmt, args...)
87 #endif
88
89 //---------------------------------------------------------------------------
90 // Initialize an IONetworkInterface instance.
91 //
92 // Returns true if initialized successfully, false otherwise.
93
94 bool IONetworkInterface::init(IONetworkController * controller)
95 {
96 // Propagate the init() call to our superclass.
97
98 if ( super::init() == false )
99 return false;
100
101 // The controller object provided must be valid.
102
103 if ( OSDynamicCast(IONetworkController, controller) == 0 )
104 return false;
105
106 _controller = controller;
107
108 // Create interface lock to serialize ifnet updates.
109
110 _ifLock = IORecursiveLockAlloc();
111 if ( _ifLock == 0 )
112 return false;
113
114 // Create an OSNumber to store interface state bits.
115
116 _stateBits = OSNumber::withNumber((UInt64) 0, 32);
117 if ( _stateBits == 0 )
118 return false;
119 setProperty( kIOInterfaceState, _stateBits );
120
121 // Create an OSSet to store client objects. Initial capacity
122 // (which can grow) is set at 2 clients.
123
124 _clientSet = OSSet::withCapacity(2);
125 if ( _clientSet == 0 )
126 return false;
127
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().
131
132 _ifp = getIfnet();
133 if ( _ifp == 0 )
134 {
135 DLOG("%s: getIfnet() returned NULL\n", getName());
136 return false;
137 }
138
139 // Intialize the ifnet structure.
140
141 if ( initIfnet(_ifp) == false )
142 return false;
143
144 // Create a data dictionary.
145
146 if ( (_dataDict = OSDictionary::withCapacity(5)) == 0 )
147 return false;
148
149 IONetworkData * data = IONetworkData::withExternalBuffer(
150 kIONetworkStatsKey,
151 sizeof(IONetworkStats),
152 (UInt8 *) &(_ifp->if_data.ifi_ipackets));
153 if ( data )
154 {
155 addNetworkData(data);
156 data->release();
157 }
158
159 // Register default output handler.
160
161 if ( registerOutputHandler( controller,
162 controller->getOutputHandler() ) == false )
163 {
164 return false;
165 }
166
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.
170
171 setProperty( kIOInterfaceNamePrefix, getNamePrefix() );
172 setProperty( kIOPrimaryInterface, isPrimaryInterface() );
173
174 return true;
175 }
176
177 //---------------------------------------------------------------------------
178 // Destroy the interface. Release all allocated resources.
179
180 void IONetworkInterface::free()
181 {
182 DLOG("IONetworkInterface::free()\n");
183
184 if ( _clientSet )
185 {
186 // Should not have any clients.
187 assert(_clientSet->getCount() == 0);
188 _clientSet->release();
189 _clientSet = 0;
190 }
191
192 if ( _dataDict ) { _dataDict->release(); _dataDict = 0; }
193 if ( _stateBits ) { _stateBits->release(); _stateBits = 0; }
194
195 if ( _ifLock )
196 {
197 IORecursiveLockFree(_ifLock);
198 _ifLock = 0;
199 }
200
201 clearInputQueue();
202
203 super::free();
204 }
205
206 //---------------------------------------------------------------------------
207 // Returns true if the receiver of this method is the system's primary
208 // network interface.
209
210 bool IONetworkInterface::isPrimaryInterface() const
211 {
212 IOService * provider = getController();
213 bool isPrimary = false;
214
215 if ( provider ) provider = provider->getProvider();
216
217 // FIXME: Should rely on a single property, and the platform
218 // expert should patch the device tree if necessary to make
219 // it so.
220
221 if ( provider &&
222 ( provider->getProperty( "AAPL,slot-name" ) == 0 ) &&
223 ( provider->getProperty( "built-in" ) ||
224 provider->getProperty( "AAPL,connector" ) ||
225 ( strcmp( provider->getName(), "ethernet" ) == 0 ) ) )
226 {
227 isPrimary = true;
228 }
229
230 return isPrimary;
231 }
232
233 //---------------------------------------------------------------------------
234 // Get the IONetworkCotroller object that is servicing this interface.
235
236 IONetworkController * IONetworkInterface::getController() const
237 {
238 return _controller;
239 }
240
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.
246
247 static UInt32 getIfnetHardwareAssistValue( IONetworkController * ctr )
248 {
249 UInt32 input;
250 UInt32 output;
251 UInt32 hwassist = 0;
252
253 do {
254 if ( ctr->getChecksumSupport(
255 &input,
256 IONetworkController::kChecksumFamilyTCPIP,
257 false ) != kIOReturnSuccess ) break;
258
259 if ( ctr->getChecksumSupport(
260 &output,
261 IONetworkController::kChecksumFamilyTCPIP,
262 true ) != kIOReturnSuccess ) break;
263
264 if ( input & output & IONetworkController::kChecksumIP )
265 {
266 hwassist |= CSUM_IP;
267 }
268
269 if ( ( input & ( IONetworkController::kChecksumTCP |
270 IONetworkController::kChecksumTCPNoPseudoHeader ) )
271 && ( output & ( IONetworkController::kChecksumTCP |
272 IONetworkController::kChecksumTCPSum16 ) ) )
273 {
274 hwassist |= CSUM_TCP;
275 }
276
277 if ( ( input & ( IONetworkController::kChecksumUDP |
278 IONetworkController::kChecksumUDPNoPseudoHeader ) )
279 && ( output & ( IONetworkController::kChecksumUDP |
280 IONetworkController::kChecksumTCPSum16 ) ) )
281 {
282 hwassist |= CSUM_UDP;
283 }
284 }
285 while ( false );
286
287 return hwassist;
288 }
289 #endif HW_CSUM_SUPPORT
290
291 //---------------------------------------------------------------------------
292 // Initialize the ifnet structure.
293
294 bool IONetworkInterface::initIfnet(struct ifnet * ifp)
295 {
296 lock();
297
298 // Register our 'shim' functions. These function pointers
299 // points to static member functions inside this class.
300
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();
307
308 unlock();
309
310 return true;
311 }
312
313 //---------------------------------------------------------------------------
314 // Implement family specific matching.
315
316 bool IONetworkInterface::matchPropertyTable(OSDictionary * table,
317 SInt32 * score)
318 {
319 return super::matchPropertyTable(table, score);
320 }
321
322 //---------------------------------------------------------------------------
323 // Take the interface lock.
324
325 void IONetworkInterface::lock()
326 {
327 IORecursiveLockLock(_ifLock);
328 }
329
330 //---------------------------------------------------------------------------
331 // Release the interface lock.
332
333 void IONetworkInterface::unlock()
334 {
335 IORecursiveLockUnlock(_ifLock);
336 }
337
338 //---------------------------------------------------------------------------
339 // Inspect the controller after it has been opened.
340
341 bool IONetworkInterface::controllerDidOpen(IONetworkController * controller)
342 {
343 return true; // by default, always accept the controller open.
344 }
345
346 //---------------------------------------------------------------------------
347 // Perform cleanup before the controller is closed.
348
349 void IONetworkInterface::controllerWillClose(IONetworkController * controller)
350 {
351 }
352
353 //---------------------------------------------------------------------------
354 // Handle a client open on the interface.
355
356 bool IONetworkInterface::handleOpen(IOService * client,
357 IOOptionBits options,
358 void * argument)
359 {
360 bool accept = false;
361 bool controllerOpen = false;
362
363 do {
364 // Was this object already registered as our client?
365
366 if ( _clientSet->containsObject(client) )
367 {
368 DLOG("%s: multiple opens from client %lx\n",
369 getName(), (UInt32) client);
370 accept = true;
371 break;
372 }
373
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
378 // be rejected.
379
380 if ( ( getInterfaceState() & kIONetworkInterfaceOpenedState ) == 0 )
381 {
382 if ( ( (controllerOpen = _controller->open(this)) == false ) ||
383 ( controllerDidOpen(_controller) == false ) )
384 break;
385 }
386
387 // Qualify the client.
388
389 if ( handleClientOpen(client, options, argument) == false )
390 break;
391
392 // Add the new client object to our client set.
393
394 if ( _clientSet->setObject(client) == false )
395 {
396 handleClientClose(client, 0);
397 break;
398 }
399
400 accept = true;
401 }
402 while (false);
403
404 // If provider was opened above, but an error has caused us to refuse
405 // the client open, then close our provider.
406
407 if ( controllerOpen )
408 {
409 if (accept)
410 {
411 setInterfaceState( kIONetworkInterfaceOpenedState );
412 _controller->registerInterestedDriver( this );
413 }
414 else {
415 controllerWillClose(_controller);
416 _controller->close(this);
417 }
418 }
419
420 return accept;
421 }
422
423 //---------------------------------------------------------------------------
424 // Handle a client close on the interface.
425
426 void IONetworkInterface::handleClose(IOService * client, IOOptionBits options)
427 {
428 // Remove the object from the client OSSet.
429
430 if ( _clientSet->containsObject(client) )
431 {
432 // Call handleClientClose() to handle the client close.
433
434 handleClientClose( client, options );
435
436 // If this is the last client, then close our provider.
437
438 if ( _clientSet->getCount() == 1 )
439 {
440 _controller->deRegisterInterestedDriver( this );
441 controllerWillClose( _controller );
442 _controller->close( this );
443 setInterfaceState( 0, kIONetworkInterfaceOpenedState );
444 }
445
446 // Remove the client from our OSSet.
447
448 _clientSet->removeObject(client);
449 }
450 }
451
452 //---------------------------------------------------------------------------
453 // Query whether a client has an open on the interface.
454
455 bool IONetworkInterface::handleIsOpen(const IOService * client) const
456 {
457 if (client)
458 return _clientSet->containsObject(client);
459 else
460 return (_clientSet->getCount() > 0);
461 }
462
463 //---------------------------------------------------------------------------
464 // Handle a client open on the interface.
465
466 bool IONetworkInterface::handleClientOpen(IOService * client,
467 IOOptionBits options,
468 void * argument)
469 {
470 if ( OSDynamicCast(IONetworkStack, client) )
471 {
472 // Transition state to registered interface.
473
474 setInterfaceState( kIONetworkInterfaceRegisteredState );
475 }
476 return true;
477 }
478
479 //---------------------------------------------------------------------------
480 // Handle a client close on the interface.
481
482 void IONetworkInterface::handleClientClose(IOService * client,
483 IOOptionBits options)
484 {
485 if ( OSDynamicCast(IONetworkStack, client) )
486 {
487 // Transition state to unregistered interface.
488
489 setInterfaceState( 0, kIONetworkInterfaceRegisteredState );
490 }
491 }
492
493 //---------------------------------------------------------------------------
494 // Register the output packet handler.
495
496 bool IONetworkInterface::registerOutputHandler(OSObject * target,
497 IOOutputAction action)
498 {
499 lock();
500
501 // Sanity check on the arguments.
502
503 if ( (getInterfaceState() & kIONetworkInterfaceRegisteredState) ||
504 !target || !action )
505 {
506 unlock();
507 return false;
508 }
509
510 _outTarget = target;
511 _outAction = action;
512
513 unlock();
514
515 return true;
516 }
517
518 //---------------------------------------------------------------------------
519 // Feed packets to the input/output BPF packet filter taps.
520
521 static inline void _feedPacketTap(struct ifnet * ifp,
522 struct mbuf * m,
523 BPF_FUNC func,
524 int mode)
525 {
526 if (func) func(ifp, m);
527 }
528
529 //---------------------------------------------------------------------------
530 // Called by a network controller to submit a single packet received from
531 // the network to the data link layer.
532
533 #define IN_Q_ENQUEUE(m) \
534 { \
535 if (_inputQHead == 0) { \
536 _inputQHead = _inputQTail = (m); \
537 } \
538 else { \
539 _inputQTail->m_nextpkt = (m) ; \
540 _inputQTail = (m); \
541 } \
542 _inputQCount++; \
543 }
544
545 #define DLIL_INPUT(m_head, m_tail) \
546 { \
547 if ( m_head ) { \
548 dlil_input(_ifp, (m_head), (m_tail)); \
549 } \
550 }
551
552 UInt32 IONetworkInterface::flushInputQueue()
553 {
554 UInt32 count = _inputQCount;
555
556 DLIL_INPUT(_inputQHead, _inputQTail);
557 _inputQHead = _inputQTail = 0;
558 _inputQCount = 0;
559
560 return count;
561 }
562
563 UInt32 IONetworkInterface::clearInputQueue()
564 {
565 UInt32 count = _inputQCount;
566
567 m_freem_list( _inputQHead );
568
569 _inputQHead = _inputQTail = 0;
570 _inputQCount = 0;
571
572 return count;
573 }
574
575 UInt32 IONetworkInterface::inputPacket(struct mbuf * pkt,
576 UInt32 length = 0,
577 IOOptionBits options = 0,
578 void * param = 0)
579 {
580 UInt32 count;
581
582 assert(pkt);
583
584 // Set the source interface and length of the received frame.
585
586 if ( length )
587 {
588 if ( pkt->m_next == 0 )
589 {
590 pkt->m_pkthdr.len = pkt->m_len = length;
591 }
592 else
593 {
594 struct mbuf * m = pkt;
595 pkt->m_pkthdr.len = length;
596 do {
597 if (length < (UInt32) m->m_len)
598 m->m_len = length;
599 length -= m->m_len;
600 } while (( m = m->m_next ));
601 assert(length == 0);
602 }
603 }
604
605 pkt->m_pkthdr.rcvif = _ifp;
606
607 // Increment input byte count.
608
609 _ifp->if_ibytes += pkt->m_pkthdr.len;
610
611 // Feed BPF tap.
612
613 _feedPacketTap(_ifp, pkt, _inputFilterFunc, BPF_TAP_INPUT);
614
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);
619
620 if ( options & kInputOptionQueuePacket )
621 {
622 IN_Q_ENQUEUE(pkt);
623 count = 0;
624 }
625 else
626 {
627 if ( _inputQHead ) // queue is not empty
628 {
629 IN_Q_ENQUEUE(pkt);
630
631 count = _inputQCount;
632
633 DLIL_INPUT(_inputQHead, _inputQTail);
634
635 _inputQHead = _inputQTail = 0;
636 _inputQCount = 0;
637 }
638 else
639 {
640 DLIL_INPUT(pkt, pkt);
641 count = 1;
642 }
643 }
644 return count;
645 }
646
647 //---------------------------------------------------------------------------
648 // Deliver an event to the network layer.
649
650 bool IONetworkInterface::inputEvent(UInt32 type, void * data)
651 {
652 bool success = true;
653
654 #ifdef KEV_DL_LINK_ON
655 struct {
656 kern_event_msg header;
657 u_long unit;
658 char if_name[IFNAMSIZ];
659 } event;
660
661 switch (type)
662 {
663 // Deliver an IOKit defined event.
664
665 case kIONetworkEventTypeLinkUp:
666 case kIONetworkEventTypeLinkDown:
667
668 if ( ( _ifp->if_flags & IFF_UP ) == 0 )
669 {
670 break;
671 }
672
673 bzero((void *) &event, sizeof(event));
674
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);
684
685 dlil_event(_ifp, &event.header);
686 break;
687
688 // Deliver a raw kernel event to DLIL.
689 // The data argument must point to a kern_event_msg structure.
690
691 case kIONetworkEventTypeDLIL:
692 dlil_event(_ifp, (struct kern_event_msg *) data);
693 break;
694
695 default:
696 IOLog("IONetworkInterface: unknown event type %lx\n", type);
697 success = false;
698 break;
699 }
700 #endif
701
702 return success;
703 }
704
705 //---------------------------------------------------------------------------
706 // SIOCSIFMTU (set interface MTU) ioctl handler.
707
708 SInt32 IONetworkInterface::syncSIOCSIFMTU(IONetworkController * ctr,
709 struct ifreq * ifr)
710 {
711 SInt32 error;
712 UInt32 newMTU = ifr->ifr_mtu;
713
714 // If change is not necessary, return success without getting the
715 // controller involved.
716
717 if ( getMaxTransferUnit() == newMTU )
718 return 0;
719
720 // Request the controller to switch MTU size.
721
722 error = errnoFromReturn( ctr->setMaxPacketSize(newMTU) );
723
724 if ( error == 0 )
725 {
726 // Controller reports success. Update the interface MTU size
727 // property.
728
729 setMaxTransferUnit(newMTU);
730 }
731
732 return error;
733 }
734
735 //---------------------------------------------------------------------------
736 // SIOCSIFMEDIA (SET interface media) ioctl handler.
737
738 SInt32 IONetworkInterface::syncSIOCSIFMEDIA(IONetworkController * ctr,
739 struct ifreq * ifr)
740 {
741 OSDictionary * mediumDict;
742 IONetworkMedium * medium;
743 SInt32 error;
744
745 mediumDict = ctr->copyMediumDictionary(); // creates a copy
746 if ( mediumDict == 0 )
747 {
748 // unable to allocate memory, or no medium dictionary.
749 return EOPNOTSUPP;
750 }
751
752 medium = IONetworkMedium::getMediumWithType(mediumDict, ifr->ifr_media);
753 if ( medium == 0 )
754 {
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!
758
759 medium = IONetworkMedium::getMediumWithType(mediumDict,
760 ifr->ifr_media,
761 ~(IFM_TMASK | IFM_NMASK));
762 if ( medium == 0 )
763 {
764 mediumDict->release();
765 return EINVAL; // requested medium not found.
766 }
767 }
768
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.
774
775 error = errnoFromReturn( ctr->selectMediumWithName(medium->getName()) );
776
777 mediumDict->release();
778
779 return error;
780 }
781
782 //---------------------------------------------------------------------------
783 // SIOCGIFMEDIA (GET interface media) ioctl handler.
784
785 SInt32 IONetworkInterface::syncSIOCGIFMEDIA(IONetworkController * ctr,
786 struct ifreq * ifr)
787 {
788 OSDictionary * mediumDict = 0;
789 UInt mediumCount = 0;
790 UInt maxCount;
791 OSCollectionIterator * iter = 0;
792 UInt32 * typeList;
793 UInt typeListSize;
794 OSSymbol * keyObject;
795 SInt32 error = 0;
796 struct ifmediareq * ifmr = (struct ifmediareq *) ifr;
797
798 // Maximum number of medium types that the caller will accept.
799 //
800 maxCount = ifmr->ifm_count;
801
802 do {
803 mediumDict = ctr->copyMediumDictionary(); // creates a copy
804 if (mediumDict == 0)
805 {
806 break; // unable to allocate memory, or no medium dictionary.
807 }
808
809 if ((mediumCount = mediumDict->getCount()) == 0)
810 break; // no medium in the medium dictionary
811
812 if (maxCount == 0)
813 break; // caller is only probing for support and media count.
814
815 if (maxCount < mediumCount)
816 {
817 // user buffer is too small to hold all medium entries.
818 error = E2BIG;
819
820 // Proceed with partial copy on E2BIG. This follows the
821 // SIOCGIFMEDIA handling practice in bsd/net/if_media.c.
822 //
823 // break;
824 }
825
826 // Create an iterator to loop through the medium entries in the
827 // dictionary.
828 //
829 iter = OSCollectionIterator::withCollection(mediumDict);
830 if (!iter)
831 {
832 error = ENOMEM;
833 break;
834 }
835
836 // Allocate memory for the copyout buffer.
837 //
838 typeListSize = maxCount * sizeof(UInt32);
839 typeList = (UInt32 *) IOMalloc(typeListSize);
840 if (!typeList)
841 {
842 error = ENOMEM;
843 break;
844 }
845 bzero(typeList, typeListSize);
846
847 // Iterate through the medium dictionary and copy the type of
848 // each medium entry to typeList[].
849 //
850 mediumCount = 0;
851 while ( (keyObject = (OSSymbol *) iter->getNextObject()) &&
852 (mediumCount < maxCount) )
853 {
854 IONetworkMedium * medium = (IONetworkMedium *)
855 mediumDict->getObject(keyObject);
856 if (!medium)
857 continue; // should not happen!
858
859 typeList[mediumCount++] = medium->getType();
860 }
861
862 if (mediumCount)
863 {
864 error = copyout((caddr_t) typeList,
865 (caddr_t) ifmr->ifm_ulist,
866 typeListSize);
867 }
868
869 IOFree(typeList, typeListSize);
870 }
871 while (0);
872
873 ifmr->ifm_active = ifmr->ifm_current = IFM_NONE;
874 ifmr->ifm_status = 0;
875 ifmr->ifm_count = mediumCount;
876
877 // Get a copy of the controller's property table and read the
878 // link status, current, and active medium.
879
880 OSDictionary * pTable = ctr->dictionaryWithProperties();
881 if (pTable)
882 {
883 OSNumber * linkStatus = (OSNumber *)
884 pTable->getObject(kIOLinkStatus);
885 if (linkStatus)
886 ifmr->ifm_status = linkStatus->unsigned32BitValue();
887
888 if (mediumDict)
889 {
890 IONetworkMedium * medium;
891 OSSymbol * mediumName;
892
893 if ((mediumName = (OSSymbol *) pTable->getObject(kIOSelectedMedium))
894 && (medium = (IONetworkMedium *)
895 mediumDict->getObject(mediumName)))
896 {
897 ifmr->ifm_current = medium->getType();
898 }
899
900 if ((mediumName = (OSSymbol *) pTable->getObject(kIOActiveMedium))
901 && (medium = (IONetworkMedium *)
902 mediumDict->getObject(mediumName)))
903 {
904 ifmr->ifm_active = medium->getType();
905 }
906 }
907 pTable->release();
908 }
909
910 if (iter)
911 iter->release();
912
913 if (mediumDict)
914 mediumDict->release();
915
916 return error;
917 }
918
919 //---------------------------------------------------------------------------
920 // Handle ioctl commands sent to the network interface.
921
922 SInt32 IONetworkInterface::performCommand(IONetworkController * ctr,
923 UInt32 cmd,
924 void * arg0,
925 void * arg1)
926 {
927 struct ifreq * ifr = (struct ifreq *) arg1;
928 SInt32 ret = EOPNOTSUPP;
929
930 if ( (ifr == 0) || (ctr == 0) )
931 return EINVAL;
932
933 switch ( cmd )
934 {
935 // Get interface MTU.
936
937 case SIOCGIFMTU:
938 ifr->ifr_mtu = getMaxTransferUnit();
939 ret = 0; // no error
940 break;
941
942 // Get interface media type and status.
943
944 case SIOCGIFMEDIA:
945 ret = syncSIOCGIFMEDIA(ctr, ifr);
946 break;
947
948 case SIOCSIFMTU:
949 case SIOCSIFMEDIA:
950 ret = (int) ctr->executeCommand(
951 this, /* client */
952 (IONetworkController::Action)
953 &IONetworkInterface::performGatedCommand,
954 this, /* target */
955 ctr, /* param0 */
956 (void *) cmd, /* param1 */
957 arg0, /* param2 */
958 arg1 ); /* param3 */
959 break;
960
961 default:
962 // DLOG(%s: command not handled (%08lx), getName(), cmd);
963 break;
964 }
965
966 return ret;
967 }
968
969 //---------------------------------------------------------------------------
970 // Perform an ioctl command on the controller's workloop context.
971
972 int IONetworkInterface::performGatedCommand(void * target,
973 void * arg1_ctr,
974 void * arg2_cmd,
975 void * arg3_0,
976 void * arg4_1)
977 {
978 IONetworkInterface * self = (IONetworkInterface *) target;
979 IONetworkController * ctr = (IONetworkController *) arg1_ctr;
980 struct ifreq * ifr = (struct ifreq *) arg4_1;
981 SInt32 ret = EOPNOTSUPP;
982
983 // Refuse to issue I/O to the controller if it is in a power state
984 // that renders it "unusable".
985
986 if ( self->getInterfaceState() & kIONetworkInterfaceDisabledState )
987 return EPWROFF;
988
989 switch ( (UInt32) arg2_cmd )
990 {
991 // Set interface MTU.
992
993 case SIOCSIFMTU:
994 ret = self->syncSIOCSIFMTU(ctr, ifr);
995 break;
996
997 // Set interface (controller) media type.
998
999 case SIOCSIFMEDIA:
1000 ret = self->syncSIOCSIFMEDIA(ctr, ifr);
1001 break;
1002 }
1003
1004 return ret;
1005 }
1006
1007 //---------------------------------------------------------------------------
1008 // if_ioctl() handler - Calls performCommand() when we receive an ioctl
1009 // from DLIL.
1010
1011 int
1012 IONetworkInterface::ioctl_shim(struct ifnet * ifp, u_long cmd, caddr_t data)
1013 {
1014 assert(ifp && ifp->if_private);
1015
1016 IONetworkInterface * self = (IONetworkInterface *) ifp->if_private;
1017
1018 assert(ifp == self->_ifp);
1019
1020 return self->performCommand( self->_controller,
1021 cmd,
1022 (void *) ifp,
1023 (void *) data );
1024 }
1025
1026 //---------------------------------------------------------------------------
1027 // if_output() handler.
1028 //
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.
1031
1032 int IONetworkInterface::output_shim(struct ifnet * ifp, struct mbuf * m)
1033 {
1034 assert(ifp && ifp->if_private);
1035
1036 IONetworkInterface * self = (IONetworkInterface *) ifp->if_private;
1037
1038 assert(ifp == self->_ifp);
1039
1040 if ( m == 0 )
1041 {
1042 DLOG("IONetworkInterface: NULL output mbuf\n");
1043 return EINVAL;
1044 }
1045
1046 if ( (m->m_flags & M_PKTHDR) == 0 )
1047 {
1048 DLOG("IONetworkInterface: M_PKTHDR bit not set\n");
1049 m_freem(m);
1050 return EINVAL;
1051 }
1052
1053 // Increment output byte counter.
1054
1055 ifp->if_obytes += m->m_pkthdr.len;
1056
1057 // Feed the output filter tap.
1058
1059 _feedPacketTap(ifp, m, self->_outputFilterFunc, BPF_TAP_OUTPUT);
1060
1061 // Forward the packet to the registered output packet handler.
1062
1063 return ((self->_outTarget)->*(self->_outAction))(m, 0);
1064 }
1065
1066 //---------------------------------------------------------------------------
1067 // if_set_bpf_tap() handler. Handles request from the DLIL to enable or
1068 // disable the input/output filter taps.
1069 //
1070 // FIXME - locking may be needed.
1071
1072 int IONetworkInterface::set_bpf_tap_shim(struct ifnet * ifp,
1073 int mode,
1074 BPF_FUNC func)
1075 {
1076 assert(ifp && ifp->if_private);
1077
1078 IONetworkInterface * self = (IONetworkInterface *) ifp->if_private;
1079
1080 assert(ifp == self->_ifp);
1081
1082 self->lock();
1083
1084 switch ( mode )
1085 {
1086 case BPF_TAP_DISABLE:
1087 self->_inputFilterFunc = self->_outputFilterFunc = 0;
1088 break;
1089
1090 case BPF_TAP_INPUT:
1091 assert(func);
1092 self->_inputFilterFunc = func;
1093 break;
1094
1095 case BPF_TAP_OUTPUT:
1096 assert(func);
1097 self->_outputFilterFunc = func;
1098 break;
1099
1100 case BPF_TAP_INPUT_OUTPUT:
1101 assert(func);
1102 self->_inputFilterFunc = self->_outputFilterFunc = func;
1103 break;
1104
1105 default:
1106 DLOG("IONetworkInterface: Unknown BPF tap mode %d\n", mode);
1107 break;
1108 }
1109
1110 self->unlock();
1111
1112 return 0;
1113 }
1114
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
1119 // timer facility.
1120
1121 void IONetworkInterface::null_shim(struct ifnet * /*ifp*/)
1122 {
1123 IOLog("IONetworkInterface::null_shim called!\n");
1124 }
1125
1126 //---------------------------------------------------------------------------
1127 // ifnet field (and property table) getter/setter.
1128
1129 bool IONetworkInterface::_setInterfaceProperty(UInt32 value,
1130 UInt32 mask,
1131 UInt32 bytes,
1132 void * addr,
1133 char * key)
1134 {
1135 bool updateOk = false;
1136 UInt32 newValue;
1137 OSNumber * number;
1138
1139 lock();
1140
1141 // Update the property in ifnet.
1142
1143 switch (bytes)
1144 {
1145 case 1:
1146 newValue = (*((UInt8 *) addr) & mask) | value;
1147 *((UInt8 *) addr) = (UInt8) newValue;
1148 break;
1149 case 2:
1150 newValue = (*((UInt16 *) addr) & mask) | value;
1151 *((UInt16 *) addr) = (UInt16) newValue;
1152 break;
1153 case 4:
1154 newValue = (*((UInt32 *) addr) & mask) | value;
1155 *((UInt32 *) addr) = (UInt32) newValue;
1156 break;
1157 default:
1158 goto abort;
1159 }
1160
1161 // Update the OSNumber in the property table.
1162
1163 if ( key )
1164 {
1165 if ( (number = (OSNumber *) getProperty(key)) )
1166 {
1167 number->setValue(newValue);
1168 updateOk = true;
1169 }
1170 else
1171 {
1172 updateOk = setProperty(key, newValue, bytes * 8);
1173 }
1174 }
1175 abort:
1176 unlock();
1177 return updateOk;
1178 }
1179
1180 #define IO_IFNET_GET(func, type, field) \
1181 type IONetworkInterface:: ## func() const \
1182 { \
1183 type ret; \
1184 ((IONetworkInterface *) this)->lock(); \
1185 ret = _ifp ? _ifp-> ## field : 0; \
1186 ((IONetworkInterface *) this)->unlock(); \
1187 return ret; \
1188 }
1189
1190 #define IO_IFNET_SET(func, type, field, propName) \
1191 bool IONetworkInterface:: ## func(type value) \
1192 { \
1193 return _setInterfaceProperty( \
1194 (UInt32) value, \
1195 0, \
1196 sizeof(type), \
1197 (void *) &_ifp-> ## field, \
1198 propName); \
1199 }
1200
1201 #define IO_IFNET_RMW(func, type, field, propName) \
1202 bool IONetworkInterface:: ## func(type value, type clear = 0) \
1203 { \
1204 return _setInterfaceProperty( \
1205 (UInt32) value, \
1206 (UInt32) ~clear, \
1207 sizeof(type), \
1208 (void *) &_ifp-> ## field, \
1209 propName); \
1210 }
1211
1212 //---------------------------------------------------------------------------
1213 // Interface type accessors (ifp->if_type). The list of interface types is
1214 // defined in <bsd/net/if_types.h>.
1215
1216 IO_IFNET_SET(setInterfaceType, UInt8, if_type, kIOInterfaceType)
1217 IO_IFNET_GET(getInterfaceType, UInt8, if_type)
1218
1219 //---------------------------------------------------------------------------
1220 // Mtu (MaxTransferUnit) accessors (ifp->if_mtu).
1221
1222 IO_IFNET_SET(setMaxTransferUnit, UInt32, if_mtu, kIOMaxTransferUnit)
1223 IO_IFNET_GET(getMaxTransferUnit, UInt32, if_mtu)
1224
1225 //---------------------------------------------------------------------------
1226 // Flags accessors (ifp->if_flags). This is a read-modify-write operation.
1227
1228 IO_IFNET_RMW(setFlags, UInt16, if_flags, kIOInterfaceFlags)
1229 IO_IFNET_GET(getFlags, UInt16, if_flags)
1230
1231 //---------------------------------------------------------------------------
1232 // EFlags accessors (ifp->if_eflags). This is a read-modify-write operation.
1233
1234 IO_IFNET_RMW(setExtraFlags, UInt32, if_eflags, kIOInterfaceExtraFlags)
1235 IO_IFNET_GET(getExtraFlags, UInt32, if_eflags)
1236
1237 //---------------------------------------------------------------------------
1238 // MediaAddressLength accessors (ifp->if_addrlen)
1239
1240 IO_IFNET_SET(setMediaAddressLength, UInt8, if_addrlen, kIOMediaAddressLength)
1241 IO_IFNET_GET(getMediaAddressLength, UInt8, if_addrlen)
1242
1243 //---------------------------------------------------------------------------
1244 // MediaHeaderLength accessors (ifp->if_hdrlen)
1245
1246 IO_IFNET_SET(setMediaHeaderLength, UInt8, if_hdrlen, kIOMediaHeaderLength)
1247 IO_IFNET_GET(getMediaHeaderLength, UInt8, if_hdrlen)
1248
1249 //---------------------------------------------------------------------------
1250 // Interface unit number. The unit number for the interface is assigned
1251 // by our client.
1252
1253 IO_IFNET_SET(setUnitNumber, UInt16, if_unit, kIOInterfaceUnit)
1254 IO_IFNET_GET(getUnitNumber, UInt16, if_unit)
1255
1256 //---------------------------------------------------------------------------
1257 // Return true if the interface has been registered with the network layer,
1258 // false otherwise.
1259
1260 bool IONetworkInterface::isRegistered() const
1261 {
1262 return (bool)(getInterfaceState() & kIONetworkInterfaceRegisteredState);
1263 }
1264
1265 //---------------------------------------------------------------------------
1266 // Return the interface state flags.
1267
1268 UInt32 IONetworkInterface::getInterfaceState() const
1269 {
1270 return _stateBits->unsigned32BitValue();
1271 }
1272
1273 //---------------------------------------------------------------------------
1274 // Set (or clear) the interface state flags.
1275
1276 UInt32 IONetworkInterface::setInterfaceState( UInt32 set,
1277 UInt32 clear )
1278 {
1279 UInt32 val;
1280
1281 assert( _stateBits );
1282
1283 lock();
1284
1285 val = ( _stateBits->unsigned32BitValue() | set ) & ~clear;
1286 _stateBits->setValue( val );
1287
1288 unlock();
1289
1290 return val;
1291 }
1292
1293 //---------------------------------------------------------------------------
1294 // Perform a lookup of the dictionary kept by the interface,
1295 // and return an entry that matches the specified string key.
1296 //
1297 // key: Search for an IONetworkData entry with this key.
1298 //
1299 // Returns the matching entry, or 0 if no match was found.
1300
1301 IONetworkData * IONetworkInterface::getNetworkData(const OSSymbol * key) const
1302 {
1303 return OSDynamicCast(IONetworkData, _dataDict->getObject(key));
1304 }
1305
1306 IONetworkData * IONetworkInterface::getNetworkData(const char * key) const
1307 {
1308 return OSDynamicCast(IONetworkData, _dataDict->getObject(key));
1309 }
1310
1311 //---------------------------------------------------------------------------
1312 // A private function to copy the data dictionary to the property table.
1313
1314 bool IONetworkInterface::_syncNetworkDataDict()
1315 {
1316 OSDictionary * aCopy = OSDictionary::withDictionary(_dataDict);
1317 bool ret = false;
1318
1319 if (aCopy) {
1320 ret = setProperty(kIONetworkData, aCopy);
1321 aCopy->release();
1322 }
1323
1324 return ret;
1325 }
1326
1327 //---------------------------------------------------------------------------
1328 // Remove an entry from the IONetworkData dictionary managed by the interface.
1329 // The removed object is released.
1330
1331 bool IONetworkInterface::removeNetworkData(const OSSymbol * aKey)
1332 {
1333 bool ret = false;
1334
1335 lock();
1336
1337 do {
1338 if ( getInterfaceState() & kIONetworkInterfaceOpenedState )
1339 break;
1340
1341 _dataDict->removeObject(aKey);
1342 ret = _syncNetworkDataDict();
1343 }
1344 while (0);
1345
1346 unlock();
1347
1348 return ret;
1349 }
1350
1351 bool IONetworkInterface::removeNetworkData(const char * aKey)
1352 {
1353 bool ret = false;
1354
1355 lock();
1356
1357 do {
1358 if ( getInterfaceState() & kIONetworkInterfaceOpenedState )
1359 break;
1360
1361 _dataDict->removeObject(aKey);
1362 ret = _syncNetworkDataDict();
1363 }
1364 while (0);
1365
1366 unlock();
1367
1368 return ret;
1369 }
1370
1371 //---------------------------------------------------------------------------
1372 // Add an IONetworkData object to a dictionary managed by the interface.
1373
1374 bool IONetworkInterface::addNetworkData(IONetworkData * aData)
1375 {
1376 bool ret = false;
1377
1378 if (OSDynamicCast(IONetworkData, aData) == 0)
1379 return false;
1380
1381 lock();
1382
1383 if (( getInterfaceState() & kIONetworkInterfaceOpenedState ) == 0)
1384 {
1385 if ((ret = _dataDict->setObject(aData->getKey(), aData)))
1386 ret = _syncNetworkDataDict();
1387 }
1388
1389 unlock();
1390
1391 return ret;
1392 }
1393
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.
1398
1399 IOReturn IONetworkInterface::newUserClient(task_t owningTask,
1400 void * /*security_id*/,
1401 UInt32 type,
1402 IOUserClient ** handler)
1403 {
1404 IOReturn err = kIOReturnSuccess;
1405 IONetworkUserClient * client;
1406
1407 if (type != kIONUCType)
1408 return kIOReturnBadArgument;
1409
1410 client = IONetworkUserClient::withTask(owningTask);
1411
1412 if (!client || !client->attach(this) || !client->start(this))
1413 {
1414 if (client)
1415 {
1416 client->detach(this);
1417 client->release();
1418 client = 0;
1419 }
1420 err = kIOReturnNoMemory;
1421 }
1422
1423 *handler = client;
1424
1425 return err;
1426 }
1427
1428 //---------------------------------------------------------------------------
1429 // Handle controller's power state transitions.
1430
1431 IOReturn
1432 IONetworkInterface::controllerWillChangePowerState(
1433 IONetworkController * controller,
1434 IOPMPowerFlags flags,
1435 UInt32 stateNumber,
1436 IOService * policyMaker )
1437 {
1438 if ( ( flags & IOPMDeviceUsable ) == 0 )
1439 {
1440 setInterfaceState( kIONetworkInterfaceDisabledState );
1441 }
1442 return kIOReturnSuccess;
1443 }
1444
1445 IOReturn
1446 IONetworkInterface::controllerDidChangePowerState(
1447 IONetworkController * controller,
1448 IOPMPowerFlags flags,
1449 UInt32 stateNumber,
1450 IOService * policyMaker )
1451 {
1452 if ( flags & IOPMDeviceUsable )
1453 {
1454 setInterfaceState( 0, kIONetworkInterfaceDisabledState );
1455 }
1456 return kIOReturnSuccess;
1457 }
1458
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
1462 // functions.
1463
1464 IOReturn
1465 IONetworkInterface::sControllerWillChangePowerState(
1466 IONetworkInterface * netif,
1467 void * param0,
1468 void * param1,
1469 void * param2,
1470 void * param3 )
1471 {
1472 return netif->controllerWillChangePowerState(
1473 (IONetworkController *) param0,
1474 (IOPMPowerFlags) param1,
1475 (UInt32) param2,
1476 (IOService *) param3 );
1477 }
1478
1479 IOReturn
1480 IONetworkInterface::sControllerDidChangePowerState(
1481 IONetworkInterface * netif,
1482 void * param0,
1483 void * param1,
1484 void * param2,
1485 void * param3 )
1486 {
1487 return netif->controllerDidChangePowerState(
1488 (IONetworkController *) param0,
1489 (IOPMPowerFlags) param1,
1490 (UInt32) param2,
1491 (IOService *) param3 );
1492 }
1493
1494 //---------------------------------------------------------------------------
1495 // Handle notitifications triggered by controller's power state change.
1496
1497 IOReturn
1498 IONetworkInterface::powerStateWillChangeTo( IOPMPowerFlags flags,
1499 UInt32 stateNumber,
1500 IOService * policyMaker )
1501 {
1502 _controller->executeCommand(
1503 this, /* client */
1504 (IONetworkController::Action)
1505 &IONetworkInterface::sControllerWillChangePowerState,
1506 this, /* target */
1507 (void *) _controller, /* param0 */
1508 (void *) flags, /* param1 */
1509 (void *) stateNumber, /* param2 */
1510 (void *) policyMaker); /* param3 */
1511
1512 return IOPMAckImplied;
1513 }
1514
1515 IOReturn
1516 IONetworkInterface::powerStateDidChangeTo( IOPMPowerFlags flags,
1517 UInt32 stateNumber,
1518 IOService * policyMaker )
1519 {
1520 _controller->executeCommand(
1521 this, /* client */
1522 (IONetworkController::Action)
1523 &IONetworkInterface::sControllerDidChangePowerState,
1524 this, /* target */
1525 (void *) _controller, /* param0 */
1526 (void *) flags, /* param1 */
1527 (void *) stateNumber, /* param2 */
1528 (void *) policyMaker); /* param3 */
1529
1530 return IOPMAckImplied;
1531 }