Annotation of XNU/iokit/Families/IONetworking/IONetworkStack.cpp, revision 1.1

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:  * IONetworkStack.cpp - An IOKit proxy for the BSD network stack.
        !            26:  *
        !            27:  * HISTORY
        !            28:  *
        !            29:  * IONetworkStack abstracts certain essential network stack services.
        !            30:  * Those services include attaching/detaching network interfaces, and
        !            31:  * interface naming. Note that although BSD network stack does not assign
        !            32:  * interface names, it is the responsibility of this object to manage the
        !            33:  * interface name space.
        !            34:  *
        !            35:  * IONetworkStack is a client of IONetworkInterface. This object uses the
        !            36:  * standard IOKit matching mechanism to discover and attach to interface
        !            37:  * objects. Each interface object is expected to have only a single
        !            38:  * IONetworkStack client. Under IOKit, the stack object initiates the
        !            39:  * action to attach to an interface. And subsequently, detaches from an
        !            40:  * interface when signaled to do so.
        !            41:  *
        !            42:  * The packet flow bypasses this object for efficiency sake. The interface
        !            43:  * object interact directly with the 'real' network stack to send and
        !            44:  * receive packets.
        !            45:  */
        !            46: 
        !            47: #include <IOKit/assert.h>
        !            48: #include <IOKit/IOLib.h>
        !            49: #include <IOKit/IOBSD.h>
        !            50: #include <IOKit/IOMessage.h>
        !            51: #include <IOKit/network/IONetworkInterface.h>
        !            52: #include <IOKit/network/IONetworkController.h>
        !            53: #include "IONetworkStack.h"
        !            54: 
        !            55: extern "C" {
        !            56: #include <sys/param.h>
        !            57: #include <sys/mbuf.h>
        !            58: #include <sys/socket.h>
        !            59: #include <net/bpf.h>
        !            60: #include <net/if.h>
        !            61: #include <netinet/if_ether.h>
        !            62: }
        !            63: 
        !            64: #define super IOService
        !            65: 
        !            66: OSDefineMetaClassAndStructorsWithInit( IONetworkStack,
        !            67:                                        IOService,
        !            68:                                        IONetworkStack::initialize())
        !            69: 
        !            70: #ifdef  DEBUG
        !            71: #define DLOG(fmt, args...)  IOLog(fmt, ## args)
        !            72: #else
        !            73: #define DLOG
        !            74: #endif
        !            75: 
        !            76: // Maintain a linked list of network interfaces.
        !            77: // Each time a new interface is added, an unit number is assigned,
        !            78: // and an interface entry is added to the list. When the interface
        !            79: // goes away, the entry is removed from the list and deallocated.
        !            80: //
        !            81: static queue_head_t         netifTable;
        !            82: static IOLock *             netifTableLock;
        !            83: 
        !            84: typedef struct {
        !            85:     IONetworkInterface *    netif;
        !            86:     const char *            name;
        !            87:     short                   unit;
        !            88:     queue_chain_t           link;
        !            89: } netifEntry;
        !            90: 
        !            91: #define BSD_IFNET_ENTRY     ((IONetworkInterface *) 0)
        !            92: #define NETIF_LOCK          IOTakeLock(netifTableLock)
        !            93: #define NETIF_UNLOCK        IOUnlock(netifTableLock)
        !            94: 
        !            95: #define LOCK                IOTakeLock(_lock);
        !            96: #define UNLOCK              IOUnlock(_lock);
        !            97: 
        !            98: // --------------------------------------------------------------------------
        !            99: //
        !           100: // Add a new entry to the netifTable for the interface 'netif'.
        !           101: // Return true if the entry was added successfully, otherwise
        !           102: // returns false.
        !           103: //
        !           104: // The table lock must be held by the caller of this function.
        !           105: //
        !           106: static bool addNetworkInterfaceEntry(IONetworkInterface * netif,
        !           107:                                      const char *         name,
        !           108:                                      short                unit)
        !           109: {
        !           110:     if (!netif || !name || (unit < 0)) return false;
        !           111: 
        !           112:     netifEntry * entry = (netifEntry *) IOMalloc(sizeof(netifEntry));
        !           113:     if (!entry)
        !           114:         return false;
        !           115:     bzero(entry, sizeof(*entry));
        !           116: 
        !           117:     entry->netif = netif;
        !           118:     entry->unit  = unit;
        !           119:     entry->name  = name;
        !           120: 
        !           121:     queue_enter(&netifTable, entry, netifEntry *, link);
        !           122: 
        !           123:     return true;
        !           124: }
        !           125: 
        !           126: // --------------------------------------------------------------------------
        !           127: //
        !           128: // Release the table entry occupied by the 'netif' instance.
        !           129: // Returns true if an entry was found and removed, otherwise
        !           130: // return false.
        !           131: //
        !           132: static bool releaseNetworkInterfaceEntry(IONetworkInterface * netif)
        !           133: {
        !           134:     netifEntry * foundEntry = 0;
        !           135: 
        !           136:     if (!netif) return false;
        !           137: 
        !           138:     NETIF_LOCK;
        !           139:     if (!queue_empty(&netifTable)) {
        !           140:         netifEntry * entry;
        !           141:         queue_iterate(&netifTable, entry, netifEntry *, link) {
        !           142:             if (entry->netif == netif) {
        !           143:                 foundEntry = entry;
        !           144:                 break;
        !           145:             }
        !           146:         }
        !           147:     }
        !           148:     if (foundEntry) {
        !           149:         queue_remove(&netifTable, foundEntry, netifEntry *, link);
        !           150:         IOFree(foundEntry, sizeof(*foundEntry));
        !           151:     }
        !           152:     NETIF_UNLOCK;
        !           153: 
        !           154:     return (foundEntry ? true : false);
        !           155: }
        !           156: 
        !           157: // --------------------------------------------------------------------------
        !           158: //
        !           159: // Initialize the table, and preload it with any existing BSD network
        !           160: // interfaces.
        !           161: //
        !           162: static void initNetifTable()
        !           163: {
        !           164:     netifTableLock = IOLockAlloc();
        !           165:     assert(netifTableLock);
        !           166: 
        !           167:     IOLockInitWithState(netifTableLock, kIOLockStateUnlocked);
        !           168: 
        !           169:     queue_init(&netifTable);
        !           170: 
        !           171:     // Insert entries for all existing 'BSD' network interfaces into the 
        !           172:     // netifTable. Hopefully only lo0 will be found.
        !           173:     //
        !           174: #if 1   // FreeBSD 3.2
        !           175:     for (struct ifnet * ifp = ifnet.tqh_first;
        !           176:          ifp;
        !           177:          ifp = ifp->if_link.tqe_next)
        !           178:         addNetworkInterfaceEntry(BSD_IFNET_ENTRY, ifp->if_name, ifp->if_unit);
        !           179: #else
        !           180:     for (struct ifnet * ifp = ifnet; ifp; ifp = ifp->if_next)
        !           181:         addNetworkInterfaceEntry(BSD_IFNET_ENTRY, ifp->if_name, ifp->if_unit);
        !           182: #endif
        !           183: }
        !           184: 
        !           185: // --------------------------------------------------------------------------
        !           186: //
        !           187: // Add a entry for the interface object 'netif', with name prefix 'name'.
        !           188: // The chosen unit number is returned in 'unit'. Returns true on success.
        !           189: //
        !           190: static bool reserveNetworkInterfaceEntry(IONetworkInterface * netif,
        !           191:                                          const char *         name,
        !           192:                                          short *              unit)
        !           193: {
        !           194:     bool ret = true;
        !           195:     bool addEntry = true;   // add new entry to list.
        !           196:     bool error = false;
        !           197: 
        !           198:     if (!netif || !name || !unit || (*unit < 0)) return false;
        !           199: 
        !           200:     NETIF_LOCK;
        !           201: 
        !           202:     if (!queue_empty(&netifTable)) {
        !           203:         bool rescan;
        !           204:         netifEntry * entry;
        !           205: 
        !           206:         do {
        !           207:             rescan = false;
        !           208:             
        !           209:             // Scan through the interface list and search for duplicates
        !           210:             // and conflicts. If a conflict is found, increment the unit
        !           211:             // number and rescan.
        !           212:             //
        !           213:             queue_iterate(&netifTable, entry, netifEntry *, link) {
        !           214:                 if (entry->netif == netif) {    // can't have duplicates
        !           215:                     addEntry = false;           // re-use existing entry
        !           216:                     *unit = entry->unit;
        !           217:                     break;
        !           218:                 }
        !           219:                 if ((entry->unit == *unit) && !strcmp(entry->name, name)) {
        !           220:                     // name conflict detected.
        !           221:                     if (++(*unit) > 0)
        !           222:                         rescan = true;
        !           223:                     else
        !           224:                         error = true;
        !           225:                     break;
        !           226:                 }
        !           227:             }
        !           228:         } while (rescan);
        !           229:     }
        !           230: 
        !           231:     if (error)
        !           232:         ret = false;
        !           233:     else if (addEntry)
        !           234:         ret = addNetworkInterfaceEntry(netif, name, *unit);
        !           235: 
        !           236:     NETIF_UNLOCK;
        !           237: 
        !           238:     return ret;
        !           239: }
        !           240: 
        !           241: // --------------------------------------------------------------------------
        !           242: //
        !           243: // IONetworkStack class initializer.
        !           244: 
        !           245: void IONetworkStack::initialize()
        !           246: {
        !           247:     initNetifTable();
        !           248: }
        !           249: 
        !           250: // --------------------------------------------------------------------------
        !           251: //
        !           252: // init method.
        !           253: 
        !           254: bool IONetworkStack::init(OSDictionary * properties)
        !           255: {
        !           256:     _netif = 0;     // IONetworkInterface instance (provider).
        !           257:     _ifp   = 0;     // ifnet struct for the interface.
        !           258:     _lock  = 0;     // big serialization lock.
        !           259:     _state = kIONetworkStackStateInit;  // default state.
        !           260: 
        !           261:     if (!super::init())
        !           262:         return false;
        !           263: 
        !           264:     // Allocate a lock which will protect all accesses to this object.
        !           265:     //
        !           266:     _lock = IOLockAlloc();
        !           267:     if (!_lock)
        !           268:         return false;
        !           269: 
        !           270:     return true;
        !           271: }
        !           272: 
        !           273: // --------------------------------------------------------------------------
        !           274: //
        !           275: // probe. the score forces the probe and start in IONetworkStack to occur
        !           276: // before the notification from IONetworkInterface is sent. We need to delay
        !           277: // that until the network stack object has assigned a BSD name to the
        !           278: // interface.
        !           279: 
        !           280: IOService * IONetworkStack::probe(IOService * provider,
        !           281:                                   SInt32 *    score)
        !           282: {
        !           283:     if (!super::probe(provider, score))
        !           284:         return 0;
        !           285: 
        !           286:     // We are not picky about our provider, but it must be an
        !           287:     // IONetworkInterface instance.
        !           288:     //
        !           289:     IONetworkInterface * netif = OSDynamicCast(IONetworkInterface, provider);
        !           290:     if (!netif)
        !           291:         return 0;
        !           292: 
        !           293:     *score = 32;    // must be larger than notification score.
        !           294:     
        !           295:     // Query interface for any requirements before qualifying the probe.
        !           296:     // For now, there is nothing that needs to be done. Return 'this' to
        !           297:     // indicate successful probe.
        !           298: 
        !           299:     return this;
        !           300: }
        !           301: 
        !           302: // --------------------------------------------------------------------------
        !           303: //
        !           304: // start method. We have attached to our provider, now start ourselve up.
        !           305: 
        !           306: bool IONetworkStack::start(IOService * provider)
        !           307: {
        !           308:     IONetworkInterface * netif = OSDynamicCast(IONetworkInterface, provider);
        !           309:     bool                 ret    = false;
        !           310:     bool                 opened = false;
        !           311: 
        !           312:     if (!netif) return false;
        !           313: 
        !           314:     LOCK;
        !           315: 
        !           316:     do {
        !           317:         // Catch illegal state transitions.
        !           318:         //
        !           319:         if (_state != kIONetworkStackStateInit)
        !           320:             break;
        !           321: 
        !           322:         // Our provider must reveal its ifnet structure.
        !           323:         //
        !           324:         _netif = netif;
        !           325:         _ifp   = _netif->getIfnet();
        !           326:         if (!_ifp || (_netif != (IONetworkInterface *) _ifp->if_private))
        !           327:             break;
        !           328: 
        !           329:         // Pass start() to our superclass.
        !           330:         //
        !           331:         if (!super::start(provider))
        !           332:             break;
        !           333: 
        !           334:         // Open our provider.
        !           335:         //
        !           336:         if (!_netif->open(this))
        !           337:             break;
        !           338:         opened = true;
        !           339: 
        !           340:         // Assign a name for the interface. Must do this before the
        !           341:         // if_attach() call. Remember to release the OSString object
        !           342:         // obtained through this call.
        !           343:         //
        !           344:         OSString * ifname = _assignInterfaceName(_netif);
        !           345:         if (!ifname) {
        !           346:             releaseNetworkInterfaceEntry(_netif);
        !           347:             break;
        !           348:         }
        !           349:         ifname->release();
        !           350: 
        !           351:         // When IONetworkStack gets probed, we assume that BSD is already
        !           352:         // up and running. So it is safe to call BSD to attach the network 
        !           353:         // interface.
        !           354:         //
        !           355:         // FIXME: This will only work with Ethernet interfaces. Switch to
        !           356:         // new DLIL API once that is available.
        !           357:         //
        !           358:         _netif->lock();
        !           359: 
        !           360:         // Set the if_free() function pointer in the ifnet to point to our
        !           361:         // detachCallBack() static function.
        !           362:         //
        !           363:         // _ifp->if_free  = detachCallBackHandler;
        !           364:         // _netif->_stack = this;
        !           365: 
        !           366: #if 1   // FreeBSD 3.2
        !           367:         bpfattach(_ifp, DLT_EN10MB,sizeof(struct ether_header));
        !           368: #else
        !           369:         bpfattach(&_ifp->if_bpf, _ifp, DLT_EN10MB,sizeof(struct ether_header));
        !           370: #endif  
        !           371: 
        !           372:         ether_ifattach(_ifp); 
        !           373:         
        !           374:         _netif->unlock();
        !           375: 
        !           376:         // Network stack is now attached to the interface.
        !           377:         //
        !           378:         _state = kIONetworkStackStateAttached;
        !           379: 
        !           380:         ret = true;
        !           381:     }
        !           382:     while (0);
        !           383: 
        !           384:     if (!ret)
        !           385:     {
        !           386:         // start failed, undo any actions performed.
        !           387:         //
        !           388:         if (opened)
        !           389:             _netif->close(this);
        !           390:         
        !           391:         _netif = 0;
        !           392:         _ifp   = 0;
        !           393:     }
        !           394: 
        !           395:     UNLOCK;
        !           396: 
        !           397:     return ret;
        !           398: }
        !           399: 
        !           400: // --------------------------------------------------------------------------
        !           401: //
        !           402: // stop method.
        !           403: 
        !           404: void IONetworkStack::stop(IOService * provider)
        !           405: {
        !           406:     LOCK;
        !           407: 
        !           408:     // Catch an illegal stop.
        !           409:     //
        !           410:     assert((_state == kIONetworkStackStateInit) ||
        !           411:            (_state == kIONetworkStackStateDetached));
        !           412: 
        !           413:     // Remove the interface from linked list.
        !           414:     //
        !           415:     if (_netif) {
        !           416:         assert(_netif == (IONetworkInterface *) provider);
        !           417:         releaseNetworkInterfaceEntry(_netif);
        !           418:     }
        !           419: 
        !           420:     _netif = 0;
        !           421:     _ifp   = 0;
        !           422:     _state = kIONetworkStackStateInit;
        !           423: 
        !           424:     UNLOCK;
        !           425:     
        !           426:     super::stop(provider);
        !           427: }
        !           428: 
        !           429: // --------------------------------------------------------------------------
        !           430: //
        !           431: // sendIfDetachRequest
        !           432: //
        !           433: // Handle a detach request from our provider and signal to the network stack 
        !           434: // that the interface wishes to detach. The network stack will callback when 
        !           435: // the interface is allowed to proceed with the detach. There is no hard
        !           436: // limit on how soon the callback will occur.
        !           437: //
        !           438: // Returns true if the request was handled. Otherwise, returns false.
        !           439: 
        !           440: bool IONetworkStack::sendIfDetachRequest()
        !           441: {
        !           442:     bool ret = false;
        !           443: 
        !           444:     DLOG("IONetworkStack::sendIfDetachRequest() called state = %d\n", _state);
        !           445: 
        !           446:     LOCK;
        !           447: 
        !           448:     if (_state == kIONetworkStackStateAttached) {
        !           449:     
        !           450:         // Send a detach request to the network stack and wait for
        !           451:         // a callback indicating detach operation complete.
        !           452:         //
        !           453:         // if_detach() is a new proposed DLIL call and does not exist yet.
        !           454: 
        !           455:         _state = kIONetworkStackStateDetaching;
        !           456: 
        !           457:         ret = true; // detach request handled.
        !           458:     }
        !           459:     
        !           460:     UNLOCK;
        !           461:     
        !           462:     return ret;
        !           463: }
        !           464: 
        !           465: // --------------------------------------------------------------------------
        !           466: //
        !           467: // ifDetachCallback method.
        !           468: 
        !           469: void IONetworkStack::ifDetachCallback()
        !           470: {
        !           471:     LOCK;
        !           472:     
        !           473:     if (_state == kIONetworkStackStateDetaching) {
        !           474:         
        !           475:         // We previously sent a detach request, the network stack is now
        !           476:         // calling back to indicate detach completion.
        !           477:         //
        !           478:         assert(_netif && _ifp);
        !           479: 
        !           480:         // Close our provider.
        !           481:         //
        !           482:         _netif->close(this);
        !           483:  
        !           484:         // Detach is now complete.
        !           485:         //
        !           486:         _state = kIONetworkStackStateDetached;
        !           487:     }
        !           488:     else {
        !           489:         DLOG("%s: Unexpected detach callback\n", getName());
        !           490:     }
        !           491: 
        !           492:     UNLOCK;
        !           493: }
        !           494: 
        !           495: // --------------------------------------------------------------------------
        !           496: //
        !           497: // This static member function is registered as the if_free() handler in
        !           498: // the ifnet structure of our provider. The IONetworkStack instance is 
        !           499: // discovered and its ifFreeCallback() method is called.
        !           500: 
        !           501: void IONetworkStack::ifDetachCallbackHandler(struct ifnet * ifp)
        !           502: {
        !           503:     IONetworkInterface *    netif;
        !           504:     IONetworkStack *        stack;
        !           505:     
        !           506:     netif = OSDynamicCast(IONetworkInterface,
        !           507:                           (IONetworkInterface *) ifp->if_private);
        !           508:     assert(netif);
        !           509: 
        !           510:     netif->lockForArbitration();
        !           511:     
        !           512:     stack = (IONetworkStack *) netif->_client;
        !           513:     if (stack)
        !           514:         stack->ifDetachCallback();
        !           515:     else
        !           516:         DLOG("IONetworkStack: No target for ifDetachCallback\n");
        !           517: 
        !           518:     netif->unlockForArbitration();
        !           519: }
        !           520: 
        !           521: // --------------------------------------------------------------------------
        !           522: //
        !           523: // Release allocated resources.
        !           524: 
        !           525: void IONetworkStack::free()
        !           526: {
        !           527:     assert(_state == kIONetworkStackStateInit);
        !           528: 
        !           529:     if (_lock)
        !           530:         IOLockFree(_lock);
        !           531: }
        !           532: 
        !           533: // --------------------------------------------------------------------------
        !           534: //
        !           535: // Facility provided by IOService for general purpose provider-to-client 
        !           536: // notification. We catch the kIOMessageServiceIsTerminated message.
        !           537: 
        !           538: IOReturn IONetworkStack::message(UInt32 type, IOService * provider,
        !           539:                                  void * argument = 0)
        !           540: {
        !           541:     // Our provider has gone into an inactive state, we should begin the
        !           542:     // tear-down process by signalling the network stack to unregister
        !           543:     // and detach the network interface.
        !           544:     //
        !           545:     // We do not look at the argument, which contains the options given
        !           546:     // to the terminate() method.
        !           547:     //
        !           548:     if (type == kIOMessageServiceIsTerminated) {
        !           549:         sendIfDetachRequest();
        !           550:         return kIOReturnSuccess;
        !           551:     }
        !           552:     
        !           553:     return kIOReturnUnsupported;
        !           554: }
        !           555: 
        !           556: // --------------------------------------------------------------------------
        !           557: //
        !           558: // Assign a BSD friendly name to the network interface. The interface
        !           559: // object has to assist in this process by returning its name prefix,
        !           560: // i.e. "en". This routine will pick an unit number that does not
        !           561: // conflict with any existing interface.
        !           562: 
        !           563: OSString * IONetworkStack::_assignInterfaceName(IONetworkInterface * netif)
        !           564: {
        !           565:     SInt16                  unit = 0;
        !           566:     UInt32                  index = 0;
        !           567:     const char *            namePrefix = netif->getNamePrefix();
        !           568:     char                    nameBuf[40];
        !           569:     OSString *              nameString;
        !           570:     IONetworkController *   ctlr = OSDynamicCast(IONetworkController, 
        !           571:                                                  netif->getProvider());
        !           572: 
        !           573:     if (!ctlr || !namePrefix || !*namePrefix)
        !           574:         return 0;
        !           575: 
        !           576:     // First, we need to determine the initial interface unit number.
        !           577:     // The current scheme needs a lot of work. Currently, motherboard
        !           578:     // devices gets unit 0, while add-on PCI cards are assigned
        !           579:     // unit 1 and up. Here, we need to determine whether this is an
        !           580:     // onboard or a PCI network controller.
        !           581:     //
        !           582:     if (ctlr->getProvider()) {
        !           583:             OSObject * propObject = ctlr->getProvider()->getProperty("built-in");
        !           584:         
        !           585:         if (!propObject) {
        !           586:             propObject = ctlr->getProvider()->getProperty("AAPL,slot-name");
        !           587:             if (propObject) {
        !           588:                 unit = 1;   // PCI add-on card
        !           589:                 
        !           590:                 // If we have an index number, increment
        !           591:                 // the unit by the index number.
        !           592:                 // (for multiport PCI cards).
        !           593:                 ctlr->doGetControllerIndex(this, &index);
        !           594:                 unit += index;
        !           595:             }       
        !           596:         }
        !           597:     }
        !           598: 
        !           599:     // "unit" is now the initial unit number requested by the interface.
        !           600:     // If this unit number is already taken by an existing interface, we
        !           601:     // will automatically increment the unit number until there are no 
        !           602:     // conflicts. We don't want to confuse BSD with identical names.
        !           603:     //
        !           604:     // Now try to reserve the chosen name.
        !           605:     //
        !           606:     if (!reserveNetworkInterfaceEntry(netif, namePrefix, &unit))
        !           607:         return 0;
        !           608: 
        !           609:     // Update the interface object with its assigned name.
        !           610:     //
        !           611:     sprintf(nameBuf, "%s%d", namePrefix, unit);
        !           612:     nameString = OSString::withCString(nameBuf);
        !           613:     if (nameString) {
        !           614:         //
        !           615:         // Now fill in the ifnet name fields.
        !           616:         //      
        !           617:         netif->setInterfaceNameInt(namePrefix);
        !           618:         netif->setUnitNumberInt(unit);
        !           619:         
        !           620:         // Set the interface's kIOBSDName property.
        !           621:         //
        !           622:         netif->setProperty(kIOBSDName, nameString);
        !           623:     }
        !           624: 
        !           625:     return nameString;
        !           626: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.