Annotation of XNU/bsd/netat/at.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 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) 1998 Apple Computer, Inc. 
        !            24:  */
        !            25: 
        !            26: /*     at.c
        !            27:  */
        !            28: 
        !            29: #include <sys/param.h>
        !            30: #include <sys/systm.h>
        !            31: #include <sys/ioctl.h>
        !            32: #include <sys/errno.h>
        !            33: #include <sys/malloc.h>
        !            34: #include <sys/socket.h>
        !            35: #include <sys/socketvar.h>
        !            36: 
        !            37: #include <net/if.h>
        !            38: #include <net/if_dl.h>
        !            39: #include <net/if_types.h>
        !            40: #include <net/etherdefs.h>
        !            41: #include <net/tokendefs.h>
        !            42: #include <net/dlil.h>
        !            43: 
        !            44: #include <netat/appletalk.h>
        !            45: #include <netat/sysglue.h>
        !            46: #include <netat/at_pcb.h>
        !            47: #include <netat/at_var.h>
        !            48: #include <netat/ddp.h>
        !            49: #include <netat/nbp.h>
        !            50: #include <netat/routing_tables.h>
        !            51: #include <netat/at_config.h>
        !            52: 
        !            53: extern int at_ioctl(struct atpcb *, u_long, caddr_t);
        !            54: extern int routerStart(at_kern_err_t *);
        !            55: extern void elap_offline(at_ifaddr_t *);
        !            56: extern at_ifaddr_t *find_ifID(char *);
        !            57: 
        !            58: extern int xpatcnt;
        !            59: extern at_ifaddr_t at_interfaces[];
        !            60: extern at_ifaddr_t *ifID_home;
        !            61: extern TAILQ_HEAD(name_registry, _nve_) name_registry;
        !            62: extern int nve_lock;
        !            63: 
        !            64: struct  etalk_addr      etalk_multicast_addr = {
        !            65:   {0x09, 0x00, 0x07, 0xff, 0xff, 0xff}};
        !            66: struct  etalk_addr      ttalk_multicast_addr = {
        !            67:   {0xC0, 0x00, 0x40, 0x00, 0x00, 0x00}};
        !            68: 
        !            69: /*
        !            70:   * Generic internet control operations (ioctl's).
        !            71:   * ifp is 0 if not an interface-specific ioctl.
        !            72:   */
        !            73: 
        !            74: int at_control(so, cmd, data, ifp)
        !            75:      struct socket *so;
        !            76:      u_long cmd;
        !            77:      caddr_t data;
        !            78:      struct ifnet *ifp;
        !            79: {
        !            80:        struct ifreq *ifr = (struct ifreq *)data;
        !            81:        int pat_id = 0, error = 0;
        !            82:        struct proc *p = current_proc();       
        !            83:        at_ifaddr_t *ifID = 0;
        !            84:        struct ifaddr *ifa;
        !            85:        struct sockaddr_dl *sdl;
        !            86: 
        !            87:        if (cmd == 0x2000ff99) {
        !            88:                /* *** this is a temporary hack to get at_send_to_dev() to
        !            89:                   work with BSD-style sockets instead of the special purpose 
        !            90:                   system calls, ATsocket() and ATioctl().
        !            91:                   *** */
        !            92:                if ((error = at_ioctl((struct atpcb *)so->so_pcb, cmd, data))) {
        !            93:                  if (((struct atpcb *)so->so_pcb)->proto != ATPROTO_LAP) {
        !            94:                    ((struct atpcb *)so->so_pcb)->proto = ATPROTO_LAP;
        !            95:                    error = at_ioctl((struct atpcb *)so->so_pcb, cmd, data);
        !            96:                  }
        !            97:                }
        !            98:                return(error);
        !            99: 
        !           100:                /* *** processing should be
        !           101:                   return(EINVAL);
        !           102:                   *** */
        !           103:        }
        !           104:         /*
        !           105:         * Find address for this interface, if it exists.
        !           106:         */
        !           107:        if (ifp)
        !           108:                for (pat_id = 0; pat_id < xpatcnt; pat_id++)
        !           109:                  if (at_interfaces[pat_id].aa_ifp == ifp) {
        !           110:                        ifID = &at_interfaces[pat_id];
        !           111:                        break;
        !           112:                  }
        !           113:        
        !           114:        switch (cmd) {
        !           115: 
        !           116:        case AIOCGETSTATE:
        !           117:          {
        !           118:                at_state_t *global_state = (at_state_t *)data;
        !           119: 
        !           120:                *global_state = at_state;
        !           121:                return(0);
        !           122:                break;
        !           123:          }
        !           124: 
        !           125:        case AIOCGETIFCFG:
        !           126:          {
        !           127:                at_if_cfg_t *cfgp = (at_if_cfg_t *)data;
        !           128: 
        !           129:                ifID = 0;
        !           130:                if ((at_state.flags & AT_ST_STARTED) &&
        !           131:                    ifID_home) {
        !           132:                        if (strlen(cfgp->ifr_name)) {
        !           133:                                TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) {
        !           134:                                        if (!strncmp(ifID->ifName, cfgp->ifr_name, 
        !           135:                                                     strlen(ifID->ifName)))
        !           136:                                                break;
        !           137:                                }
        !           138:                        } else {
        !           139:                                ifID = ifID_home;
        !           140:                                strncpy(cfgp->ifr_name, ifID->ifName, 
        !           141:                                        sizeof(ifID->ifName));
        !           142:                        }
        !           143:                        if  (ifID && ifID->ifState != LAP_OFFLINE) {
        !           144:                                cfgp->flags = ifID->ifFlags;
        !           145:                                /* put the IF state into the low order 
        !           146:                                   bits of flags */
        !           147:                                cfgp->flags |= (ifID->ifState & LAP_STATE_MASK);
        !           148:                                cfgp->node = ifID->ifThisNode;
        !           149:                                cfgp->router = ifID->ifARouter;
        !           150:                                cfgp->netStart = ifID->ifThisCableStart;
        !           151:                                cfgp->netEnd = ifID->ifThisCableEnd;
        !           152:                                cfgp->zonename = ifID->ifZoneName;
        !           153:                                return(0);
        !           154:                        } else
        !           155:                                return(EINVAL);
        !           156:                } else
        !           157:                        return(ENOTREADY);
        !           158:                break;
        !           159:          }
        !           160: 
        !           161:        case AIOCSETDEFZONE:
        !           162:          {
        !           163:                at_def_zone_t *defzonep = (at_def_zone_t *)data;
        !           164: 
        !           165:                /* check for root access */
        !           166:                if (error = suser(p->p_ucred, &p->p_acflag))
        !           167:                        return(EACCES);
        !           168: 
        !           169:                ifID = 0;
        !           170:                if ((at_state.flags & AT_ST_STARTED) && ifID_home) {
        !           171:                        if (strlen(defzonep->ifr_name)) {
        !           172:                            TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) {
        !           173:                                if (!strncmp(ifID->ifName, defzonep->ifr_name, 
        !           174:                                             strlen(ifID->ifName)))
        !           175:                                    break;
        !           176:                            }
        !           177:                        } else {
        !           178:                                ifID = ifID_home;
        !           179:                                strncpy(defzonep->ifr_name, ifID->ifName, 
        !           180:                                        sizeof(ifID->ifName));
        !           181:                        }
        !           182: 
        !           183:                        /* In routing mode the default zone is only set for the 
        !           184:                           default interface. */
        !           185:                        if (ROUTING_MODE && (ifID != ifID_home))
        !           186:                                return(EINVAL);
        !           187: 
        !           188:                        if  (ifID && ifID->ifState != LAP_OFFLINE) {
        !           189:                                if (zonename_equal(&ifID->ifZoneName, 
        !           190:                                                   &defzonep->zonename)) 
        !           191:                                        return(0);
        !           192:                                else {
        !           193:                                        /* check the zone name */
        !           194:                                        if (MULTIPORT_MODE) {
        !           195:                                          short zno;
        !           196:                                          char ifs_in_zone[IF_TOTAL_MAX];
        !           197: 
        !           198:                                          if (!(zno = zt_find_zname(&defzonep->zonename)))
        !           199:                                            return(EINVAL);
        !           200: 
        !           201:                                          getIfUsage(zno-1, ifs_in_zone);
        !           202:                                          if (!ifs_in_zone[ifID->ifPort]) 
        !           203:                                            return(EINVAL);
        !           204:                                          ifID->ifDefZone = zno+1;
        !           205:                                        } else {
        !           206:                                          int i;
        !           207:                                          at_nvestr_t *zone;
        !           208: 
        !           209:                                          for (i = 0, zone = getSPLocalZone(i); 
        !           210:                                               zone; 
        !           211:                                               i++, zone = getSPLocalZone(i)) {
        !           212:                                            if (zonename_equal(zone, 
        !           213:                                                               &defzonep->zonename))
        !           214:                                              break;
        !           215:                                          }
        !           216:                                          if (!zone)
        !           217:                                            return(EINVAL);
        !           218:                                        }
        !           219:                                        ifID->ifZoneName = defzonep->zonename;
        !           220:                                        (void)regDefaultZone(ifID);
        !           221:                                        return(0);
        !           222:                                }
        !           223:                        } else
        !           224:                                return(EINVAL);
        !           225:                } else
        !           226:                        return(ENOTREADY);
        !           227:                break;
        !           228:          }
        !           229: 
        !           230:        case AIOCNBPREG:
        !           231:          {
        !           232:                at_nbp_reg_t *nbpP = (at_nbp_reg_t *)data;
        !           233:                nve_entry_t nve;
        !           234:                int error;
        !           235: 
        !           236:                if (!(at_state.flags & AT_ST_STARTED) || !ifID_home)
        !           237:                        return(ENOTREADY);
        !           238: 
        !           239:                /* multihoming mode */
        !           240:                if (MULTIHOME_MODE) {
        !           241:                        return(nbp_mh_reg(nbpP));
        !           242:                }
        !           243: 
        !           244:                /* single port mode or router mode */
        !           245:                if (nbp_fillin_nve(&nbpP->name, &nve) != 0) {
        !           246:                        /* bad tuple... */
        !           247:                        return(EINVAL);
        !           248:                }
        !           249: 
        !           250:                /* In routing mode when the zone is specified, we need to 
        !           251:                   find an interface on which the specified zone is seeded, so
        !           252:                   that the zone multicast will be plausible. */
        !           253:                if (ROUTING_MODE && !(DEFAULT_ZONE(&nve.zone))) {
        !           254:                        /* find first segment (interface) which is seeded for 
        !           255:                           this zone */
        !           256:                        int finished = FALSE;
        !           257:                        int zno;
        !           258:                        char ifs_in_zone[IF_TOTAL_MAX];
        !           259:                        if (!(zno = zt_find_zname(&nve.zone))) {
        !           260:                                return(EINVAL);
        !           261:                        }
        !           262:                        getIfUsage(zno-1, ifs_in_zone);
        !           263: 
        !           264:                        TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) {
        !           265:                                if (!ifs_in_zone[ifID->ifPort]) 
        !           266:                                                /* zone doesn't match */
        !           267:                                        continue;
        !           268:                                else
        !           269:                                        finished = TRUE;
        !           270:                        }
        !           271:                        if (!finished)
        !           272:                                return(EINVAL);
        !           273:                } else 
        !           274:                        ifID = ifID_home;
        !           275: 
        !           276:                nve.address.net = ifID->ifThisNode.s_net;
        !           277:                nve.address.node = ifID->ifThisNode.s_node;
        !           278:                nve.address.socket = nbpP->addr.socket;
        !           279:                nve.ddptype = nbpP->ddptype;
        !           280: 
        !           281:                if (nbp_find_nve(&nve))
        !           282:                        return(EADDRNOTAVAIL);
        !           283: 
        !           284:                /* Normal case; no tuple found for this name, so insert
        !           285:                 * this tuple in the registry and return ok response.
        !           286:                 */
        !           287:                ATDISABLE(nve_lock, NVE_LOCK);
        !           288:                if ((error = nbp_new_nve_entry(&nve, ifID)) == 0) {
        !           289:                        nbpP->addr.net = ifID->ifThisNode.s_net;
        !           290:                        nbpP->addr.node = ifID->ifThisNode.s_node;
        !           291:                        nbpP->unique_nbp_id = nve.unique_nbp_id;
        !           292:                }
        !           293:                ATENABLE(nve_lock, NVE_LOCK);
        !           294: 
        !           295:                return(error);
        !           296:                break;
        !           297:          }
        !           298: 
        !           299:        case AIOCNBPREMOVE:
        !           300:          {
        !           301:                at_nbp_reg_t *nbpP = (at_nbp_reg_t *)data;
        !           302:                nve_entry_t    *nve_entry, nve;
        !           303: 
        !           304:                if (!(at_state.flags & AT_ST_STARTED))
        !           305:                        return(ENOTREADY);
        !           306: 
        !           307:                /* delete by id */
        !           308:                if (nbpP->unique_nbp_id) {
        !           309:                        ATDISABLE(nve_lock, NVE_LOCK);
        !           310:                        TAILQ_FOREACH(nve_entry, &name_registry, nve_link) {
        !           311:                                if (nve_entry->unique_nbp_id == nbpP->unique_nbp_id) {
        !           312:                                        /* Found a match! */
        !           313:                                        nbp_delete_entry(nve_entry);
        !           314:                                        ATENABLE(nve_lock, NVE_LOCK);
        !           315:                                        return(0);
        !           316:                                }
        !           317:                        }
        !           318:                        ATENABLE(nve_lock, NVE_LOCK);
        !           319:                        return(EADDRNOTAVAIL);
        !           320:                }
        !           321: 
        !           322:                /* delete by entity */
        !           323:                if (nbp_fillin_nve(&nbpP->name, &nve) != 0) {
        !           324:                        /* bad tuple... */
        !           325:                        return(EINVAL);
        !           326:                }
        !           327: 
        !           328:                if (MULTIHOME_MODE && DEFAULT_ZONE(&nbpP->name.zone)) {
        !           329:                        /* if mhome & *, remove nve from all default zones */
        !           330:                        int found = FALSE;      /* if any found & deleted */
        !           331: 
        !           332:                        TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) {
        !           333:                                nve.zone = ifID->ifZoneName;
        !           334:                                nve.zone_hash = nbp_strhash(&nve.zone);
        !           335:                                if ((nve_entry = nbp_find_nve(&nve)) == NULL) 
        !           336:                                        continue;
        !           337: 
        !           338:                                ATDISABLE(nve_lock, NVE_LOCK);
        !           339:                                nbp_delete_entry(nve_entry);
        !           340:                                ATENABLE(nve_lock, NVE_LOCK);
        !           341:                                found = TRUE;
        !           342:                        }
        !           343:                        if (found) 
        !           344:                                return(0);
        !           345:                        else
        !           346:                                return(EADDRNOTAVAIL);
        !           347:                }
        !           348: 
        !           349:                if ((nve_entry = nbp_find_nve(&nve)) == NULL)
        !           350:                        /* Can't find the tuple we're looking for, send error*/
        !           351:                        return(EADDRNOTAVAIL);
        !           352: 
        !           353:                /* Normal case; tuple found for this name, so delete
        !           354:                 * the entry from the registry and return ok response.
        !           355:                 */
        !           356:                ATDISABLE(nve_lock, NVE_LOCK);
        !           357:                nbp_delete_entry(nve_entry);
        !           358:                ATENABLE(nve_lock, NVE_LOCK);
        !           359:                return(0);
        !           360: 
        !           361:                break;
        !           362:          }
        !           363: 
        !           364:        case AIOCSETROUTER:
        !           365:          {
        !           366:                at_router_params_t *rt = (at_router_params_t *)data;
        !           367: 
        !           368:                /* check for root access */
        !           369:                if (error = suser(p->p_ucred, &p->p_acflag))
        !           370:                        return(EACCES);
        !           371: 
        !           372:                /* when in routing/multihome mode the AIOCSETROUTER IOCTL 
        !           373:                   is done first */
        !           374:                if (at_state.flags & AT_ST_STARTED)
        !           375:                        return(EALREADY);
        !           376: 
        !           377:                /* Setup the routing & zip table size for the router */
        !           378:                if (rt->rtmp_table_sz >= RT_MIN && rt->rtmp_table_sz <= RT_MAX)
        !           379:                        RT_maxentry = rt->rtmp_table_sz;
        !           380:                else
        !           381:                        RT_maxentry = RT_DEFAULT;
        !           382: 
        !           383:                if (rt->zone_table_sz >= ZT_MIN && rt->zone_table_sz <= ZT_MAX)
        !           384:                        ZT_maxentry = rt->zone_table_sz;
        !           385:                else
        !           386:                        ZT_maxentry = ZT_DEFAULT;
        !           387: 
        !           388:                if (rt_table_init() == ENOBUFS)
        !           389:                        return(ENOBUFS);
        !           390: 
        !           391:                if (rt->router_mix)
        !           392:                        RouterMix = (int)rt->router_mix;
        !           393:                else
        !           394:                        RouterMix = RT_MIX_DEFAULT;
        !           395: 
        !           396:                add_ddp_handler(RTMP_SOCKET, rtmp_router_input);
        !           397: 
        !           398:                if (rt->multihome)
        !           399:                        at_state.flags |= AT_ST_MULTIHOME;
        !           400:                else
        !           401:                        at_state.flags |= AT_ST_ROUTER;
        !           402:                break;
        !           403:          }
        !           404:        case AIOCSTARTROUTER:
        !           405:          {
        !           406:                at_kern_err_t *keP = (at_kern_err_t *)data;
        !           407: 
        !           408:                /* check for root access */
        !           409:                if (suser(p->p_ucred, &p->p_acflag))
        !           410:                        return(EACCES);
        !           411: 
        !           412:                if (!(at_state.flags & AT_ST_STARTED))
        !           413:                        return(ENOTREADY);
        !           414: 
        !           415:                bzero(keP, sizeof(at_kern_err_t));
        !           416:                error = routerStart(keP);
        !           417: 
        !           418:                break;
        !           419:          }
        !           420:        case AIOCGETROUTER:
        !           421:          {
        !           422:                at_router_params_t *rt = (at_router_params_t *)data;
        !           423: 
        !           424:                if (!(at_state.flags & AT_ST_STARTED))
        !           425:                        return(ENOTREADY);
        !           426: 
        !           427:                rt->multihome = (MULTIHOME_MODE)? 1: 0;
        !           428:                rt->rtmp_table_sz = RT_maxentry;
        !           429:                rt->zone_table_sz = ZT_maxentry;
        !           430:                rt->router_mix = RouterMix;
        !           431: 
        !           432:                break;
        !           433:          }
        !           434:        case AIOCSTOPATALK:
        !           435:                /* check for root access */
        !           436:                if (error = suser(p->p_ucred, &p->p_acflag))
        !           437:                        return(EACCES);
        !           438: 
        !           439:                ddp_shutdown();
        !           440:                break;
        !           441: 
        !           442:        case SIOCSIFADDR:
        !           443:                /* check for root access */
        !           444:                if (error = suser(p->p_ucred, &p->p_acflag))
        !           445:                        error = EACCES;
        !           446:                else if (ifID)
        !           447:                        error = EEXIST;
        !           448:                else {
        !           449:                        int s;
        !           450:                        if (xpatcnt == 0) {
        !           451:                                at_state.flags |= AT_ST_STARTED;
        !           452:                                ddp_brt_init();
        !           453:                        }
        !           454: 
        !           455:                        /* *** find an empty entry *** */
        !           456:                        ifID = &at_interfaces[xpatcnt];
        !           457:                        bzero((caddr_t)ifID, sizeof(at_ifaddr_t));
        !           458:                        strncpy(ifID->ifName, ifr->ifr_name, sizeof(ifID->ifName));
        !           459: 
        !           460:                        ifID->aa_ifp = ifp;
        !           461:                        ifa = &ifID->aa_ifa;
        !           462:                        TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 
        !           463:                                if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&
        !           464:                                      (sdl->sdl_family == AF_LINK)) {
        !           465:                                    bcopy(LLADDR(sdl), ifID->xaddr, sizeof(ifID->xaddr));
        !           466: #ifdef APPLETALK_DEBUG
        !           467:                                    kprintf("SIOCSIFADDR: local enet address is %x.%x.%x.%x.%x.%x\n", 
        !           468:                                            ifID->xaddr[0], ifID->xaddr[1], 
        !           469:                                            ifID->xaddr[2], ifID->xaddr[3], 
        !           470:                                            ifID->xaddr[4], ifID->xaddr[5]);
        !           471: #endif
        !           472:                                    break;
        !           473:                                  }
        !           474: 
        !           475:                        /* attach the AppleTalk address to the ifnet structure */
        !           476:                        ifa = &ifID->aa_ifa;
        !           477:                        ifa->ifa_addr = (struct sockaddr *)&ifID->ifNodeAddress;
        !           478:                        ifID->ifNodeAddress.sat_len = sizeof(struct sockaddr_at);
        !           479:                        ifID->ifNodeAddress.sat_family =  AF_APPLETALK;
        !           480:                        /* the address itself will be filled in when ifThisNode
        !           481:                           is set */
        !           482:                        s = splnet();
        !           483:                        TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
        !           484:                        splx(s);
        !           485: 
        !           486:                        switch (ifp->if_type) {
        !           487:                        case IFT_ETHER:
        !           488:                                /* Check if a tag was already registered for AppleTalk */
        !           489:                                error = dlil_find_dltag(ifp->if_family, ifp->if_unit,
        !           490:                                                        PF_APPLETALK, &ifID->at_dl_tag);
        !           491:                          
        !           492:                                ifID->aarp_dl_tag = ifID->at_dl_tag; /*both tags are the same right now */
        !           493: 
        !           494: #ifdef APPLETALK_DEBUG
        !           495:                                kprintf("atcontrol: ifp=%s%u find_dltag returns=%d dl_tag=%d\n",
        !           496:                                        ifp->if_name, ifp->if_unit, error, ifID->at_dl_tag);
        !           497: #endif
        !           498:                                if (error == EPROTONOSUPPORT) {
        !           499:                                        ether_attach_at(ifp, &ifID->at_dl_tag, 
        !           500:                                          &ifID->aarp_dl_tag);
        !           501:                                        error = 0;
        !           502:                                }
        !           503:                                ifID->cable_multicast_addr = etalk_multicast_addr;
        !           504: 
        !           505:                                xpatcnt++;
        !           506:                                break;
        !           507:                        case IFT_FDDI:
        !           508:                                ifID->cable_multicast_addr = etalk_multicast_addr;
        !           509:                                ddp_bit_reverse(&ifID->cable_multicast_addr);
        !           510:                                xpatcnt++;
        !           511:                                break;
        !           512:                        case IFT_ISO88025: /* token ring */     
        !           513:                                ifID->cable_multicast_addr = ttalk_multicast_addr;
        !           514:                                ddp_bit_reverse(&ifID->cable_multicast_addr);
        !           515: 
        !           516:                                xpatcnt++;
        !           517:                                break;
        !           518:                        default:
        !           519:                                error = EINVAL;
        !           520:                        }
        !           521: 
        !           522:                        /* *** if (!error) make entry in if_types[] *** */
        !           523:                }
        !           524:          break;
        !           525: 
        !           526:        /* complete the initialization started in SIOCSIFADDR */
        !           527:        case AIOCSIFADDR:
        !           528:          {
        !           529:                at_if_cfg_t *cfgp = (at_if_cfg_t *)data;
        !           530: 
        !           531:                if (!(at_state.flags & AT_ST_STARTED))
        !           532:                        return(ENOTREADY);
        !           533:  
        !           534:                if (!(ifID = find_ifID(cfgp->ifr_name)))
        !           535:                        return(EINVAL);
        !           536: 
        !           537:                return(lap_online(ifID, cfgp));
        !           538:                break;
        !           539:          }
        !           540: 
        !           541: #ifdef NOT_YET
        !           542:        /* *** this can't be added until AT can handle dynamic addition and
        !           543:               deletion of interfaces *** */
        !           544:        case SIOCDIFADDR:
        !           545:                /* check for root access */
        !           546:                if (error = suser(p->p_ucred, &p->p_acflag))
        !           547:                        error = EACCES;
        !           548:                else if (!ifID) 
        !           549:                        error = EINVAL;
        !           550:                else
        !           551:                        elap_offline(ifID);
        !           552:                break;
        !           553: #endif
        !           554:        default:
        !           555:                if (ifp == 0 || ifp->if_ioctl == 0)
        !           556:                        return (EOPNOTSUPP);
        !           557:                return dlil_ioctl(0, ifp, cmd, (caddr_t) data);
        !           558:        }
        !           559: 
        !           560:        return(error);
        !           561: }

unix.superglobalmegacorp.com

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