|
|
1.1 root 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/IOMessage.h>
35: #include <IOKit/network/IONetworkInterface.h>
36: #include <IOKit/network/IONetworkController.h>
37: #include <IOKit/network/IONetworkUserClient.h>
38:
39: extern "C" {
40: #include <sys/param.h>
41: #include <sys/mbuf.h>
42: #include <sys/socket.h>
43: #include <sys/sockio.h>
44: #include <net/bpf.h>
45: #include <net/if.h>
46: #include <netinet/if_ether.h>
47: #include <net/if_media.h>
48: #include <net/dlil.h>
49: int copyout(void *kaddr, void *udaddr, size_t len);
50: }
51:
52: //---------------------------------------------------------------------------
53:
54: #define super IOService
55:
56: OSDefineMetaClass( IONetworkInterface, IOService )
57: OSDefineAbstractStructors( IONetworkInterface, IOService )
58:
59: //---------------------------------------------------------------------------
60: // Macros
61:
62: #ifdef DEBUG
63: #define DLOG(fmt, args...) IOLog(fmt, ## args)
64: #else
65: #define DLOG
66: #endif
67:
68: //---------------------------------------------------------------------------
69: // Initialize an IONetworkInterface instance.
70: //
71: // properties: A property dictionary.
72: //
73: // Returns true if initialized successfully, false otherwise.
74:
75: bool IONetworkInterface::init(OSDictionary * properties = 0)
76: {
77: _provider = 0; // single IONetworkController provider.
78: _ifLock = 0; // locks interface state and data accesses.
79: _clientSet = 0; // A set of all client objects.
80: _inputFilterFunc = 0; // input filter tap handler.
81: _outputFilterFunc = 0; // output filter tap handler.
82: _target = 0; // output target object.
83: _outAction = 0; // output packet action.
84: _dataDict = 0; // IONetworkData dict.
85: _registered = false;
86:
87: inputQHead = inputQTail = 0;
88:
89: // Propagate the init() call to our superclass.
90: //
91: if (!super::init(properties))
92: return false;
93:
94: // Create interface lock.
95: //
96: _ifLock = IORecursiveLockAlloc();
97: if (!_ifLock)
98: return false;
99:
100: // Create an OSSet to store client objects. Initial capacity
101: // (which can grow) is set at 2 clients.
102: //
103: _clientSet = OSSet::withCapacity(2);
104: if (!_clientSet)
105: return false;
106:
107: // Get the ifnet structure of the network interface. Subclasses must
108: // implement getIfnet() and expect this function to be called when
109: // they call IONetworkInterface::init().
110: //
111: _ifp = getIfnet();
112: if (!_ifp)
113: {
114: DLOG("%s: getIfnet() returned NULL\n", getName());
115: return false;
116: }
117:
118: // Intialize the ifnet structure.
119: //
120: if (!initIfnet(_ifp))
121: return false;
122:
123: // Create a data dictionary.
124: //
125: if ((_dataDict = OSDictionary::withCapacity(5)) == 0)
126: return false;
127:
128: IONetworkData * data = IONetworkData::withName(
129: kIONetworkStatsKey,
130: sizeof(IONetworkStats),
131: (UInt8 *) &(_ifp->if_data.ifi_ipackets));
132: if (data) {
133: addNetworkData(data);
134: data->release();
135: }
136:
137: // Set the default filter tap mode for both directions to
138: // kIOFilterTapModeInternal. Both taps will automatically receive all
139: // packets that flow through the interface in their respective
140: // directions.
141: //
142: _inputFilterTapMode = _outputFilterTapMode = kIOFilterTapModeInternal;
143:
144: return true;
145: }
146:
147: //---------------------------------------------------------------------------
148: // Destroy the interface. Release all allocated resources.
149:
150: void IONetworkInterface::free()
151: {
152: DLOG("IONetworkInterface::free() called\n");
153:
154: // Must never free a registered interface.
155:
156: assert(_registered == false);
157:
158: if (_clientSet)
159: {
160: // Should not have any clients.
161: //
162: assert(_clientSet->getCount() == 0);
163: _clientSet->release();
164: }
165:
166: if (_ifLock)
167: {
168: IORecursiveLockFree(_ifLock);
169: _ifLock = 0;
170: }
171:
172: if (_dataDict)
173: _dataDict->release();
174:
175: clearInputQueue();
176:
177: super::free();
178: }
179:
180: //---------------------------------------------------------------------------
181: // Initialize the ifnet structure. Subclasses must override this
182: // method and initialize the ifnet structure given in a family specific
183: // manner. The implementation of this method in the subclass must call
184: // the version in super before it returns. The argument provided is a
185: // pointer to an ifnet structure obtained through getIfnet().
186: // IONetworkInterface uses this method to initialize the function
187: // pointers in ifnet.
188: //
189: // ifp: Pointer to an ifnet structure obtained through an earlier
190: // getIfnet() call.
191: //
192: // Returns true if the initialization was successful.
193:
194: bool IONetworkInterface::initIfnet(struct ifnet * ifp)
195: {
196: lock();
197:
198: // Register our 'shim' functions. These function pointers
199: // points to static member functions inside class.
200:
201: ifp->if_output = output_shim;
202: ifp->if_ioctl = ioctl_shim;
203: ifp->if_set_bpf_tap = set_bpf_tap_shim;
204: ifp->if_private = this;
205:
206: // Enable driver reentrancy. This allows the network stack
207: // to call the driver from the same thread that sent a received
208: // packet up to the stack. The netisr thread is bypassed. The context
209: // switch cost is eliminated, but how long will the driver have to wait
210: // before the thread can return to do driver work?
211: //
212: // Not enabled by default, do this on a per driver basis by calling,
213: // netif->setExtraFlags(IFEF_DVR_REENTRY_OK) from the driver's
214: // configureNetworkInterface() function.
215: //
216: // ifp->if_eflags |= IFEF_DVR_REENTRY_OK;
217:
218: unlock();
219:
220: return true;
221: }
222:
223: //---------------------------------------------------------------------------
224: // Take the interface lock (recursive lock).
225:
226: void IONetworkInterface::lock()
227: {
228: IORecursiveLockLock(_ifLock);
229: }
230:
231: //---------------------------------------------------------------------------
232: // Release the interface lock (recursive lock).
233:
234: void IONetworkInterface::unlock()
235: {
236: IORecursiveLockUnlock(_ifLock);
237: }
238:
239: //---------------------------------------------------------------------------
240: // Called by handleOpen() to configure our controller after we have just
241: // called he controller's open() method. We open the controller only when
242: // we receive the initial open request from a client. Subclasses should
243: // override this method and setup the controller before allowing the
244: // client open, and they must call this method and check the return
245: // value in their implementation.
246: //
247: // controller: Our controller object.
248: //
249: // Must return true in order for handleOpen() to accept the client open.
250: // If the return is false, then the controller will be closed and the client
251: // open will be rejected.
252:
253: bool IONetworkInterface::controllerDidOpen(IONetworkController * controller)
254: {
255: return true; // open approved.
256: }
257:
258: //---------------------------------------------------------------------------
259: // Called by handleClose() after receiving a close from the
260: // last client, and just before the controller is closed. Subclasses
261: // can override this method to perform any cleanup action before the
262: // controller is closed.
263: //
264: // controller: The controller that will be closed.
265:
266: void IONetworkInterface::controllerWillClose(IONetworkController * controller)
267: {
268: }
269:
270: //---------------------------------------------------------------------------
271: // Handle a client open on the interface. The open() method in IOService
272: // calls this method with the arbitration lock held. This method must
273: // return true to accept the client open. Subclasses should not override
274: // this method.
275: //
276: // client: See IOService.
277: // options: See IOService.
278: // argument: See IOService.
279: //
280: // Returns true to accept the client open.
281:
282: bool IONetworkInterface::handleOpen(IOService * client,
283: IOOptionBits options,
284: void * argument)
285: {
286: bool accept = false;
287: bool controllerOpen = false;
288: IONetworkController * controller = OSDynamicCast(IONetworkController,
289: getProvider());
290:
291: do {
292: // Was this object already registered as our client?
293: //
294: if (_clientSet->containsObject(client))
295: {
296: DLOG("%s: multiple opens from client %lx\n",
297: getName(), (UInt32) client);
298: accept = true;
299: break;
300: }
301:
302: // We can only provide services to a single client.
303: // IONetworkUserClient are excluded from this restriction.
304: //
305: bool isClient = (OSDynamicCast(IONetworkUserClient, client) == 0);
306: if (isClient && _client)
307: {
308: DLOG("%s: extra client %lx\n", getName(), (UInt32) client);
309: break;
310: }
311:
312: // If our provider has not yet been opened, then open it.
313: // However if the controller open fails, then we will not allow
314: // the new client to open us.
315: //
316: if (_provider == 0) {
317: if ((controller == 0) ||
318: ((controllerOpen = controller->open(this)) == false) ||
319: (controllerDidOpen(controller) == false))
320: break;
321: }
322:
323: // Qualify the client.
324: //
325: if (!handleClientOpen(controller, client))
326: break;
327:
328: // Add the new client object to our client set.
329: //
330: if (!_clientSet->setObject(client))
331: {
332: handleClientClose(controller, client);
333: break;
334: }
335:
336: // Remember our client.
337: //
338: if (isClient)
339: _client = client;
340:
341: accept = true;
342: }
343: while (0);
344:
345: // If provider was opened above, but an error has caused us to refuse
346: // the client open, then close our provider. Otherwise, cache our
347: // provider.
348: //
349: if (controllerOpen)
350: {
351: if (accept)
352: {
353: _provider = controller; // cache our provider.
354: }
355: else {
356: controllerWillClose(controller);
357: controller->close(this);
358: }
359: }
360:
361: return accept;
362: }
363:
364: //---------------------------------------------------------------------------
365: // Handle a close by one of our clients. We close the controller when
366: // we receive a close from our last client. The close() method in
367: // IOService calls this method with the arbitration lock held.
368: // Subclasses should not override this method.
369: //
370: // client: See IOService.
371: // options: See IOService.
372:
373: void IONetworkInterface::handleClose(IOService * client, IOOptionBits options)
374: {
375: // Remove the object from the client OSSet.
376: //
377: if (_clientSet->containsObject(client))
378: {
379: bool isClient = (OSDynamicCast(IONetworkUserClient, client) == 0);
380:
381: // Call handleClientClose() to handle the client close.
382: //
383: assert(_provider);
384: handleClientClose(_provider, client);
385:
386: if (isClient)
387: _client = 0;
388:
389: // If this is the last client, then close our provider.
390: //
391: if (_clientSet->getCount() == 1)
392: {
393: controllerWillClose(_provider);
394: _provider->close(this);
395: _provider = 0;
396: }
397:
398: // Remove the client from our OSSet.
399: //
400: _clientSet->removeObject(client);
401: }
402: }
403:
404: //---------------------------------------------------------------------------
405: // Returns true if the specified client, or any client if none if
406: // specified, presently has an open on this object. This function
407: // is called by IOService with the arbitration lock held.
408: // Subclasses should not override this method.
409:
410: bool IONetworkInterface::handleIsOpen(const IOService * client) const
411: {
412: if (client)
413: return _clientSet->containsObject(client);
414: else
415: return (_clientSet->getCount() > 0);
416: }
417:
418: //---------------------------------------------------------------------------
419: // This method is called by handleOpen() to qualify a client
420: // object is trying to open us. This method must return true
421: // true to accept the client open. The provider of the
422: // interface object, an IONetworkController, is also provided.
423:
424: bool IONetworkInterface::handleClientOpen(IONetworkController * /*ctlr*/,
425: IOService * client)
426: {
427: bool allowOpen = true;
428:
429: // Always allow opens from IOUserClients.
430: //
431: if (OSDynamicCast(IONetworkUserClient, client))
432: return true;
433:
434: lock();
435:
436: // Packet output handler must be valid.
437: //
438: if (!_target || !_outAction)
439: allowOpen = false;
440:
441: // Transition state to registered.
442: //
443: if (allowOpen)
444: _registered = true;
445:
446: unlock();
447:
448: return allowOpen;
449: }
450:
451: //---------------------------------------------------------------------------
452: // Called by handleClose() to handle a client close. Both the provider
453: // and the client that performed the close are provided.
454:
455: void IONetworkInterface::handleClientClose(IONetworkController * /*ctlr*/,
456: IOService * client)
457: {
458: if (OSDynamicCast(IONetworkUserClient, client))
459: return;
460:
461: lock();
462:
463: // Transition state to unregistered.
464: //
465: _registered = false;
466:
467: unlock();
468: }
469:
470: //---------------------------------------------------------------------------
471: // Register the output handler. The interface will forward all output packets,
472: // sent from the network layer, to the output handler registered through
473: // this method. Until a handler is registered, handleClientOpen()
474: // will refuse all client opens. The output handler cannot be changed
475: // when the interface state is kIONetworkInterfaceStateRegistered.
476: //
477: // target: Target object that implements the output action.
478: // action: The action which handles output packets.
479:
480: bool IONetworkInterface::registerOutputHandler(OSObject * target,
481: IOOutputAction action)
482: {
483: target = OSDynamicCast(OSObject, target);
484:
485: lock();
486:
487: // Sanity check on the arguments.
488: //
489: if (_registered || !target || !action)
490: {
491: unlock();
492: return false;
493: }
494:
495: _target = target;
496: _outAction = action;
497:
498: unlock();
499:
500: return true;
501: }
502:
503: //---------------------------------------------------------------------------
504: // Functions to set and inspect the filter tap settings. These settings
505: // cannot change once the interface becomes registered.
506:
507: bool IONetworkInterface::_setFilterTapMode(IOFilterTapMode * modePtr,
508: IOFilterTapMode mode)
509: {
510: lock();
511:
512: if (_registered)
513: {
514: unlock();
515: return false;
516: }
517: *modePtr = mode;
518:
519: unlock();
520:
521: return true;
522: }
523:
524: bool IONetworkInterface::setInputFilterTapMode(IOFilterTapMode mode)
525: {
526: return _setFilterTapMode(&_inputFilterTapMode, mode);
527: }
528:
529: bool IONetworkInterface::setOutputFilterTapMode(IOFilterTapMode mode)
530: {
531: return _setFilterTapMode(&_outputFilterTapMode, mode);
532: }
533:
534: IOFilterTapMode IONetworkInterface::getInputFilterTapMode() const
535: {
536: return _inputFilterTapMode;
537: }
538:
539: IOFilterTapMode IONetworkInterface::getOutputFilterTapMode() const
540: {
541: return _outputFilterTapMode;
542: }
543:
544: //---------------------------------------------------------------------------
545: // Feed packets to the input/output BPF packet filter taps.
546:
547: static inline void _feedFilterTap(struct ifnet * ifp,
548: struct mbuf * m,
549: BPF_FUNC func,
550: int mode)
551: {
552: if (func)
553: func(ifp, m);
554: }
555:
556: //---------------------------------------------------------------------------
557: // Feed a packet to the output filter tap. This method should not be called if
558: // the output filter tap mode is set to kIOFilterTapModeInternal, since the tap
559: // would already receive every output packet that flows through the interface.
560: // A further call to feedOutputFilterTap() would cause the tap to receive
561: // multiple copies of the same output packet.
562: //
563: // pkt: The packet mbuf to pass to the output tap.
564:
565: void IONetworkInterface::feedOutputFilterTap(struct mbuf * m)
566: {
567: assert(m);
568: _feedFilterTap(_ifp, m, _outputFilterFunc, BPF_TAP_OUTPUT);
569: }
570:
571: //---------------------------------------------------------------------------
572: // Feed a packet to the input filter tap. This method should not be called if
573: // the input filter tap mode is set to kIOFilterTapModeInternal, since the tap
574: // would already receive every input packet that flows through the interface.
575: // A further call to feedInputFilterTap() would cause the tap to receive
576: // multiple copies of the same input packet
577: //
578: // pkt: The packet mbuf to pass to the input tap. The rcvif
579: // field in the mbuf is modified by this method.
580:
581: void IONetworkInterface::feedInputFilterTap(struct mbuf * m)
582: {
583: assert(m);
584: m->m_pkthdr.rcvif = _ifp;
585: _feedFilterTap(_ifp, m, _inputFilterFunc, BPF_TAP_INPUT);
586: }
587:
588: //---------------------------------------------------------------------------
589: // Called by a controller to pass a received packet
590: // to the network layer. Packets received by this method can
591: // also be placed on a queue local to the interface, that the controller
592: // can use to delay the packet handoff to the network layer, until all
593: // received packets have been transferred to the queue. A subsequent call
594: // of flushInputQueue(), or inputPacket() with the queue argument set to
595: // false, will cause all queued packets (may be a single packet) to be
596: // delivered to the network layer, by making a single dlil_input() call.
597: // Additional methods that manipulate the input queue are flushInputQueue()
598: // and clearInputQueue(). This queue, which is nothing more than a chain of
599: // mbufs, is not protected by a lock since the controller is expected to
600: // manipulate the input queue from a single thread. If the input filter
601: // tap mode is set to kIOFilterTapModeInternal, then packets sent to
602: // this method are also fed to the input filter tap.
603: //
604: // m: The packet mbuf containing the received frame.
605: //
606: // length: If non zero, the mbuf will be truncated to the
607: // given length. If zero, then no truncation will take place.
608: //
609: // queue: If true, the only action performed is to queue the
610: // input packet. Otherwise, the dlil_input() function is
611: // called to handoff all queued packets (including the packet
612: // passed in).
613: //
614: // Returns the number of packets submitted to the network layer.
615: // Returns 0 if the packet was queued.
616: //
617: // FIXME - The current implementation does not use the new DLIL API's.
618: // Thus it will only work for Ethernet devices.
619:
620: #define IN_Q_RESET {inputQHead = 0;}
621:
622: #define IN_Q_ENQUEUE(m) \
623: { \
624: if (inputQHead == 0) \
625: inputQHead = inputQTail = (m); \
626: else { \
627: inputQTail->m_nextpkt = (m); \
628: inputQTail = (m); \
629: } \
630: }
631:
632: #define IN_Q_FLUSH(count) \
633: { \
634: struct mbuf * _m; \
635: struct ether_header * _eh; \
636: \
637: count = 0; \
638: \
639: while ((_m = inputQHead)) { \
640: inputQHead = inputQHead->m_nextpkt; \
641: _m->m_nextpkt = 0; \
642: _m->m_pkthdr.rcvif = _ifp; \
643: \
644: if (_inputFilterTapMode == kIOFilterTapModeInternal) \
645: _feedFilterTap(_ifp, _m, _inputFilterFunc, BPF_TAP_INPUT); \
646: \
647: _eh = (struct ether_header *) _m->m_data; \
648: _m->m_len -= sizeof(struct ether_header); \
649: _m->m_data += sizeof(struct ether_header); \
650: _m->m_pkthdr.len -= sizeof(struct ether_header); \
651: \
652: dlil_input(_ifp, _m, (char *) _eh); \
653: count++; \
654: } \
655: }
656:
657: UInt32 IONetworkInterface::flushInputQueue()
658: {
659: UInt32 count;
660:
661: IN_Q_FLUSH(count);
662: // IN_Q_RESET;
663: return count;
664: }
665:
666: UInt32 IONetworkInterface::clearInputQueue()
667: {
668: UInt32 count = 0;
669: struct mbuf * m;
670:
671: while ((m = inputQHead))
672: {
673: inputQHead = inputQHead->m_nextpkt;
674: m_freem(m);
675: count++;
676: }
677: // IN_Q_RESET;
678: return count;
679: }
680:
681: UInt32 IONetworkInterface::inputPacket(struct mbuf * m,
682: UInt32 length = 0,
683: bool queue = false)
684: {
685: assert(m);
686:
687: // Truncate the tail of the mbuf chain to the specified length.
688: // The mbuf chain passed in will usually have the length in
689: // each mbuf set to its capacity.
690: //
691: if (length)
692: {
693: struct mbuf * mb = m;
694: mb->m_pkthdr.len = length; // set total length
695: do {
696: if (length < (UInt) mb->m_len)
697: {
698: mb->m_len = length; // truncate mbuf to remaining length
699: }
700: length -= mb->m_len; // decrement remaining length
701: } while ((mb = mb->m_next));
702: assert(length == 0); // why is capacity smaller than length?
703: }
704:
705: IN_Q_ENQUEUE(m);
706:
707: if (queue == false)
708: {
709: UInt32 count;
710: IN_Q_FLUSH(count);
711: // IN_Q_RESET;
712: return count;
713: }
714: else
715: return 0;
716: }
717:
718: //---------------------------------------------------------------------------
719: // Called by the controller driver to send a network event to the network
720: // layer. Possible applications include: media changed events,
721: // power management events, controller state change events.
722: //
723: // eventType: The event type.
724: // arg: An argument associated with the event.
725:
726: void IONetworkInterface::inputEvent(UInt32 eventType, void * arg)
727: {
728: switch (eventType)
729: {
730: case kIONetworkEventMediumChange:
731: case kIONetworkEventLinkChange:
732: _handleMediumAndLinkChangeEvent();
733: break;
734:
735: default:
736: IOLog("IONetworkInterface: event (%x, %x) not handled\n",
737: (UInt) eventType, (UInt) arg);
738: break;
739: }
740: }
741:
742: //---------------------------------------------------------------------------
743: // Handles media and link change events. Deliver a notification to
744: // all IONetworkUserClients.
745:
746: void IONetworkInterface::_handleMediumAndLinkChangeEvent()
747: {
748: OSCollectionIterator * iter;
749: IONetworkUserClient * uc;
750:
751: lockForArbitration();
752: iter = OSCollectionIterator::withCollection(_clientSet);
753: if (iter) {
754: while ((uc = (IONetworkUserClient *) iter->getNextObject())) {
755: if ((uc = OSDynamicCast(IONetworkUserClient, uc)) == 0)
756: continue;
757: uc->deliverNotification(kIONUCNotificationTypeLinkChange);
758: }
759: iter->release();
760: }
761: unlockForArbitration();
762: }
763:
764: //---------------------------------------------------------------------------
765: // SIOCSIFMTU (set interface MTU) ioctl handler.
766:
767: SInt IONetworkInterface::syncSIOCSIFMTU(IONetworkController * ctlr,
768: struct ifreq * ifr)
769: {
770: SInt error;
771: UInt32 newMtu = ifr->ifr_mtu;
772:
773: // If change is not necessary, return success without getting the
774: // controller involved.
775:
776: if (getMaxTransferUnit() == newMtu)
777: return 0;
778:
779: // Request the controller to switch MTU size.
780: //
781: error = errnoFromReturn(ctlr->doSetMaxTransferUnit(this, newMtu));
782:
783: if (error == 0)
784: {
785: // Controller reports success. Update the interface MTU size
786: // property.
787: //
788: setMaxTransferUnitInt(newMtu);
789: }
790:
791: return error;
792: }
793:
794: //---------------------------------------------------------------------------
795: // SIOCSIFMEDIA (SET interface media) ioctl handler.
796:
797: SInt IONetworkInterface::syncSIOCSIFMEDIA(IONetworkController * ctlr,
798: struct ifreq * ifr)
799: {
800: OSDictionary * mediumDict;
801: IONetworkMedium * medium;
802: SInt error;
803:
804: mediumDict = ctlr->copyMediumDictionary(); // creates a copy
805: if (!mediumDict)
806: {
807: // unable to allocate memory, or no medium dictionary.
808: return EOPNOTSUPP;
809: }
810:
811: medium = IONetworkMedium::getMediumWithType(mediumDict, ifr->ifr_media);
812: if (!medium)
813: {
814: // Exact type was not found. Try a partial match.
815: // ifconfig program sets the media type and media
816: // options separately. The client should not send
817: // an incomplete type!!!
818:
819: medium = IONetworkMedium::getMediumWithType(mediumDict,
820: ifr->ifr_media,
821: ~kIOMediumTypeMask);
822: if (!medium)
823: {
824: mediumDict->release();
825: return EINVAL; // requested medium not found.
826: }
827: }
828:
829: // It may be possible for the controller to update the medium
830: // dictionary and perhaps delete the medium entry that we have
831: // selected from our copy of the stale dictionary. This should be
832: // harmless since IONetworkController's doSelectMedium() should
833: // filter invalid selections before calling the driver.
834:
835: error = errnoFromReturn(ctlr->doSelectMedium(this, medium->getName()));
836:
837: if (error == 0)
838: {
839: // Remember the last media type sent by BSD which the driver
840: // accepted. Note that _bsdMediaType may not be equal to
841: // medium->getType() since we may have done a partial match.
842: // The only reason for this is to be able to return the
843: // _bsdMediaType as the current media type in SICGIFMEDIA.
844:
845: _bsdMediaType = ifr->ifr_media;
846: }
847:
848: mediumDict->release();
849:
850: return error;
851: }
852:
853: //---------------------------------------------------------------------------
854: // SIOCGIFMEDIA (GET interface media) ioctl handler.
855:
856: SInt IONetworkInterface::syncSIOCGIFMEDIA(IONetworkController * ctlr,
857: struct ifreq * ifr)
858: {
859: OSDictionary * mediumDict = 0;
860: UInt mediumCount = 0;
861: UInt maxCount;
862: OSCollectionIterator * iter = 0;
863: UInt32 * typeList;
864: UInt typeListSize;
865: OSSymbol * keyObject;
866: SInt error = 0;
867: struct ifmediareq * ifmr = (struct ifmediareq *) ifr;
868:
869: // Maximum number of medium types that the ioctl caller will accept.
870: //
871: maxCount = ifmr->ifm_count;
872:
873: do {
874: mediumDict = ctlr->copyMediumDictionary(); // creates a copy
875: if (!mediumDict)
876: {
877: error = EOPNOTSUPP;
878: break; // unable to allocate memory, or no medium dictionary.
879: }
880:
881: if ((mediumCount = mediumDict->getCount()) == 0)
882: break; // no medium in the medium dictionary
883:
884: if (maxCount == 0)
885: break; // caller is only probing for support and media count.
886:
887: if (maxCount < mediumCount)
888: {
889: // user buffer is too small to hold all medium entries.
890: error = E2BIG;
891:
892: // Proceed with partial copy on E2BIG. This follows the
893: // SIOCGIFMEDIA handling practice in bsd/net/if_media.c.
894: //
895: // break;
896: }
897:
898: // Create an iterator to loop through the medium entries in the
899: // dictionary.
900: //
901: iter = OSCollectionIterator::withCollection(mediumDict);
902: if (!iter)
903: {
904: error = ENOMEM;
905: break;
906: }
907:
908: // Allocate memory for the copyout buffer.
909: //
910: typeListSize = maxCount * sizeof(UInt32);
911: typeList = (UInt32 *) IOMalloc(typeListSize);
912: if (!typeList)
913: {
914: error = ENOMEM;
915: break;
916: }
917: bzero(typeList, typeListSize);
918:
919: // Iterate through the medium dictionary and copy the type of
920: // each medium entry to typeList[].
921: //
922: mediumCount = 0;
923: while ( (keyObject = (OSSymbol *) iter->getNextObject()) &&
924: (mediumCount < maxCount) )
925: {
926: IONetworkMedium * medium = OSDynamicCast(IONetworkMedium,
927: mediumDict->getObject(keyObject));
928: if (!medium)
929: continue; // should not happen!
930:
931: typeList[mediumCount++] = medium->getType();
932: }
933:
934: if (mediumCount)
935: {
936: error = copyout((caddr_t) typeList,
937: (caddr_t) ifmr->ifm_ulist,
938: typeListSize);
939: }
940:
941: IOFree(typeList, typeListSize);
942: }
943: while (0);
944:
945: ifmr->ifm_active = ifmr->ifm_current = IFM_NONE;
946: ifmr->ifm_status = 0;
947: ifmr->ifm_count = mediumCount;
948:
949: // Get a copy of the controller's property table and read the
950: // link status, current, and active medium.
951:
952: OSDictionary * pTable = ctlr->dictionaryWithProperties();
953: if (pTable)
954: {
955: OSNumber * linkStatus = OSDynamicCast(OSNumber,
956: pTable->getObject(kIOLinkStatus));
957: if (linkStatus)
958: ifmr->ifm_status = linkStatus->unsigned32BitValue();
959:
960: if (mediumDict)
961: {
962: IONetworkMedium * medium;
963: OSSymbol * mediumName;
964:
965: if ((mediumName = OSDynamicCast(OSSymbol,
966: pTable->getObject(kIOCurrentMedium))) &&
967: (medium = OSDynamicCast(IONetworkMedium,
968: mediumDict->getObject(mediumName))))
969: {
970: ifmr->ifm_current = medium->getType();
971: if (IOMediumGetType(_bsdMediaType) ==
972: IOMediumGetType((UInt32) ifmr->ifm_current))
973: {
974: ifmr->ifm_current = _bsdMediaType;
975: }
976: }
977:
978: if ((mediumName = OSDynamicCast(OSSymbol,
979: pTable->getObject(kIOActiveMedium))) &&
980: (medium = OSDynamicCast(IONetworkMedium,
981: mediumDict->getObject(mediumName))))
982: {
983: ifmr->ifm_active = medium->getType();
984: }
985: }
986: pTable->release();
987: }
988:
989: if (iter)
990: iter->release();
991: if (mediumDict)
992: mediumDict->release();
993:
994: return error;
995: }
996:
997: //---------------------------------------------------------------------------
998: // Handles generic socket ioctl commands sent to the interface.
999: // IONetworkInterface handles commands that are common to all network
1000: // families. A subclass of IONetworkInterface may override this method
1001: // in order to handle the same command that is handled here, but in a
1002: // different manner, or (the more like case) to augment the command
1003: // handling to include additional commands, and call super for any
1004: // commands not handled in the subclass.
1005: //
1006: // The commands handled by IONetworkInterface are:
1007: // SIOCGIFMTU - Get interface MTU size.
1008: // SIOCSIFMTU - Set interface MTU size.
1009: // SIOCSIFMEDIA - Set media.
1010: // SIOCGIFMEDIA - Get media and link status.
1011: //
1012: // Returns a BSD return code defined in bsd/sys/errno.h.
1013:
1014: SInt IONetworkInterface::performCommand(IONetworkController * ctlr,
1015: UInt32 cmd,
1016: void * arg0,
1017: void * arg1)
1018: {
1019: SInt ret = EBUSY;
1020:
1021: ctlr->syncRequest(this, /* sender */
1022: this, /* target */
1023: (IONetworkAction) &IONetworkInterface::syncPerformCommand,
1024: (UInt32 *) &ret, /* return */
1025: (void *) ctlr, /* arg0 - arg3 */
1026: (void *) cmd,
1027: (void *) arg0,
1028: (void *) arg1);
1029:
1030: return ret;
1031: }
1032:
1033: SInt IONetworkInterface::syncPerformCommand(IONetworkController * ctlr,
1034: UInt32 cmd,
1035: void * arg0,
1036: void * arg1)
1037: {
1038: struct ifreq * ifr = (struct ifreq *) arg1;
1039: SInt ret = EINVAL;
1040:
1041: if (ifr == 0)
1042: return EINVAL;
1043:
1044: switch (cmd)
1045: {
1046: // Get interface MTU.
1047: //
1048: case SIOCGIFMTU:
1049: ifr->ifr_mtu = getMaxTransferUnit();
1050: ret = 0; // no error
1051: break;
1052:
1053: // Set interface MTU.
1054: //
1055: case SIOCSIFMTU:
1056: ret = syncSIOCSIFMTU(ctlr, ifr);
1057: break;
1058:
1059: // Set interface media type.
1060: //
1061: case SIOCSIFMEDIA:
1062: ret = syncSIOCSIFMEDIA(ctlr, ifr);
1063: break;
1064:
1065: // Get interface media type and status.
1066: //
1067: case SIOCGIFMEDIA:
1068: ret = syncSIOCGIFMEDIA(ctlr, ifr);
1069: break;
1070:
1071: default:
1072: // DLOG(%s: command not handled (%08lx), getName(), cmd);
1073: break;
1074: }
1075:
1076: return ret;
1077: }
1078:
1079: //---------------------------------------------------------------------------
1080: // if_ioctl() handler - Calls performCommand() when we receive an ioctl
1081: // command from the network stack.
1082:
1083: int
1084: IONetworkInterface::ioctl_shim(struct ifnet * ifp, u_long cmd, caddr_t data)
1085: {
1086: assert(ifp && ifp->if_private);
1087:
1088: IONetworkInterface * self = (IONetworkInterface *) ifp->if_private;
1089:
1090: assert((ifp == self->_ifp) && self->_provider);
1091:
1092: return self->performCommand(self->_provider,
1093: cmd,
1094: (void *) ifp,
1095: (void *) data);
1096: }
1097:
1098: //---------------------------------------------------------------------------
1099: // if_output() handler.
1100: //
1101: // Handle a call from the network stack to transmit all packets in
1102: // the ifnet's output queue. This queue is likely to be removed in
1103: // the future when DLIL gets rolled out.
1104:
1105: int IONetworkInterface::output_shim(struct ifnet * ifp, struct mbuf * m)
1106: {
1107: assert(ifp && ifp->if_private);
1108:
1109: IONetworkInterface * self = (IONetworkInterface *) ifp->if_private;
1110:
1111: assert(ifp == self->_ifp);
1112:
1113: if (m == 0)
1114: {
1115: DLOG("IONetworkInterface: NULL output mbuf\n");
1116: return EINVAL;
1117: }
1118:
1119: if ((m->m_flags & M_PKTHDR) == 0)
1120: {
1121: DLOG("IONetworkInterface: M_PKTHDR bit not set\n");
1122: m_freem(m);
1123: return EINVAL;
1124: }
1125:
1126: // Feed the output filter tap.
1127: //
1128: if (self->_outputFilterTapMode == kIOFilterTapModeInternal)
1129: _feedFilterTap(ifp, m, self->_outputFilterFunc, BPF_TAP_OUTPUT);
1130:
1131: // Forward the packet to the registered output packet handler.
1132: //
1133: return ((self->_target)->*(self->_outAction))(m);
1134: }
1135:
1136: //---------------------------------------------------------------------------
1137: // if_set_bpf_tap() handler. Handles request from the DLIL to enable or
1138: // disable the input/output filter taps.
1139: //
1140: // FIXME - locking may be needed.
1141:
1142: int IONetworkInterface::set_bpf_tap_shim(struct ifnet * ifp,
1143: int mode,
1144: BPF_FUNC func)
1145: {
1146: assert(ifp && ifp->if_private);
1147:
1148: IONetworkInterface * self = (IONetworkInterface *) ifp->if_private;
1149:
1150: assert(ifp == self->_ifp);
1151:
1152: switch (mode)
1153: {
1154: case BPF_TAP_DISABLE:
1155: self->_inputFilterFunc = self->_outputFilterFunc = 0;
1156: break;
1157:
1158: case BPF_TAP_INPUT:
1159: assert(func);
1160: self->_inputFilterFunc = func;
1161: break;
1162:
1163: case BPF_TAP_OUTPUT:
1164: assert(func);
1165: self->_outputFilterFunc = func;
1166: break;
1167:
1168: case BPF_TAP_INPUT_OUTPUT:
1169: assert(func);
1170: self->_inputFilterFunc = self->_outputFilterFunc = func;
1171: break;
1172:
1173: default:
1174: DLOG("IONetworkInterface: Unknown BPF tap mode %d\n", mode);
1175: break;
1176: }
1177:
1178: return 0;
1179: }
1180:
1181: //---------------------------------------------------------------------------
1182: // As the name implies, this function does nothing. This will get called
1183: // if the network stack tries to call the if_watchdog function pointer
1184: // in ifnet. This should not happen. IOKit does not use this watchdog
1185: // timer facility.
1186:
1187: void IONetworkInterface::null_shim(struct ifnet * /*ifp*/)
1188: {
1189: IOLog("IONetworkInterface::null_shim called!\n");
1190: }
1191:
1192: //---------------------------------------------------------------------------
1193: // ifnet field (and property table) getter/setter.
1194: //
1195: // For the setter, if restrict flag is set, that means that the property is
1196: // restricted from being modified once the interface's has been registered.
1197:
1198: bool IONetworkInterface::_setInterfaceProperty(
1199: UInt32 value,
1200: UInt32 mask,
1201: UInt32 bytes,
1202: void * addr,
1203: char * key,
1204: bool restrict)
1205: {
1206: bool updateOk = false;
1207: UInt32 newValue;
1208:
1209: lock();
1210:
1211: if (restrict && (_registered == true))
1212: goto abort;
1213:
1214: // Update the property in ifnet.
1215: //
1216: switch (bytes)
1217: {
1218: case 1:
1219: newValue = (*((UInt8 *) addr) & mask) | value;
1220: *((UInt8 *) addr) = (UInt8) newValue;
1221: break;
1222: case 2:
1223: newValue = (*((UInt16 *) addr) & mask) | value;
1224: *((UInt16 *) addr) = (UInt16) newValue;
1225: break;
1226: case 4:
1227: newValue = (*((UInt32 *) addr) & mask) | value;
1228: *((UInt32 *) addr) = (UInt32) newValue;
1229: break;
1230: default:
1231: goto abort;
1232: }
1233:
1234: // Update the OSNumber in the property table.
1235: //
1236: updateOk = key ? setProperty(key, newValue, bytes * 8) : true;
1237:
1238: abort:
1239: unlock();
1240: return updateOk;
1241: }
1242:
1243: #define IO_IFNET_GET(func, type, field) \
1244: type IONetworkInterface:: ## func() const \
1245: { \
1246: type ret; \
1247: ((IONetworkInterface *) this)->lock(); \
1248: ret = _ifp ? _ifp-> ## field : 0; \
1249: ((IONetworkInterface *) this)->unlock(); \
1250: return ret; \
1251: }
1252:
1253: #define IO_IFNET_SET(func, type, field, propName) \
1254: bool IONetworkInterface:: ## func ## Int(type value) \
1255: { \
1256: return _setInterfaceProperty( \
1257: (UInt32) value, \
1258: 0, \
1259: sizeof(type), \
1260: (void *) &_ifp-> ## field, \
1261: propName, \
1262: false); \
1263: } \
1264: \
1265: bool IONetworkInterface:: ## func(type value) \
1266: { \
1267: return _setInterfaceProperty( \
1268: (UInt32) value, \
1269: 0, \
1270: sizeof(type), \
1271: (void *) &_ifp-> ## field, \
1272: propName, \
1273: true); \
1274: }
1275:
1276: #define IO_IFNET_RMW(func, type, field, propName) \
1277: bool IONetworkInterface:: ## func ## Int(type value, type clear = 0) \
1278: { \
1279: return _setInterfaceProperty( \
1280: (UInt32) value, \
1281: (UInt32) ~clear, \
1282: sizeof(type), \
1283: (void *) &_ifp-> ## field, \
1284: propName, \
1285: false); \
1286: } \
1287: \
1288: bool IONetworkInterface:: ## func(type value, type clear = 0) \
1289: { \
1290: return _setInterfaceProperty( \
1291: (UInt32) value, \
1292: (UInt32) ~clear, \
1293: sizeof(type), \
1294: (void *) &_ifp-> ## field, \
1295: propName, \
1296: true); \
1297: }
1298:
1299: //---------------------------------------------------------------------------
1300: // Interface type accessors (ifp->if_type). The list of interface types is
1301: // defined in <bsd/net/if_types.h>.
1302:
1303: IO_IFNET_SET(setInterfaceType, UInt8, if_type, kIOInterfaceType)
1304: IO_IFNET_GET(getInterfaceType, UInt8, if_type)
1305:
1306: //---------------------------------------------------------------------------
1307: // Mtu (MaxTransferUnit) accessors (ifp->if_mtu).
1308:
1309: IO_IFNET_SET(setMaxTransferUnit, UInt32, if_mtu, kIOMaxTransferUnit)
1310: IO_IFNET_GET(getMaxTransferUnit, UInt32, if_mtu)
1311:
1312: //---------------------------------------------------------------------------
1313: // Flags accessors (ifp->if_flags). This is a read-modify-write operation.
1314:
1315: IO_IFNET_RMW(setFlags, UInt16, if_flags, kIOInterfaceFlags)
1316: IO_IFNET_GET(getFlags, UInt16, if_flags)
1317:
1318: //---------------------------------------------------------------------------
1319: // EFlags accessors (ifp->if_eflags). This is a read-modify-write operation.
1320:
1321: IO_IFNET_RMW(setExtraFlags, UInt32, if_eflags, kIOInterfaceExtraFlags)
1322: IO_IFNET_GET(getExtraFlags, UInt32, if_eflags)
1323:
1324: //---------------------------------------------------------------------------
1325: // MediaAddressLength accessors (ifp->if_addrlen)
1326:
1327: IO_IFNET_SET(setMediaAddressLength, UInt8, if_addrlen, kIOMediaAddressLength)
1328: IO_IFNET_GET(getMediaAddressLength, UInt8, if_addrlen)
1329:
1330: //---------------------------------------------------------------------------
1331: // MediaHeaderLength accessors (ifp->if_hdrlen)
1332:
1333: IO_IFNET_SET(setMediaHeaderLength, UInt8, if_hdrlen, kIOMediaHeaderLength)
1334: IO_IFNET_GET(getMediaHeaderLength, UInt8, if_hdrlen)
1335:
1336: //---------------------------------------------------------------------------
1337: // Interface unit number. The unit number for the interface is assigned
1338: // by our client.
1339:
1340: IO_IFNET_SET(setUnitNumber, UInt16, if_unit, 0)
1341: IO_IFNET_GET(getUnitNumber, UInt16, if_unit)
1342:
1343: //---------------------------------------------------------------------------
1344: // Interface name.
1345:
1346: IO_IFNET_SET(setInterfaceName, const char *, if_name, 0)
1347: IO_IFNET_GET(getInterfaceName, const char *, if_name)
1348:
1349: //---------------------------------------------------------------------------
1350: // Return true if the interface has been registered with the network layer,
1351: // false otherwise.
1352:
1353: bool IONetworkInterface::isRegistered() const
1354: {
1355: return _registered;
1356: }
1357:
1358: //---------------------------------------------------------------------------
1359: // Perform a lookup of the dictionary kept by the interface,
1360: // and return an entry that matches the specified string key.
1361: //
1362: // key: Search for an IONetworkData entry with this key.
1363: //
1364: // Returns the matching entry, or 0 if no match was found.
1365:
1366: IONetworkData * IONetworkInterface::getNetworkData(const OSSymbol * key) const
1367: {
1368: return OSDynamicCast(IONetworkData, _dataDict->getObject(key));
1369: }
1370:
1371: IONetworkData * IONetworkInterface::getNetworkData(const char * key) const
1372: {
1373: return OSDynamicCast(IONetworkData, _dataDict->getObject(key));
1374: }
1375:
1376: //---------------------------------------------------------------------------
1377: // A private function to copy the data dictionary to the property table.
1378:
1379: bool IONetworkInterface::_copyNetworkDataDictToPropertyTable()
1380: {
1381: OSDictionary * aCopy = OSDictionary::withDictionary(_dataDict);
1382: bool ret = false;
1383:
1384: if (aCopy) {
1385: ret = setProperty(kIONetworkData, _dataDict);
1386: aCopy->release();
1387: }
1388:
1389: return ret;
1390: }
1391:
1392: //---------------------------------------------------------------------------
1393: // Remove an entry from the dictionary of IONetworkData objects.
1394: //
1395: // aKey: A key for an IONetworkData entry in the dictionary.
1396: //
1397: // Returns true if completed without errors,
1398: // false if the operation was aborted.
1399:
1400: bool IONetworkInterface::removeNetworkData(const OSSymbol * aKey)
1401: {
1402: bool ret = false;
1403:
1404: lockForArbitration();
1405:
1406: do {
1407: if (_clientSet->getCount())
1408: break;
1409:
1410: _dataDict->removeObject(aKey);
1411: ret = _copyNetworkDataDictToPropertyTable();
1412: }
1413: while (0);
1414:
1415: unlockForArbitration();
1416:
1417: return ret;
1418: }
1419:
1420: bool IONetworkInterface::removeNetworkData(const char * aKey)
1421: {
1422: bool ret = false;
1423:
1424: lockForArbitration();
1425:
1426: do {
1427: if (_clientSet->getCount())
1428: break;
1429:
1430: _dataDict->removeObject(aKey);
1431: ret = _copyNetworkDataDictToPropertyTable();
1432: }
1433: while (0);
1434:
1435: unlockForArbitration();
1436:
1437: return ret;
1438: }
1439:
1440: //---------------------------------------------------------------------------
1441: // Add an IONetworkData object to a dictionary kept by
1442: // the interface.
1443: //
1444: // aData: An IONetworkData object.
1445: //
1446: // Returns true if the data object was added successfully, false otherwise.
1447:
1448: bool IONetworkInterface::addNetworkData(IONetworkData * aData)
1449: {
1450: bool ret = false;
1451:
1452: if (OSDynamicCast(IONetworkData, aData) == 0)
1453: return false;
1454:
1455: lockForArbitration();
1456:
1457: if (_clientSet->getCount() == 0)
1458: {
1459: if ((ret = _dataDict->setObject(aData->getKey(), aData)))
1460: ret = _copyNetworkDataDictToPropertyTable();
1461: }
1462:
1463: unlockForArbitration();
1464:
1465: return ret;
1466: }
1467:
1468: //---------------------------------------------------------------------------
1469: // Create a new IOUserClient to handle client requests. The default
1470: // implementation will create an IONetworkUserClient instance if
1471: // the type is kIONUCType.
1472:
1473: IOReturn IONetworkInterface::newUserClient(task_t owningTask,
1474: void * /*security_id*/,
1475: UInt32 type,
1476: IOUserClient ** handler)
1477: {
1478: IOReturn err = kIOReturnSuccess;
1479: IONetworkUserClient * client;
1480:
1481: if (type != kIONUCType)
1482: return kIOReturnBadArgument;
1483:
1484: client = IONetworkUserClient::withTask(owningTask);
1485:
1486: if (!client || !client->attach(this) || !client->start(this))
1487: {
1488: if (client)
1489: {
1490: client->detach(this);
1491: client->release();
1492: client = 0;
1493: }
1494: err = kIOReturnNoMemory;
1495: }
1496:
1497: *handler = client;
1498:
1499: return err;
1500: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.